.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$VBD30$
.tt 2 $$$
.tt 3 $JuergenP$treehandling$$$$2000-10-04$
***********************************************************
.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  : treehandling
=========
.sp
Purpose : - general tree operations
          - tree operations managing primary data
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        PROCEDURE
              b30cappend_to_tree (
                    VAR rk       : tgg00_Lkey;
                    VAR b        : tgg00_Rec;
                    VAR tree_pos : tgg00_FilePos;
                    VAR current  : tbd_current_tree);
 
        PROCEDURE
              b30cget_result_leaf (
                    VAR rk          : tgg00_Lkey;
                    get_next        : boolean;
                    prepare_for_upd : boolean;
                    VAR tree_pos    : tgg00_FilePos;
                    VAR nptr        : tbd_node_ptrs;
                    VAR current     : tbd_current_tree);
 
        PROCEDURE
              b30cnext_from_tree (
                    VAR rk         : tgg00_Lkey;
                    VAR set_result : tgg00_BdSetResultRecord;
                    VAR tree_pos   : tgg00_FilePos;
                    VAR b          : tsp00_MoveObj;
                    VAR current    : tbd_current_tree);
 
        PROCEDURE
              b30cprev_from_tree (
                    VAR rk         : tgg00_Lkey;
                    VAR set_result : tgg00_BdSetResultRecord;
                    VAR tree_pos   : tgg00_FilePos;
                    VAR b          : tsp00_MoveObj;
                    VAR current    : tbd_current_tree);
 
        PROCEDURE
              bd30CheckDatabase (
                    VAR t                        : tgg00_TransContext;
                    VAR bad_index_cnt            : tsp00_Int4;
                    VAR total_bad_cnt            : tsp00_Int4;
                    VAR verify_error             : tgg00_BasisError;
                    bWithUpdate                  : boolean;
                    bWithExtendedCheck           : boolean;
                    bWithIndexes                 : boolean;
                    bWithDeleteUnreferencedBlobs : boolean;
                    max_server                   : integer);
 
        PROCEDURE
              b30fdir_to_treeid (VAR fi : tbd_fileinfo;
                    VAR file_id : tgg00_FileId);
 
        PROCEDURE
              b30init_load (VAR rightmost_leaf : tsp00_PageNo;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b30load_table (VAR lnptr : tbd_node_ptrs;
                    VAR nptr           : tbd_node_ptrs;
                    only_left          : boolean;
                    VAR current        : tbd_current_tree);
 
        PROCEDURE
              b30new_tree (VAR fi : tbd_fileinfo;
                    VAR current   : tbd_current_tree);
 
        PROCEDURE
              bd30AddFileState (
                    VAR current : tbd_current_tree;
                    fileState   : tbd_file_state_set);
 
        PROCEDURE
              bd30AddToTempTree (
                    bCountDuplicates : boolean;
                    VAR rec          : tgg00_Rec;
                    VAR current      : tbd_current_tree);
 
        PROCEDURE
              bd30AddToTree (
                    VAR recKey    : tgg00_Lkey;
                    VAR rec       : tgg00_Rec;
                    VAR current   : tbd_current_tree);
 
        PROCEDURE
              bd30AddToTreeWithSpecialKey (
                    VAR recKey  : tgg00_Lkey;
                    VAR rec     : tgg00_Rec;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30AddToTreeWithBeforeImage (
                    VAR recKey  : tgg00_Lkey;
                    VAR rec     : tgg00_Rec;
                    VAR m       : tgg00_MessBlock;
                    pInsertCmd  : tsp00_Addr;
                    grantedLock : tgg00_LockReqMode;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30AddToTreeWithBeforeImageAndSpecialKey (
                    VAR recKey  : tgg00_Lkey;
                    VAR rec     : tgg00_Rec;
                    VAR m       : tgg00_MessBlock;
                    pInsertCmd  : tsp00_Addr;
                    grantedLock : tgg00_LockReqMode;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30BadFile (
                    VAR trans  : tgg00_TransContext;
                    VAR fileId : tgg00_FileId);
 
        PROCEDURE
              bd30BuildCurrent (
                    VAR trans   : tgg00_TransContext;
                    VAR fileId  : tgg00_FileId;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30CheckTree (
                    VAR trans           : tgg00_TransContext;
                    VAR fileId          : tgg00_FileId;
                    VAR treeStatistic   : tbd00_TreeStatistic;
                    longColCnt          : tsp00_Int2;
                    newLongColCnt       : tsp00_Int2;
                    bWithExtendedCheck  : boolean;
                    bCheckLongExistence : boolean;
                    bQuiet              : boolean;
                    bUpdateLeaves       : boolean);
 
        PROCEDURE
              bd30DelFromTree (
                    VAR recKey  : tgg00_Lkey;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30DelGarbageFromTree (
                    VAR recKey    : tgg00_Lkey;
                    VAR current   : tbd_current_tree;
                    VAR wantedRef : tgg91_PageRef);
 
        PROCEDURE
              bd30DelFromTreeWithBeforeImage (
                    VAR recKey  : tgg00_Lkey;
                    VAR oldRec  : tgg00_Rec;
                    VAR m       : tgg00_MessBlock;
                    pDeleteCmd  : tsp00_Addr;
                    grantedLock : tgg00_LockReqMode;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30DropTree (
                    VAR current     : tbd_current_tree;
                    longColumnCount : integer;
                    bOnlyEmpty      : boolean);
 
        PROCEDURE
              bd30ExistRecord (
                    VAR recKey  : tgg00_Lkey;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30FindLeaf (
                    VAR key     : tgg00_Lkey;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30GetFromTree (
                    VAR recKey  : tgg00_Lkey;
                    VAR rec     : tgg00_Rec;
                    VAR current : tbd_current_tree;
                    wantedLock  : tgg00_LockReqMode);
 
        PROCEDURE
              bd30GetFromTreeWithTreepos (
                    VAR recKey  : tgg00_Lkey;
                    VAR rec     : tgg00_Rec;
                    VAR tree_pos   : tgg00_FilePos;
                    VAR current : tbd_current_tree;
                    wantedLock  : tgg00_LockReqMode);
 
        PROCEDURE
              bd30GetNextLeafPage (
                    VAR nextLeafPage : tsp00_PageNo;
                    VAR nptr         : tbd_node_ptrs;
                    VAR current      : tbd_current_tree);
 
        PROCEDURE
              bd30GetNextLong (
                    VAR recKey      : tgg00_Lkey;
                    numberOfLongs   : integer;
                    VAR currentLong : integer;
                    VAR longFileId  : tgg00_FileId;
                    VAR filePos     : tgg00_FilePos;
                    VAR current     : tbd_current_tree);
 
        PROCEDURE
              bd30GetTree (
                    VAR trans            : tgg00_TransContext;
                    VAR fileId           : tgg00_FileId;
                    VAR current          : tbd_current_tree;
                    messType             : tgg00_MessType;
                    bLockTreeExcl        : boolean;
                    bSynchronizeTreeLock : boolean);
 
        PROCEDURE
              bd30GetSubTree (
                    VAR current : tbd_current_tree;
                    indexPageNo : tsp00_PageNo);
 
        PROCEDURE
              bd30MarkDeletedFromTree (
                    VAR recKey    : tgg00_Lkey;
                    VAR current   : tbd_current_tree;
                    markForDelete : boolean;
                    VAR beforeRef : tgg91_PageRef;
                    VAR updTrans  : tgg91_TransNo;
                    pRec          : tgg00_RecPtr);
 
        PROCEDURE
              bd30NextFromTree (
                    VAR recKey   : tgg00_Lkey;
                    bInclusive   : boolean;
                    bWithSQLLock : boolean;
                    VAR rec      : tgg00_Rec;
                    VAR current  : tbd_current_tree);
 
        PROCEDURE
              bd30NewTree (
                    VAR trans            : tgg00_TransContext;
                    VAR fileId           : tgg00_FileId;
                    VAR current          : tbd_current_tree;
                    bLockTreeExcl        : boolean;
                    bSynchronizeTreeLock : boolean);
 
        PROCEDURE
              bd30PrevFromTree (
                    VAR recKey   : tgg00_Lkey;
                    bInclusive   : boolean;
                    bWithSQLLock : boolean;
                    VAR rec      : tgg00_Rec;
                    VAR current  : tbd_current_tree);
 
        PROCEDURE
              bd30ReleaseTree (
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30ReleaseSubTree(
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30ReplaceInTree (
                    VAR recKey    : tgg00_Lkey;
                    VAR rec       : tgg00_Rec;
                    VAR current   : tbd_current_tree;
                    VAR beforeRef : tgg91_PageRef;
                    VAR updTrans  : tgg91_TransNo);
 
        PROCEDURE
              bd30ReplaceInTreeWithTreepos (
                    VAR rec      : tgg00_Rec;
                    VAR tree_pos : tgg00_FilePos;
                    VAR current  : tbd_current_tree);
 
        PROCEDURE
              bd30ReplaceInTreeWithBeforeImage (
                    VAR recKey  : tgg00_Lkey;
                    VAR oldRec  : tgg00_Rec;
                    VAR newRec  : tgg00_Rec;
                    VAR m       : tgg00_MessBlock;
                    pUpdateCmd  : tsp00_Addr;
                    grantedLock : tgg00_LockReqMode;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30ResetBadFile (
                    VAR trans  : tgg00_TransContext;
                    VAR fileId : tgg00_FileId);
 
        PROCEDURE
              bd30SearchRecord(
                    VAR current      : tbd_current_tree;
                    VAR recKey       : tsp00_Key (* ptocSynonym tsp00_KeyPtr *);
                    recKeyLen        : tsp00_Int4;
                    bLockLeafExcl    : boolean;
                    VAR nptr         : tbd_node_ptrs;
                    VAR recIndex     : tsp00_Int4;
                    VAR neighbs      : tbd_neighbors;
                    VAR searchResult : tbd_searchresult);
 
        PROCEDURE
              bd30SetReadOnly (
                    VAR trans  : tgg00_TransContext;
                    VAR fileId : tgg00_FileId);
 
        PROCEDURE
              bd30SetFileVersion (
                    VAR current    : tbd_current_tree;
                    newfileVersion : tgg91_FileVersion);
 
        PROCEDURE
              bd30SubFileState (
                    VAR current : tbd_current_tree;
                    fileState   : tbd_file_state_set);
 
        PROCEDURE
              bd30VerifyTree (
                    VAR trans          : tgg00_TransContext;
                    VAR fileId         : tgg00_FileId;
                    VAR treeStatistic  : tbd00_TreeStatistic;
                    bUpdateConverter   : boolean;
                    bWithExtendedCheck : boolean);
 
        PROCEDURE
              bd30InitFileIdForBlobFileIds;
 
        PROCEDURE
              bd30AddBlobIdFoundInFiledirectory  (
                    VAR trans : tgg00_TransContext;
                    BlobId : tgg00_Surrogate);
 
        PROCEDURE
              bd30AddBlobIdFoundInTable (
                    VAR trans : tgg00_TransContext;
                    BlobId : tgg00_Surrogate);
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
        FROM
              filesysteminterface_1 : VBD01;
 
        VAR
              b01downfilesystem : boolean;
              b01niltree_id     : tgg00_FileId;
              b01fullkey        : tsp00_Key;
 
        PROCEDURE
              b01pverify_participant (
                    VAR t              : tgg00_TransContext;
                    VAR file_id        : tgg00_FileId;
                    is_cold            : boolean;
                    bWithExtendedCheck : boolean);
 
        PROCEDURE
              bd01SetToNilCurrent(
                    VAR current : tbd_current_tree );
 
        PROCEDURE
              bd01CreatePermTableFile (
                    VAR trans    : tgg00_TransContext;
                    VAR fileId   : tgg00_FileId;
                    eFiletypeSet : tgg00_ExtendedFiletypeSet;
                    blobCount    : tsp00_Int2);
 
        PROCEDURE
              b01pdestroy_perm_file (VAR t : tgg00_TransContext;
                    VAR file_id : tgg00_FileId);
 
        PROCEDURE
              bd01DropLobFile (
                    VAR trans    : tgg00_TransContext;
                    VAR fileId   : tgg00_FileId;
                    parentFileNo : tgg00_Surrogate);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_2 : VBD02;
 
        PROCEDURE
              b02add_record (VAR t : tgg00_TransContext;
                    VAR file_id : tgg00_FileId;
                    VAR b       : tgg00_Rec                (*ptocConst*));
 
        PROCEDURE
              b02get_record (VAR t : tgg00_TransContext;
                    VAR file_id : tgg00_FileId;
                    VAR rk      : tgg00_Lkey               (*ptocConst*);
                    VAR b       : tgg00_Rec);
 
        PROCEDURE
              b02repl_record (VAR t : tgg00_TransContext;
                    VAR file_id : tgg00_FileId;
                    VAR b       : tgg00_Rec                (*ptocConst*));
 
        PROCEDURE
              b02next_record (VAR t : tgg00_TransContext;
                    VAR file_id : tgg00_FileId;
                    VAR rk      : tgg00_Lkey;
                    inclusive   : boolean;
                    VAR b       : tgg00_Rec);
 
      ------------------------------ 
 
        FROM
              error_text_handling : VBD06;
 
        PROCEDURE
              b06file_opmsg (
                    msg_no     : tsp00_Int4;
                    VAR fileId : tgg00_FileId);
 
        PROCEDURE
              b06dump_bad_page (pid : tsp00_TaskId;
                    page_type_flag : char;
                    file_ext       : tsp00_C4;
                    bad_pno        : tsp00_Int4;
                    buf_ptr        : tbd_nodeptr;
                    curr_buf_cnt   : integer);
 
        PROCEDURE
              b06write_filename_and_root (VAR file_id : tgg00_FileId);
 
        PROCEDURE
              bd06IllegalRootAccess (
                    VAR trans       : tgg00_TransContext;
                    VAR fileId      : tgg00_FileId;
                    bWriteBacktrace : boolean);
 
      ------------------------------ 
 
        FROM
              Trace : VBD120;
 
        PROCEDURE
              b120InsertTrace (VAR t   : tgg00_TransContext;
                    trace_layer  : tgg00_Debug;
                    trace_object : tgg00_VtraceType;
                    body_len     : tsp00_Int2;
                    trace_body   : tgg11_VtraceBodyPtr);
 
      ------------------------------ 
 
        FROM
              nodehandling : VBD13;
 
        PROCEDURE
              b13init_default_data_page (
                    VAR FileId  : tgg00_FileId;
                    Level       : tsp00_Int2;
                    NewPno      : tsp00_PageNo;
                    VAR Nptrs   : tbd_node_ptrs);
 
        PROCEDURE
              b13new_root (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b13r_release_node (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree;
                    lru_info    : tbd_lru_info);
 
        PROCEDURE
              b13w_release_node (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd13FreePnosAfterUnlock(VAR Current : tbd_current_tree);
 
        PROCEDURE
              bd13GetNode (VAR Current : tbd_current_tree;
                    Pno          : tsp00_PageNo;
                    PageLockMode : tbd00_PageLockMode;
                    NodeReq      : tbd_node_request;
                    VAR Nptrs    : tbd_node_ptrs);
 
        PROCEDURE
              bd13WriteExclusiveLockedRoot (
                    VAR Trans     : tgg00_TransContext;
                    VAR FileId    : tgg00_FileId;
                    VAR RootNptrs : tbd_node_ptrs );
 
        PROCEDURE
              bd13RReleaseRoot (VAR current : tbd_current_tree);
 
        PROCEDURE
              bd13WReleaseRoot (VAR current : tbd_current_tree);
 
        PROCEDURE
              bd13RReleaseSubRoot (VAR current : tbd_current_tree);
 
        PROCEDURE
              bd13WReleaseSubRoot (VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              filedirectory : VBD17;
 
        PROCEDURE
              b17fadd_file_state (
                    VAR t      : tgg00_TransContext;
                    VAR fileId : tgg00_FileId;
                    new_state  : tbd_file_state_set);
 
        PROCEDURE
              b17fsub_file_state (
                    VAR t      : tgg00_TransContext;
                    VAR fileId : tgg00_FileId;
                    subState   : tbd_file_state_set);
 
        PROCEDURE
              b17state_fdir (VAR fn : tgg00_Filename;
                    VAR fi          : tbd_fileinfo;
                    concurrent_file : boolean;
                    VAR t           : tgg00_TransContext);
 
        FUNCTION
              bd17GetBlobFdirRoot : tsp00_PageNo;
 
        PROCEDURE
              bd17GetNextBlob (
                    VAR trans    : tgg00_TransContext;
                    VAR filename : tgg00_Filename;
                    VAR fileInfo : tbd_fileinfo);
 
        PROCEDURE
              bd17GetBlobFileInfo (
                    VAR trans       : tgg00_TransContext;
                    VAR fileId      : tgg00_FileId;
                    VAR fileVersion : tgg91_FileVersion;
                    VAR fileState   : tbd_file_state_set);
 
      ------------------------------ 
 
        FROM
              systembufferinterface : VBD20;
 
        FUNCTION
              bd20IsPageExclusiveLocked (
                    pCBlock : tbd_nodeptr) : boolean;
 
      ------------------------------ 
 
        FROM
              leafhandling : VBD31;
 
        PROCEDURE
              b31add_to_leaf (VAR b : tgg00_Rec;
                    VAR nptr    : tbd_node_ptrs;
                    index       : integer;
                    left        : tsp00_PageNo;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b31del_from_leaf (VAR nptr : tbd_node_ptrs;
                    index       : integer;
                    left        : tsp00_PageNo;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b31get_from_leaf (VAR nptr : tbd_node_ptrs;
                    index        : integer;
                    with_kb_lock : boolean;
                    VAR b        : tgg00_Rec;
                    VAR current  : tbd_current_tree);
 
        PROCEDURE
              b31next_search (
                    VAR nptr    : tbd_node_ptrs;
                    VAR index   : integer;
                    VAR current : tbd_current_tree;
                    lruInfo     : tbd_lru_info );
 
        PROCEDURE
              b31nfill_recordbuffer (VAR nptr : tbd_node_ptrs;
                    VAR test_key   : tgg00_Lkey;
                    VAR tree_pos   : tgg00_FilePos;
                    VAR set_result : tgg00_BdSetResultRecord;
                    VAR b          : tsp00_MoveObj;
                    VAR current    : tbd_current_tree);
 
        PROCEDURE
              b31pfill_recordbuffer (VAR nptr : tbd_node_ptrs;
                    VAR test_key   : tgg00_Lkey;
                    VAR tree_pos   : tgg00_FilePos;
                    VAR set_result : tgg00_BdSetResultRecord;
                    VAR b          : tsp00_MoveObj;
                    VAR current    : tbd_current_tree);
 
        PROCEDURE
              bd31PrevSearch (
                    VAR recKey        : tsp00_Key;
                    keyLen            : tsp00_Int4;
                    VAR pNodes        : tbd_node_ptrs;
                    VAR recIndex      : integer;
                    VAR prevLeafPage  : tsp00_PageNo;
                    VAR current       : tbd_current_tree;
                    bGetLeafForUpdate : boolean);
 
        PROCEDURE
              b31repl_in_leaf (VAR b : tgg00_Rec;
                    VAR nptr    : tbd_node_ptrs;
                    index       : integer;
                    left        : tsp00_PageNo;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b31search_entry (VAR current : tbd_current_tree;
                    VAR rk     : tsp00_Key;
                    KeyLen     : tsp00_Int4;
                    VAR nptr   : tbd_nodeptr;
                    VAR index  : tsp00_Int4;
                    VAR result : tbd_searchresult);
 
        PROCEDURE
              b31t_append_to_temp_leaf (VAR b : tgg00_Rec;
                    VAR nptr     : tbd_node_ptrs;
                    VAR tree_pos : tgg00_FilePos;
                    VAR current  : tbd_current_tree);
 
        PROCEDURE
              b31t_prev_temp_search (VAR nptr : tbd_node_ptrs;
                    VAR index   : integer;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b31w_next_search (
                    VAR nptr    : tbd_node_ptrs;
                    VAR index   : integer;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd31AddToLeaf (VAR b : tgg00_Rec;
                    VAR nptr      : tbd_node_ptrs;
                    index         : integer;
                    left          : tsp00_PageNo;
                    VAR current   : tbd_current_tree;
                    useTransInfo  : boolean;
                    VAR beforeRef : tgg91_PageRef);
 
        PROCEDURE
              bd31AppendToLeaf (
                    VAR b           : tgg00_Rec;
                    VAR nptr        : tbd_node_ptrs;
                    index           : integer;
                    left            : tsp00_PageNo;
                    VAR current     : tbd_current_tree;
                    useTransInfo    : boolean;
                    VAR beforeRef   : tgg91_PageRef);
 
        PROCEDURE
              bd31ReplaceInLeaf (VAR b : tgg00_Rec;
                    VAR nptr      : tbd_node_ptrs;
                    index         : integer;
                    left          : tsp00_PageNo;
                    VAR current   : tbd_current_tree;
                    VAR beforeRef : tgg91_PageRef;
                    VAR updTrans  : tgg91_TransNo);
 
      ------------------------------ 
 
        FROM
              indexhandling : VBD50;
 
        PROCEDURE
              bd50CheckSubTree (
                    subRoot               : tsp00_PageNo;
                    right                 : tsp00_PageNo;
                    longColCnt            : tsp00_Int2;
                    newLongColCnt         : tsp00_Int2;
                    VAR scanCount         : tsp00_Int4;
                    VAR boundNeighborLeaf : tsp00_PageNo;
                    VAR bDumpParent       : boolean;
                    VAR bLongIsBad        : boolean;
                    VAR reEntranceKey     : tgg00_Lkey;
                    VAR checkKey          : tgg00_Lkey;
                    VAR current           : tbd_current_tree;
                    VAR treeStatistic     : tbd00_TreeStatistic;
                    bWithExtendedCheck    : boolean;
                    bCheckLongExistence   : boolean;
                    bUpdateLeaves         : boolean);
 
        PROCEDURE
              bd50DetermineLeafNode (
                    VAR current  : tbd_current_tree;
                    pSepKey      : tsp00_KeyAddr;
                    keyLen       : tsp00_Int4;
                    VAR recIndex : tsp00_Int4;
                    VAR leaf     : tsp00_PageNo;
                    VAR leftLeaf : tsp00_PageNo);
 
        PROCEDURE
              bd50DropSubTree (
                    root          : tsp00_PageNo;
                    numberOfLongs : integer;
                    bOnlyEmpty    : boolean;
                    VAR current   : tbd_current_tree);
 
        PROCEDURE
              bd50FindLeaf (
                    VAR sepKey          : tsp00_Key;
                    keyLen              : tsp00_Int4;
                    bLockLeafExcl       : boolean;
                    VAR nptrs           : tbd_node_ptrs;
                    VAR neighbs         : tbd_neighbors;
                    VAR recIndexForLeaf : tsp00_Int4;
                    VAR current         : tbd_current_tree);
 
        FUNCTION
              bd50IndexNodeIsSaveForDelete (
                    VAR current   : tbd_current_tree;
                    recIndex      : tsp00_Int4;
                    maximumKeyLen : tsp00_Int4) : boolean;
 
        FUNCTION
              bd50IndexNodeIsSaveForInsert (
                    VAR current   : tbd_current_tree;
                    recIndex      : tsp00_Int4;
                    newKeyLen     : tsp00_Int4;
                    maximumKeyLen : tsp00_Int4) : boolean;
 
        FUNCTION
              bd50IndexNodeIsSaveForReplace (
                    VAR current   : tbd_current_tree;
                    bIsGrowing    : boolean;
                    recIndex      : tsp00_Int4;
                    newKeyLen     : tsp00_Int4;
                    maximumKeyLen : tsp00_Int4) : boolean;
 
        PROCEDURE
              bd50VerifySubTree (
                    subRoot               : tsp00_PageNo;
                    right                 : tsp00_PageNo;
                    bUpdateConverter      : boolean;
                    bWithExtendedCheck    : boolean;
                    bCheckLongExistence   : boolean;
                    longColCnt            : tsp00_Int2;
                    VAR reEntranceKey     : tgg00_Lkey;
                    VAR checkKey          : tgg00_Lkey;
                    VAR boundNeighborLeaf : tsp00_PageNo;
                    VAR bDumpParent       : boolean;
                    VAR current           : tbd_current_tree;
                    VAR treeStatistic     : tbd00_TreeStatistic;
                    VAR scanCount         : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              branchhandling : VBD52;
 
        FUNCTION
              bd52SubtreePno (
                    VAR nptr : tbd_nodeptr;
                    RecIndex : tsp00_Int4) : tsp00_PageNo;
 
      ------------------------------ 
 
        FROM
              indexing : VBD53;
 
        PROCEDURE
              bd53NewLeafIndex (VAR Nptr : tbd_nodeptr;
                    VAR Nnptr        : tbd_nodeptr;
                    VAR NewSeparator : tgg00_Lkey;
                    t                : tgg00_TransContextPtr);
 
      ------------------------------ 
 
        FROM
              indexupdateorders : VBD54;
 
        PROCEDURE
              b54add_index (pSep       : tsp00_KeyAddr;
                    SepLen             : tsp00_Int4;
                    n_id               : tsp00_PageNo;
                    n_level            : tsp00_Int2;
                    VAR indexorderlist : tbd00_OrderList);
 
        PROCEDURE
              b54execute_indexorder (
                    VAR indexorderlist : tbd00_OrderList;
                    VAR current        : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              InvHandling : VBD300;
 
        PROCEDURE
              bd300FileIdRootCheck (VAR FileId  : tgg00_FileId;
                    VAR TrError : tgg00_BasisError);
 
        PROCEDURE
              bd300SetRootCheck (VAR FileId  : tgg00_FileId);
 
      ------------------------------ 
 
        FROM
              FileDir_Wrapper : VBD998;
 
        PROCEDURE
              bd998NewFileDirIterator (
                    VAR trans          : tgg00_TransContext;
                    VAR iteratorPtr    : tsp00_Addr);
 
        PROCEDURE
              bd998InitFileDirIterator (
                    VAR trans          : tgg00_TransContext;
                    showDeletedFiles   : boolean;
                    VAR iteratorPtr    : tsp00_Addr);
 
        PROCEDURE
              bd998AdvanceFileDirIterator (
                    VAR trans          : tgg00_TransContext;
                    VAR iteratorPtr    : tsp00_Addr;
                    VAR fileId         : tgg00_FileId);
 
        PROCEDURE
              bd998DestroyFileDirIterator (
                    VAR trans          : tgg00_TransContext;
                    VAR iteratorPtr    : tsp00_Addr);
 
        PROCEDURE
              bd998GetPageAndRecordCount (
                    VAR trans          : tgg00_TransContext;
                    VAR surrogate      : tgg00_Surrogate;
                    VAR leafPageCount  : tsp00_Int4;
                    VAR indexPageCount : tsp00_Int4;
                    VAR entryCount     : tsp00_Int4);
 
        PROCEDURE
              bd998GcGetFDirEntryFileinfo (
                    VAR transContext: tgg00_TransContext;
                    VAR filename    : tgg00_Filename;
                    VAR fileinfo    : tbd_fileinfo;
                    shared_file     : boolean);
 
        PROCEDURE
              bd998SetPageAndRecordCount (
                    VAR trans      : tgg00_TransContext;
                    VAR surrogate  : tgg00_Surrogate;
                    leafPageCount  : tsp00_Int4;
                    indexPageCount : tsp00_Int4;
                    entryCount     : tsp00_Int4);
 
        PROCEDURE
              bd998GetFileInfo(
                    VAR trans        : tgg00_TransContext;
                    VAR surrogate    : tgg00_Surrogate(*ptocConst*);
                    VAR fileId       : tgg00_FileId;
                    VAR fileVersion  : tgg91_FileVersion;
                    VAR fileState    : tbd_file_state_set);
 
        PROCEDURE
              bd998NewFileNo (
                    VAR file_no : tgg00_Surrogate);
 
        PROCEDURE
              bd998SetLobPageCount (
                    VAR trans     : tgg00_TransContext;
                    VAR surrogate : tgg00_Surrogate;
                    lobPageCount  : tsp00_Int4);
 
        FUNCTION
              bd998GetNewSysKeyForFile(
                    VAR trans     : tgg00_TransContext;
                    VAR tableSurr : tgg00_Surrogate(*ptocConst*);
                    VAR sysKey    : tgg00_Surrogate) : boolean;
 
        FUNCTION
              bd998AddAndGetNewSysKeyForFile(
                    VAR trans     : tgg00_TransContext;
                    VAR tableSurr : tgg00_Surrogate(*ptocConst*);
                    VAR sysKey    : tgg00_Surrogate) : boolean;
 
        PROCEDURE
              bd998GetExtendedFiletypeSet(
                    VAR trans        : tgg00_TransContext;
                    VAR surrogate    : tgg00_Surrogate(*ptocConst*);
                    VAR eFiletypeSet : tgg00_ExtendedFiletypeSet);
 
      ------------------------------ 
 
        FROM
              BD_Wrapper : VBD999;
 
        FUNCTION
              Data_GetRecLen(pRecord : tgg00_RecPtr) : integer;
 
        PROCEDURE
              bd999CopyRecord (
                    pRec                 : tgg00_RecPtr;
                    withTransHistoryInfo : boolean;
                    destSize             : tsp00_Int4;
                    pDest                : tsp00_Addr;
                    VAR destPos          : tsp00_Int4;
                    VAR e                : tgg00_BasisError);
 
        PROCEDURE
              bd999CopyRow (
                    VAR Source      : tgg00_Rec;
                    VAR Destination : tgg00_Rec;
                    VAR e           : tgg00_BasisError);
 
        PROCEDURE
              bd999CopyRecordAndTransHistoryInfo (
                    pRec                 : tgg00_RecPtr;
                    VAR transHistoryInfo : tgg00_ObjTransInfo;
                    VAR rec              : tgg00_Rec;
                    VAR e                : tgg00_BasisError);
 
        FUNCTION
              bd999GetTransHistoryInfo (
                    pRec : tsp00_BufAddr) : tgg00_ObjTransInfoPtr;
 
        FUNCTION
              bd999IsRowDeleted (
                    pRec : tsp00_BufAddr) : boolean;
 
        PROCEDURE
              bd999MarkRowDeleted (
                    VAR t         : tgg00_TransContext;
                    VAR node      : tbd_node;
                    pRec          : tgg00_RecPtr;
                    VAR beforeRef : tgg91_PageRef;
                    VAR updTrans  : tgg91_TransNo;
                    markDelete    : boolean);
 
        FUNCTION
              bd999PackRow (
                    VAR Source      : tgg00_Rec;
                    VAR Destination : tgg00_Rec) : tgg00_RecPtr;
 
        FUNCTION
              bd999UnpackRow (
                    VAR Source      : tgg00_Rec;
                    VAR Destination : tgg00_Rec) : tgg00_RecPtr;
 
      ------------------------------ 
 
        FROM
              RTE_kernel : VEN101;
 
        PROCEDURE
              vsleep (pid : tsp00_TaskId;
                    limit : tsp00_Int2);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01vtrace                : tgg00_VtraceState;
              g01glob                  : tgg00_KernelGlobals;
              g01ConsistentReadEnabled : boolean;
 
        PROCEDURE
              g01abort (msg_no : tsp00_Int4;
                    msg_label : tsp00_C8;
                    msg_text  : tsp00_C24;
                    bad_value : tsp00_Int4);
 
        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);
 
        PROCEDURE
              g01check (
                    msg_no     : tsp00_Int4;
                    msg_label  : tsp00_C8;
                    msg_text   : tsp00_C24;
                    bad_value  : tsp00_Int4;
                    constraint : boolean);
 
      ------------------------------ 
 
        FROM
              Select_Help_Procedures : VGG04;
 
        PROCEDURE
              g04locate_col (VAR st : tgg00_StackEntry;
                    rec_buf        : tgg00_RecPtr;
                    VAR varcol_pos : tgg00_VarColPosList;
                    VAR col_pos    : integer;
                    VAR col_len    : integer);
 
        FUNCTION
              g04inv_tfn (Tfn : tgg00_Tfn) : boolean;
 
      ------------------------------ 
 
        FROM
              GG_cpp_auxiliary_functions : VGG06;
 
        FUNCTION
              gg06IsNilRef (VAR PageRef : tgg91_PageRef): boolean;
 
        FUNCTION
              gg06Min (
                    value1 : tsp00_Int4;
                    value2 : tsp00_Int4 ) : tsp00_Int4;
 
        FUNCTION
              gg06PnoGet (VAR Cint4 : tgg90_Cint4): tsp00_Int4;
 
        PROCEDURE
              gg06PnoPut (VAR Cint4 : tgg90_Cint4; int4 : tsp00_Int4);
 
        PROCEDURE
              gg06SetNilRef (VAR PageRef : tgg91_PageRef);
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              SAPDB_PascalMove (
                    mod_id      : tsp00_C6;
                    mod_num     : tsp00_Int4;
                    source_upb  : tsp00_Int4;
                    dest_upb    : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    src_pos     : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    dest_pos    : tsp00_Int4;
                    length      : tsp00_Int4;
                    VAR e       : tgg00_BasisError);
 
      ------------------------------ 
 
        FROM
              GG_edit_routines : VGG17;
 
        PROCEDURE
              g17hexto_line (c : char;
                    VAR ln_len : integer;
                    VAR ln     : tsp00_C40);
 
        PROCEDURE
              g17nameto_line (n : tsp00_Name;
                    VAR ln_len  : integer;
                    VAR ln      : tsp00_C40);
 
        PROCEDURE
              g17trimint4_to_line (int : tsp00_Int4;
                    VAR ln_len : integer;
                    VAR ln     : tsp_c40);
 
        PROCEDURE
              g17basis_err_to_line (b_err : tgg00_BasisError;
                    VAR ln_len : integer;
                    VAR ln     : tsp00_C40);
 
      ------------------------------ 
 
        FROM
              KB_Logging : vkb560;
 
        FUNCTION
              kb560IsCatalogTable(
                    VAR tabId : tgg00_Surrogate) : boolean;
 
      ------------------------------ 
 
        FROM
              KB_ins_del_upd : VKB61;
 
        PROCEDURE
              k61bd_del (
                    VAR m                : tgg00_MessBlock;
                    pDeleteCmd           : tsp00_Addr;
                    VAR old_rec          : tgg00_Rec;
                    VAR transHistoryInfo : tgg00_ObjTransInfo;
                    granted_lock         : tgg00_LockReqMode);
 
        PROCEDURE
              k61bd_ins (
                    VAR m                : tgg00_MessBlock;
                    pInsertCmd           : tsp00_Addr;
                    VAR rec              : tgg00_Rec;
                    granted_lock         : tgg00_LockReqMode;
                    VAR TransHistoryInfo : tgg00_ObjTransInfo);
 
      ------------------------------ 
 
        FROM
              KB_InsDelUpd_interface : VKB611;
 
        PROCEDURE
              kb611ins_AssignBeforeImage (
                    pInsertCmd  : tsp00_Addr;
                    VAR Rec     : tgg00_Rec (*ptocConst*));
 
      ------------------------------ 
 
        FROM
              KB_update : VKB63;
 
        PROCEDURE
              k63bd_upd (VAR m           : tgg00_MessBlock;
                    pUpdateCmd           : tsp00_Addr;
                    VAR old_recbuf       : tgg00_Rec;
                    VAR new_recbuf       : tgg00_Rec;
                    granted_lock         : tgg00_LockReqMode;
                    VAR TransHistoryInfo : tgg00_ObjTransInfo);
 
      ------------------------------ 
 
        FROM
              KB_ServerTasks : VKB900;
 
        PROCEDURE
              kb900CreateCheckDataCoordinator(VAR trans : tgg00_TransContext;
                    VAR pCheckDataCoordinator : tsp00_Addr);
 
        PROCEDURE
              kb900ExecuteCheckDataJob(VAR trans : tgg00_TransContext;
                    pCheckDataCoordinator : tsp00_Addr;
                    VAR fileid            : tgg00_FileId;
                    bWithUpdate           : boolean;
                    bWithExtendedCheck    : boolean);
 
        PROCEDURE
              kb900WaitForAnyCheckDataJob(VAR trans : tgg00_TransContext;
                    pCheckDataCoordinator : tsp00_Addr;
                    VAR joberror          : tgg00_BasisError;
                    VAR errorRoot         : tsp00_PageNo);
 
        PROCEDURE
              kb900AbortCheckDataJobs(VAR trans : tgg00_TransContext;
                    pCheckDataCoordinator : tsp00_Addr);
 
        PROCEDURE
              kb900DeleteCheckDataCoordinator(VAR trans : tgg00_TransContext;
                    VAR pCheckDataCoordinator : tsp00_Addr);
 
      ------------------------------ 
 
        FROM
              RTE-Extension-30 : VSP30;
 
        PROCEDURE
              s30cmp (VAR buf1   : tsp00_MoveObj;
                    fieldpos1    : tsp00_Int4;
                    fieldlength1 : tsp00_Int4;
                    VAR buf2     : tgg00_Rec;
                    fieldpos2    : tsp00_Int4;
                    fieldlength2 : tsp00_Int4;
                    VAR l_result : tsp00_LcompResult);
 
        PROCEDURE
              s30cmp1 (VAR buf1  : tsp00_Key;
                    fieldpos1    : tsp00_Int4;
                    fieldlength1 : tsp00_Int4;
                    VAR buf2     : tgg00_RecBody;
                    fieldpos2    : tsp00_Int4;
                    fieldlength2 : tsp00_Int4;
                    VAR l_result : tsp00_LcompResult);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01basis_error (layer : tgg00_Debug;
                    nam   : tsp00_Sname;
                    b_err : tgg00_BasisError);
 
        PROCEDURE
              t01bool2 (
                    debug     : tgg00_Debug;
                    nam1      : tsp00_Sname (*ptocSynonym const char**);
                    bool1     : boolean;
                    nam2      : tsp00_Sname (*ptocSynonym const char**);
                    bool2     : boolean);
 
        PROCEDURE
              t01buf (debug  : tgg00_Debug;
                    VAR buf  : tgg00_Rec;
                    startpos : integer;
                    endpos   : integer);
 
        PROCEDURE
              t01int4 (debug : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int4     : tsp00_Int4);
 
        PROCEDURE
              t01key (
                    debug   : tgg00_Debug;
                    nam     : tsp00_Sname;
                    VAR k   : tgg00_Lkey);
 
        PROCEDURE
              t01surrogate (
                    debug     : tgg00_Debug;
                    nam       : tsp00_Sname (*ptocSynonym const char**);
                    VAR tabid : tgg00_Surrogate);
 
        PROCEDURE
              t01p2int4 (debug : tgg00_Debug;
                    nam_1 : tsp00_Sname;
                    int_1 : tsp00_Int4;
                    nam_2 : tsp00_Sname;
                    int_2 : tsp00_Int4);
&       endif
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
        PROCEDURE
              b06dump_bad_page;
 
              tbd_univ_ptr tbd_nodeptr
 
        FUNCTION
              bd20IsPageExclusiveLocked;
 
              tbd02_pDataCBlock tbd_nodeptr
 
        PROCEDURE
              bd999GetTransHistoryInfo;
 
              tgg00_RecPtr  tsp00_BufAddr
 
        PROCEDURE
              bd999IsRowDeleted;
 
              tgg00_RecPtr tsp00_BufAddr
 
        PROCEDURE
              g17hexto_line;
 
              tsp00_Line tsp00_C40
 
        PROCEDURE
              g17nameto_line;
 
              tsp00_Line tsp00_C40
 
        PROCEDURE
              g17trimint4_to_line;
 
              tsp00_Line tsp_c40
 
        PROCEDURE
              g17basis_err_to_line;
 
              tsp00_Line tsp00_C40
 
        PROCEDURE
              s30cmp;
 
              tsp00_MoveObj tgg00_Rec
 
        PROCEDURE
              s30cmp1;
 
              tsp00_MoveObj tsp00_Key
              tsp00_MoveObj tgg00_RecBody
 
        PROCEDURE
              t01buf;
 
              tsp00_Buf tgg00_Rec
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : JuergenP
.sp
.cp 3
Created : 1979-11-09
.sp
.cp 3
.sp
.cp 3
Release :      Date : 2000-10-04
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
 
Every (nonempty) file of the base file system is managed via
a B* tree.  B* trees are special storage and access structures
for the index sequential organization of dynamically changeable
files.  They feature
.sp ;.of 2
- rapid access during optional and sequential processing,
.sp ;.in ;.of 2
- efficient utilization of the secondary storage area and
.sp ;.in ;.of 2
- dynamic reorganization of the storage and access structure.
.sp ;.in
For the file management system described here, a B* tree variant is
used that is specially suited to managing files with the
following characteristics:
.sp
.of 2
- the length of file entries and entry keys can vary within
very wide margins
.sp ;.in ;.of 2
- the files change frequently (insertion, replacement and
deletion of records).
.sp 2;.cp 4
.in
In an indexed sequential file that is organized via a B* tree, the
data entries and the index are accomodated in blocks of a fixed
length, called pages or page frames.  The pages form the units that
are transferred between the main memory and the secondary storage.
At the same time, these units form the nodes of a tree structure.
The way in which this tree is dynamically structured and reorganized
is successively described in a series of modules, with each
module solving individual problem aspects.
The following is intended merely to provide a terminological framework
for the specification of the routines concerned.
.sp 2
A
.oc _/1;B* tree
B is a finite set whose elements are called
.oc _/1;nodes.
It is either empty (
.oc _/1;empty_tree
) or it contains a designated node W, known as the
.oc _/1;root,
and the remaining nodes (B(W)) are subdivided into
g(W) >= 0
.oc _/1;subtrees;
each subtree is itself a B* tree.
Under certain circumstances, the entire B* tree can also be referred
to as a subtree.  The subtrees can be graphically depicted as branches
from the root; g(W) is therefore called the
.oc _/1;branching_degree
of the node W.
The nodes of a B* tree have a variable branching degree!
.sp
A root is referred to as a
.oc _/1;parent_node
with relation to the roots of its subtrees and, inversely, the
subtree nodes are the
.oc _/1;offspring_nodes
of the parent node.
The offspring nodes of a root are always ordered;
nodes that directly follow one another are called
.oc _/1;neighbor nodes,
as are the last and first offspring of two adjacent
parent nodes.
In this case, the preceeding node in the sequence
(or last offspring node) is the
.oc _/1;left_neighbor_node
and the suceeding node (or first offspring node) is the
.oc _/1;right_neighbor_node.
.sp
A node is a
.oc _/1;leaf
if it has a branching degree of zero; otherwise it is a
.oc _/1;branch_node.
B* trees are characterized by the fact that each node that is
neighbor to a leaf is also a leaf.
This means that each node can be assigned a
.oc _/1;level_number
according to the following principle:
neighbor nodes have the same level number,
parent nodes have a level number that is one greater
than that of their offspring nodes and all leaves have the same
level number of zero.
.sp
Since each node is implemented via a page in the secondary
storage (see pagestore), the nodes are unambiguously identified by
.oc _/1;page_numbers
and B* trees are identified by the page numbers of their roots.
Unless otherwise indicated, the routines always process the
.oc _/1;current_B*_tree,
as determined by the last call of the routine b30adjust_tree
since the last system startup (or since system generation).
.sp 3;.cp 7
   b30new_tree(fi,current,e)
.sp
This routine generates a new B* tree for a file with
file information fi.
The new B* tree consists only of a root, whose page number
is entered in fi.root.
'current' contains additional information on the tree.
Some possible acknowledgements in e:
   - e_ok
   - b_no_more_space
   - b_disk_not_accessible
.sp 2;.cp 7
   b30adjust_tree (fi,t,current)
.sp
The file with file information fi becomes the current
B* tree.  File-specific information is made available in 'current'
by calling b30adjust_tree.
.sp 2;.cp 7
   bd30DropTree(current,stringcol_cnt,only_empty,e)
.sp
This routine re-releases all pages being used by the current
B* tree (current contains the necessary information).
.br
However, if 'only_empty' is assigned, the root of the tree is not
released but instead is re-initialized.
In this way, the contents of a file can be deleted without
the file having to be removed from the database.
.br
Otherwise ('only_empty' = FALSE), in order to ensure that no other
process with an invalid tree_id can access this tree, the root,
before it is released, is written to the secondary storage with a
deleted treeroot entry in the header. The parameter stringcol_cnt
contains the number of string fields in the RECORD representation
that belongs to this tree.  The B* trees that are referred to in
these fields are also deleted.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
.sp 2;.cp 7
   bd30VerifyTree (current,e)
.sp
The tree identified by 'current' is verified, i.e. the entire tree
is traversed and every node in the tree is labelled as used
in the previously deleted free storage manager.  In this manner,
pages that do not belong to any tree but were labelled as used
are again released.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
.sp 2;.cp 7
   current
.sp
The following is some of the information on the current B* tree
that is held in this variable:
.sp ;.of 2
- the page number 'root' of the root of the tree,
.br ;.in ;.of 2
- the file type ft that manages the tree,
(see filesysteminterface)
.br ;.in ;.of 2
- the buffer type bt, depending on whether a temporary file, the
system file or another permanent file is involved (see
systembufferinterface).
.sp 2;.cp 7
   indexorderlist
.sp
In this list, information is managed for a possible index
update or an index reorganization.
(see VBD54, indexupdateorders !).
.sp ;.in
.sp 3;.cp 6
.oc _/1
Operations_Involving_Trees_that_Manage_Primary_Files
.sp 2
Primary file entries are records with unambiguous record keys.
The way in which records and keys are transferred to a record or
key buffer is described in bufferhandling.
.sp 2;.cp 4
   bd30AddFileState (current, new_filestate)
.sp
.sp 2;.cp 4
   b30add_to_tree (rk, b, page_fill_limit, current)
.sp
Inserts in the current B* tree the record contained in the record
buffer b with the key rk, if no record with this key is already
present and if enough space is available. If a page is written to the secondary
storage during a tree operation, all log pages whose page numbers
are lower than or the same as that of the current log page are also
written to the secondary storage, making the change restart-capable.
In addition, the current log information must be entered in the
data cache when the page to be changed is allocated so that,
if this page is ever displaced from the data cache, the writing
of the log pages with lower or identical page numbers to the
secondary storage can be initiated.
.br
The set bd_use_info indicates whether act_logpos must be used
- bd_valid_logpos - and whether the pages are written through to
the secondary storage unbuffered - bd_unbuffered -.  In the case
of a temporary file, this set is always empty.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_duplicate_key
   - b_no_more_space
   - b_no_more_temp_space
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
.sp 2;.cp 4
   b30cappend_to_tree (rk, b, tree_pos, current)
.sp 2;.cp 4
   b30cnext_from_tree(rk,set_result,tree_pos,b,current,e)
.sp
Copies cnt records from the current B* tree that follow the record
with key rk (with the records arranged in ascending order by
keys).  If no record with a key greater than rk is contained in
the tree, 'b_no_next_record' is sent to e and cnt is set to
zero.  Otherwise, as many (complete) records are transferred
to buffer b as it can receive or they are transferred for as long as
records with greater keys are still present.  When it has been
determined that no other record is present, b_no_next_record
is sent to e.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_buffer_limit
   - b_no_next_record
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
.sp 2;.cp 4
  b30cprev_from_tree (rk, set_result, tree_pos, b, current)
.sp
Copies cnt records from the current B* tree that preceed the record
with key rk (with the records arranged in descending order by
keys).  If no record with a key smaller than rk is contained in
the tree, 'b_no_prev_record' is sent to e and cnt is set to
zero.  Otherwise, as many (complete) records are transferred
to buffer b as it can receive or they are transferred for as long as
records with smaller keys are still present.  When it has been
determined that no other record is present, b_no_prev_record
is sent to e.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_buffer_limitn
   - b_no_prev_record
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accesible
.sp 2;.cp 4
   b30del_from_tree (rk, current)
.sp
Deletes the record with the key rk from the current B* tree,
if such a record is present.
.br
.sp 2;.cp 4
   bd30ExistRecord(rk,current)
.sp
Carries out a search for a record with the key rk in
the current B* tree.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_key_not_found
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
????????????????????????
   - e_no_next_record
   - e_no_prev_record
   - b_file_not_found
.sp 2;.cp 4
   b30fdir_to_treeid (fi, file_id)
.sp 2;.cp 4
   bd30GetFromTree (rk, b, current, wanted_mode)
.sp
Copies the record with the key rk, if such a record is present,
from the current B* tree to the record buffer b.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_key_not_found
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
.sp 2;.cp 4
  b30init_load (rightmost_leaf, current)
.sp
.sp 2;.cp 4
  b30load_table (lnptr, nptr, tbd_node_ptrs, only_left,
        sep, indexorderlist, tbd_order_list current)
.sp
.sp 2;.cp 4
  b30new_tree (fi, current);
.sp
.sp 2;.cp 4
   bd30NextFromTree (rk, inclusive, tree_pos, b, current)
.sp
If the parameter is set to 'inclusive' and the record
with record key rk is found, this record is copied to record buffer b.
.br
Otherwise, the record that follows the record with key rk (with
the records arranged in ascending order by keys) is copied to b.
If no record with a key greater than rk is contained in the tree,
b_no_next_record is sent to e.  If the record with key rk is not
present, b_key_not_found is sent to e but the record is retrieved
that would have followed rk if it had been present.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_key_not_found
   - b_no_next_record
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
.sp 2;.cp 4
  bd30PrevFromTree(rk,inclusive,tree_pos,b,current,e)
.sp
If the parameter is set to 'inclusive' and the record
with the record key rk is found, this record is copied to the
record buffer b.
.br
Otherwise, the record that preceeds the record with key rk (with
the records arranged in descending order by keys) is copied to b.
If no record with a key smaller than rk is contained in the tree,
b_no_prev_record is sent to e.  If the record with key rk is not
present, b_key_not_found is sent to e but the record is retrieved
that would have preceeded rk if it had been present.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_key_not_found
   - b_no_prev_record
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accesible
.sp 3;.cp 7
   b30repl_in_tree(rk,b,bd_use_info, current,e)
.sp
Replaces the record with the key rk in the current B* tree, if
such a record is present, with the new record contained in the
record buffer b.  The new record must also have the record key rk
and, if it is longer than the old record, will be substituted only
if sufficient space is available.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_key_not_found
   - b_no_more_space
   - b_no_more_temp_space
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
.fo
.CM *-END-* specification -------------------------------
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
 
The branch nodes of a B* tree form its
.oc _/1;B*_index
and the leaves form its
.oc _/1;B*_file.
For the management of a primary file, the records are stored
in the B* file, whereas the B* index represents a generally
multilevel index for the B* file.
.sp
For each primary file record, the B* file contains a record
entry that begins in a specific leaf (n) in a specific
position (pos).  This position can be accessed via an index
(pointer_list) that is located at the end of each leaf.  The
sorting of record entries is defined by the index.  Normally,
the record is inserted by appending it to the existing records
and maintaining the index.  This means that the sorting of all
the record entries in a leaf only becomes necessary if the leaf
takes part in a tree balancing operation.
The position of a record
entry is not fixed but changes along with the dynamic setup and
dismantling of the tree.
.sp
.cp 17
.nf
                      Structure of a node
                      ===================
 
            +-------<---------<---------+
            |    +--------<--------<----|---+
            |    |                      |   |
            |    |                      |   |
+---+------+|---+|-----+----+----+----+-|-+-|-+---+---+---+-+
|   |  s1  | s5 |  s4  | s2 | s3 |    |P5 |P4 |P3 |P2 |P1 | |
+-|-+|-----+----+------+|---+|---+----+---+---+-|-+-|-+-|-+-+
  |  |                  |    |                  |   |   |
  |  |                  |    |                  |   |   |
  |  |                  |    +----------<-------+   |   |
  |  |                  +----------<----------<-----+   |
  |  +-------<-------------<-------------<--------------+
  |
  +--> header
.fo
.sp2
The function of the B* index is to provide quick access to a
record entry with a preset key (bd50FindLeaf).
.br
In order to support the sequential processing (bd30NextFromTree),
each leaf has a pointer to its right neighbor leaf
(see nodehandling) and an additional
.oc _/1;short-term_memory
(see keymemory) is maintained.
.sp
Each time a record entry is found and transferred to a
record buffer (get/next_from_tree), the 'address' of the record
entry is recorded in the memory.  The routines that process the
leaves are responsible for ensuring that the memory is not rendered
inconsistent by the insertion, deletion or replacement of record
entries.  When a search for a record entry is being carried out
first of all an attempt is made to find the
page number of the 'leaf' and, if possible, even the position
(pos, when dirty = FALSE) of the record entry via the short-term
memory.  If no corresponding entry is found in the memory, a
descent via the index occurs (bd50FindLeaf).  The position
within a leaf is found via b31search_entry and 'result'
delivers one of the following acknowledgements:
.sp ;.of 2
- nonefound, if no record entry begins in that leaf,
.br ;.in ;.of 2
- thisfound, if the record entry being searched for was found,
.br ;.in ;.of 2
- nextfound, if the record entry being searched for does not begin
in that leaf and the next record entry was found,
.br ;.in ;.of 2
- lastfound, if the last record entry beginning in the leaf was
found and has a key that is smaller than that of the record
for which the search was run.
.sp ;.in
Changes in the leaves may result in the need for minor
modifications to the B* index.  These modifications are
executed with b54execute_indexorder
at the end.  For a more detailed description, see
indexupdateorders.
.sp
When an entire B* tree is deleted (bd30DropTree), all
nodes are recursively deleted.  If the tree is made up of a
single node only (single), it is handled separately since this is
often the case with temporary files and should then take place very
quickly, whereas the large, permanent files are seldom deleted
and are also likely to require more time.
.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    :
 
 
TYPE
 
      int4_map_c4  = RECORD
            CASE boolean OF
                true  :
                    (map_c4 : tsp00_C4);
                false :
                    (map_i4 : tsp00_Int4)
                END;
            (*ENDCASE*) 
 
 
CONST
      MSG_NOT_EXCL_LOCKED    = 'Leaf is not excl locked ';
      MSG_WRONG_STATISTIC1   = 'Inconsistent Statistic1 ';
      MSG_WRONG_STATISTIC2   = 'Inconsistent Statistic2 ';
      MSG_WRONG_LEVEL        = 'Tree level is not 1     ';
      MSG_1_WRONG_LEVEL      = 'Tree level is <= 1      ';
      MSG_2_WRONG_LEVEL      = 'No index locks on level1';
      MSG_1_DROP             = 'Error during drop file  ';
      MSG_RELEASE_MISSING    = 'Release page missing    ';
      MSG_NO_PRIVATE_FILE    = 'File is not private     ';
      MSG_CREATE_SYSKEY      = 'Syskey generation failed';
      MSG_CREATE_SPECIALKEY  = 'Special key generation failed           ';
      MSG_2_DROP             = 'CHECK DATA WITH UPDATE may be needed    ';
      (* *)
      c_withBeforeRef     = true;
      c_bIsGetTree        = true;
      c_bGetLeafForUpdate = true;
      (* *)
      c_max_retries       = 10;
      (* *)
      MSG_START_CHECK_TABLE1 = 'Start check tables and indexes          ';
      MSG_START_CHECK_TABLE2 = 'Start check tables only                 ';
      MSG_START_CHECK_BLOB   = 'Start check blobs                       ';
      MSG_FDIR_CORRUPTED     = 'File Directory corrupted                ';
      (* *)
 
TYPE
 
      t_BlobIdValue = RECORD (* PTS 1133300 UH 2005-01-11 *)
            recordLength : tsp00_Int2;
            keyLength    : tsp00_Int2;
            filler       : tsp00_Int4;
            blobId       : tgg00_Surrogate;
            foundInTable : boolean;
            foundInFdir  : boolean;
      END;
 
 
      t_BlobIdRecord = RECORD (* PTS 1133300 UH 2005-01-11 *)
            CASE integer OF
                1:
                    (rec : tgg00_Rec);
                2:
                    (value : t_BlobIdValue);
                END;
            (*ENDCASE*) 
 
 
VAR
 
      bd30FileIdForBlobFileIds : RECORD (* PTS 1133300 UH 2005-01-11 *)
            fileid      : tgg00_FileId;
            fileCreated : boolean;
      END;
 
 
 
(*------------------------------*) 
 
PROCEDURE
      bd30InitFileIdForBlobFileIds;
 
BEGIN
(* PTS 1133300 UH 2005-01-11 new *)
bd30FileIdForBlobFileIds.fileCreated := false;
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30AddBlobIdFoundInTable (VAR trans : tgg00_TransContext;
            BlobId : tgg00_Surrogate);
 
VAR
      newRecord      : t_BlobIdRecord;
      existingRecord : t_BlobIdRecord;
 
BEGIN
(* PTS 1133300 UH 2005-01-11 new *)
IF  bd30FileIdForBlobFileIds.fileCreated
THEN
    BEGIN
    newRecord.value.recordLength := sizeof(t_BlobIdValue);
    newRecord.value.keyLength    := sizeof(tgg00_Surrogate);
    newRecord.value.filler       := 0;
    newRecord.value.blobId       := BlobId;
    newRecord.value.foundInTable := true;
    newRecord.value.foundInFdir  := false;
    b02add_record (trans, bd30FileIdForBlobFileIds.fileid, newRecord.rec);
&   ifdef TRACE
    t01basis_error (td_always, 'Add-Table   ', trans.trError_gg00);
    t01bool2 (td_always,       'foundInTable', newRecord.value.foundInTable
          ,                  'foundInFdir ', newRecord.value.foundInFdir);
    t01surrogate (td_always,   'BlobId      ', newRecord.value.blobId);
&   endif
    IF  trans.trError_gg00 = e_duplicate_key
    THEN
        BEGIN
        b02get_record (trans, bd30FileIdForBlobFileIds.fileid,
              newRecord.rec.recKey_gg00, existingRecord.rec);
        IF  trans.trError_gg00 = e_ok
        THEN
            BEGIN
            IF  existingRecord.value.foundInTable
                OR
                NOT existingRecord.value.foundInFdir
            THEN
                trans.trError_gg00 := e_ok; (*error*)
            (*ENDIF*) 
            newRecord.value.foundInFdir := existingRecord.value.foundInFdir;
            b02repl_record (trans, bd30FileIdForBlobFileIds.fileid, newRecord.rec);
            END;
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30AddBlobIdFoundInFiledirectory  (VAR trans : tgg00_TransContext;
            BlobId : tgg00_Surrogate);
 
VAR
      newRecord      : t_BlobIdRecord;
      existingRecord : t_BlobIdRecord;
 
BEGIN
(* PTS 1133300 UH 2005-01-11 new *)
IF  bd30FileIdForBlobFileIds.fileCreated
THEN
    BEGIN
    newRecord.value.recordLength := sizeof(t_BlobIdValue);
    newRecord.value.keyLength    := sizeof(tgg00_Surrogate);
    newRecord.value.filler       := 0;
    newRecord.value.blobId       := BlobId;
    newRecord.value.foundInTable := false;
    newRecord.value.foundInFdir  := true;
    b02add_record (trans, bd30FileIdForBlobFileIds.fileid, newRecord.rec);
&   ifdef TRACE
    t01basis_error (td_always, 'Add-Fdir    ', trans.trError_gg00);
    t01bool2 (td_always,       'foundInTable', newRecord.value.foundInTable
          ,                  'foundInFdir ', newRecord.value.foundInFdir);
    t01surrogate (td_always,   'BlobId      ', newRecord.value.blobId);
&   endif
    IF  trans.trError_gg00 = e_duplicate_key
    THEN
        BEGIN
        b02get_record (trans, bd30FileIdForBlobFileIds.fileid,
              newRecord.rec.recKey_gg00, existingRecord.rec);
        IF  trans.trError_gg00 = e_ok
        THEN
            BEGIN
            IF  existingRecord.value.foundInFdir
                OR
                NOT existingRecord.value.foundInTable
            THEN
                trans.trError_gg00 := e_ok; (*error*)
            (*ENDIF*) 
            newRecord.value.foundInTable := existingRecord.value.foundInTable;
            b02repl_record (trans, bd30FileIdForBlobFileIds.fileid, newRecord.rec);
            END;
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30DropUnreferencedBlobs (VAR trans : tgg00_TransContext);
 
VAR
      blobIdRecord : t_BlobIdRecord;
      blobFileId   : tgg00_FileId;
      fileinfo     : tbd_fileinfo;
 
BEGIN
(* PTS 1133300 UH 2005-01-11 new *)
IF  bd30FileIdForBlobFileIds.fileCreated
THEN
    BEGIN
    blobIdRecord.rec.recKeyLen_gg00 := 0;
    (**)
    blobFileId                 := b01niltree_id;
    blobFileId.fileType_gg00   := [ftsByteStr_egg00, ftsConcurrent_egg00];
    blobFileId.fileTfn_gg00    := tfnColumn_egg00;
    (**)
    WHILE trans.trError_gg00 = e_ok DO
        BEGIN
        b02next_record (trans, bd30FileIdForBlobFileIds.fileid,
              blobIdRecord.rec.recKey_gg00, false, blobIdRecord.rec);
&       ifdef TRACE
        t01basis_error (td_always, 'Drop Blob   ', trans.trError_gg00);
&       endif
        IF  trans.trError_gg00 = e_key_not_found (* first record *)
        THEN
            trans.trError_gg00 := e_ok;
        (*ENDIF*) 
        IF  trans.trError_gg00 <> e_no_next_record
        THEN
            BEGIN
&           ifdef TRACE
            t01bool2 (td_always,       'foundInTable', blobIdRecord.value.foundInTable
                  ,                    'foundInFdir ', blobIdRecord.value.foundInFdir);
            t01surrogate (td_always,   'BlobId      ', blobIdRecord.value.blobId);
&           endif
            IF  trans.trError_gg00 = e_ok
            THEN
                IF  NOT blobIdRecord.value.foundInTable
                THEN
                    BEGIN
                    blobFileId.fileTabId_gg00 := blobIdRecord.value.blobId;
                    blobFileId.fileRoot_gg00  := NIL_PAGE_NO_GG00;
                    b17state_fdir (blobFileId.fileName_gg00, fileinfo, true, trans);
                    IF  trans.trError_gg00 = e_ok
                    THEN
                        g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg,
                              csp3_n_btree, 'DROP UNREFERENCED BLOBS ', fileinfo.fi_root);
                    (*ENDIF*) 
                    trans.trError_gg00 := e_ok;
                    bd01DropLobFile (trans, blobFileId, cgg_zero_id);
&                   ifdef TRACE
                    t01basis_error (td_always, 'DestroyBlob ', trans.trError_gg00);
&                   endif
                    trans.trError_gg00 := e_ok;
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  trans.trError_gg00 = e_no_next_record
    THEN
        trans.trError_gg00 := e_ok;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30cappend_to_tree (
            VAR rk       : tgg00_Lkey;
            VAR b        : tgg00_Rec;
            VAR tree_pos : tgg00_FilePos;
            VAR current  : tbd_current_tree);
 
VAR
      searchResult : tbd_searchresult;
      recIndex     : tsp00_Int4;
      nptr         : tbd_node_ptrs;
      neighbs      : tbd_neighbors;
 
BEGIN
(* ATTENTION: THE CALLER OF THIS PROCEDURE HAS TO *)
(* ENSURE THAT THE ROOT PAGE IS LOCKED EXCLUSIVE! *)
WITH current, curr_trans^ DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    IF  tree_pos.tpsPno_gg00 <> NIL_PAGE_NO_GG00
    THEN
        bd13GetNode (current, tree_pos.tpsPno_gg00, plmLock_ebd00, nr_for_update, nptr)
    ELSE
        BEGIN
        bd30SearchRecord (current, rk.keyVal_gg00, rk.keyLen_gg00,
              LOCK_LEAF_EXCL_BD00, nptr, recIndex, neighbs, searchResult);
        IF  trError_gg00 = e_ok
        THEN
            IF  searchResult = thisfound
            THEN
                trError_gg00 := e_duplicate_key
            ELSE
                IF  (searchResult = nextfound) OR
                    (nptr.np_ptr^.nd_right <> NIL_PAGE_NO_GG00)
                THEN
                    trError_gg00 := e_append_not_allowed
                ELSE
                    BEGIN
                    tree_pos.tpsPno_gg00 := nptr.np_ptr^.nd_id;
                    IF  searchResult = nonefound
                    THEN
                        tree_pos.tpsIndex_gg00 := recIndex - 1
                    ELSE
                        tree_pos.tpsIndex_gg00 := recIndex
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        b31t_append_to_temp_leaf (b, nptr, tree_pos, current);
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30cget_result_leaf (
            VAR rk          : tgg00_Lkey;
            get_next        : boolean;
            prepare_for_upd : boolean;
            VAR tree_pos    : tgg00_FilePos;
            VAR nptr        : tbd_node_ptrs;
            VAR current     : tbd_current_tree);
 
VAR
      searchResult     : tbd_searchresult;
      node_req        : tbd_node_request;
      recIndex        : tsp00_Int4;
      right_neighbor  : tsp00_PageNo;
      neighbs         : tbd_neighbors;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    IF  prepare_for_upd
    THEN
        node_req := nr_for_update
    ELSE
        node_req := nr_for_read;
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        BEGIN
        IF  get_next
        THEN
            right_neighbor := nptr.np_ptr^.nd_right
        ELSE
            right_neighbor := tree_pos.tpsPno_gg00;
        (*ENDIF*) 
        IF  prepare_for_upd
        THEN
            b13w_release_node (nptr, current)
        ELSE
            b13r_release_node (nptr, current, lru_normal)
        (*ENDIF*) 
        END
    ELSE
        IF  get_next
        THEN
            right_neighbor := NIL_PAGE_NO_GG00
        ELSE
            right_neighbor := tree_pos.tpsPno_gg00;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  tree_pos.tpsPno_gg00 = NIL_PAGE_NO_GG00
    THEN
        BEGIN
        bd30SearchRecord (current, rk.keyVal_gg00, rk.keyLen_gg00,
              prepare_for_upd, nptr, recIndex, neighbs, searchResult);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  searchResult = nonefound
            THEN
                trError_gg00 := e_no_next_record
            ELSE
                IF  (searchResult = lastfound) OR (searchResult = thisfound)
                THEN
                    IF  prepare_for_upd
                    THEN
                        b31w_next_search (nptr, recIndex, current )
                    ELSE
                        b31next_search (nptr, recIndex, current, lru_normal);
                    (*ENDIF*) 
                (*might return b_no_next_record*)
                (*ENDIF*) 
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                tree_pos.tpsPno_gg00   := nptr.np_ptr^.nd_id;
                tree_pos.tpsIndex_gg00 := recIndex
                END
            ELSE
                tree_pos.tpsPno_gg00 := NIL_PAGE_NO_GG00
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  right_neighbor <> NIL_PAGE_NO_GG00
        THEN
            BEGIN
            bd13GetNode (current, right_neighbor, plmLock_ebd00, node_req, nptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                tree_pos.tpsPno_gg00   := nptr.np_ptr^.nd_id;
                tree_pos.tpsIndex_gg00 := FIRST_REC_INDEX_BD00
                END
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            trError_gg00         := e_no_next_record;
            tree_pos.tpsPno_gg00 := NIL_PAGE_NO_GG00
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
&   ifdef TRACE
    IF  (trError_gg00 = e_ok) AND prepare_for_upd
    THEN
        BEGIN
        IF  NOT bd20IsPageExclusiveLocked (nptr.np_cbptr)
        THEN
            g01abort (csp3_bd_msg, csp3_n_btree, MSG_NOT_EXCL_LOCKED, nptr.np_ptr^.nd_id);
        (*ENDIF*) 
        END;
&   endif
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30cnext_from_tree (
            VAR rk         : tgg00_Lkey;
            VAR set_result : tgg00_BdSetResultRecord;
            VAR tree_pos   : tgg00_FilePos;
            VAR b          : tsp00_MoveObj;
            VAR current    : tbd_current_tree);
 
VAR
      searchResult : tbd_searchresult;
      recIndex     : tsp00_Int4;
      nptr         : tbd_node_ptrs;
      neighbs      : tbd_neighbors;
 
BEGIN
WITH current, curr_trans^  DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    IF  tree_pos.tpsPno_gg00 = NIL_PAGE_NO_GG00
    THEN
        BEGIN
        bd30SearchRecord (current, rk.keyVal_gg00, rk.keyLen_gg00,
              NOT LOCK_LEAF_EXCL_BD00, nptr, recIndex, neighbs, searchResult);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  searchResult = nonefound
            THEN
                trError_gg00 := e_no_next_record
            ELSE
                IF  (searchResult = lastfound) OR
                    ((searchResult = thisfound) AND set_result.bd_next)
                THEN
                    b31next_search (nptr, recIndex, current, lru_normal);
                (*might return b_no_next_record*)
                (*ENDIF*) 
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                tree_pos.tpsPno_gg00   := nptr.np_ptr^.nd_id;
                tree_pos.tpsIndex_gg00 := recIndex
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  tree_pos.tpsIndex_gg00 = NIL_RECINDEX_BD00
        THEN
            trError_gg00 := e_no_next_record
        ELSE
            BEGIN
            searchResult := thisfound;
            bd13GetNode (current, tree_pos.tpsPno_gg00, plmLock_ebd00, nr_for_read, nptr);
            IF  set_result.bd_next AND (trError_gg00 = e_ok)
            THEN
                BEGIN
                recIndex := tree_pos.tpsIndex_gg00;
                b31next_search (nptr, recIndex, current,lru_normal);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    tree_pos.tpsPno_gg00   := nptr.np_ptr^.nd_id;
                    tree_pos.tpsIndex_gg00 := recIndex
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        b31nfill_recordbuffer (nptr, rk, tree_pos, set_result, b, current);
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND (searchResult <> thisfound)
    THEN
        trError_gg00 := e_key_not_found;
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30cprev_from_tree (
            VAR rk         : tgg00_Lkey;
            VAR set_result : tgg00_BdSetResultRecord;
            VAR tree_pos   : tgg00_FilePos;
            VAR b          : tsp00_MoveObj;
            VAR current    : tbd_current_tree);
 
VAR
      searchResult : tbd_searchresult;
      recIndex     : tsp00_Int4;
      nptr         : tbd_node_ptrs;
      neighbs      : tbd_neighbors;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    IF  tree_pos.tpsPno_gg00 = NIL_PAGE_NO_GG00
    THEN
        BEGIN
        bd30SearchRecord (current, rk.keyVal_gg00, rk.keyLen_gg00,
              NOT LOCK_LEAF_EXCL_BD00, nptr, recIndex, neighbs, searchResult);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  searchResult = nonefound
            THEN
                trError_gg00 := e_no_prev_record
            ELSE
                IF  (searchResult = nextfound) OR
                    ((searchResult = thisfound) AND set_result.bd_next)
                THEN
                    b31t_prev_temp_search (nptr, recIndex, current);
                (*ENDIF*) 
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                tree_pos.tpsPno_gg00   := nptr.np_ptr^.nd_id;
                tree_pos.tpsIndex_gg00 := recIndex
                END;
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  tree_pos.tpsIndex_gg00 = NIL_RECINDEX_BD00
        THEN
            trError_gg00 := e_no_prev_record
        ELSE
            BEGIN
            searchResult := thisfound;
            bd13GetNode (current, tree_pos.tpsPno_gg00, plmLock_ebd00, nr_for_read, nptr);
            IF  set_result.bd_next AND (trError_gg00 = e_ok)
            THEN
                BEGIN
                recIndex := tree_pos.tpsIndex_gg00;
                b31t_prev_temp_search (nptr, recIndex, current);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    tree_pos.tpsPno_gg00   := nptr.np_ptr^.nd_id;
                    tree_pos.tpsIndex_gg00 := recIndex
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        b31pfill_recordbuffer (nptr, rk, tree_pos, set_result, b, current);
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND (searchResult <> thisfound)
    THEN
        trError_gg00 := e_key_not_found;
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30CheckDatabase (
            VAR t                        : tgg00_TransContext;
            VAR bad_index_cnt            : tsp00_Int4;
            VAR total_bad_cnt            : tsp00_Int4;
            VAR verify_error             : tgg00_BasisError;
            bWithUpdate                  : boolean;
            bWithExtendedCheck           : boolean;
            bWithIndexes                 : boolean;
            bWithDeleteUnreferencedBlobs : boolean; (* PTS 1133300 UH 2005-01-11 *)
            max_server                   : integer);
 
VAR
      finish                : boolean;
      startBlobVerify       : boolean;
      bSearchNext           : boolean;
      retry_cnt             : integer;
      send_cnt              : integer;
      eFiletypeSet          : tgg00_ExtendedFiletypeSet;
      ErrorRoot             : tsp00_PageNo;
      fi                    : tbd_fileinfo;
      file_id               : tgg00_FileId;
      bCheckBlobFiles       : boolean;
      pFileDirIter          : tsp00_Addr;
      pCheckDataCoordinator : tsp00_Addr; (* UH 2004-10-04 *)
      auxError              : tgg00_BasisError;
 
BEGIN
finish                := false;
startBlobVerify       := false;
bSearchNext           := false;
retry_cnt             := 0;
send_cnt              := 0;
ErrorRoot             := NIL_PAGE_NO_GG00;
file_id               := b01niltree_id;
pFileDirIter          := NIL;
bCheckBlobFiles       := false;
pCheckDataCoordinator := NIL;
IF  bWithDeleteUnreferencedBlobs (* PTS 1133300 UH 2005-01-11 *)
THEN
    BEGIN
    bd30FileIdForBlobFileIds.fileid               := b01niltree_id;
    bd30FileIdForBlobFileIds.fileid.fileType_gg00 := [ ftsPerm_egg00, ftsConcurrent_egg00 ];
    bd998NewFileNo (bd30FileIdForBlobFileIds.fileid.fileTabId_gg00);
    eFiletypeSet := [];
    bd01CreatePermTableFile (t, bd30FileIdForBlobFileIds.fileid,
          eFiletypeSet, 0);
    IF  t.trError_gg00 = e_ok
    THEN
        bd30FileIdForBlobFileIds.fileCreated := true;
    (*ENDIF*) 
    g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg,
          csp3_n_btree, 'SCAN FOR UNREF. BLOBS   ', bd30FileIdForBlobFileIds.fileid.fileRoot_gg00);
    END;
(*ENDIF*) 
IF  bWithUpdate
THEN
    bWithIndexes := true;
(*ENDIF*) 
WITH t DO
    BEGIN
    IF  bWithIndexes
    THEN
        g01optextmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
              csp3_n_check, MSG_START_CHECK_TABLE1)
    ELSE
        g01optextmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
              csp3_n_check, MSG_START_CHECK_TABLE2);
    (*ENDIF*) 
    bd998NewFileDirIterator (t, pFileDirIter);
    IF  trError_gg00 = e_ok
    THEN
        bd998InitFileDirIterator (t, bWithUpdate, pFileDirIter);
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        kb900CreateCheckDataCoordinator(t, pCheckDataCoordinator);
    (*ENDIF*) 
    WHILE (
          (trError_gg00 = e_ok) AND
          (NOT finish         )
          )
          OR
          (
          (trError_gg00 = e_no_server_task_available) AND
          (retry_cnt < c_max_retries                )
          )
          DO
        BEGIN
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  NOT bCheckBlobFiles
            THEN
                REPEAT
                    bd998AdvanceFileDirIterator (t, pFileDirIter, file_id);
                    IF  (ftsTemp_egg00 IN file_id.fileType_gg00   ) OR
                        (ftsArchive_egg00 IN file_id.fileType_gg00) OR
                        ((NOT bWithIndexes) AND (g04inv_tfn (file_id.fileTfn_gg00)))
                    THEN
                        bSearchNext := true
                    ELSE
                        BEGIN
                        bd998GcGetFDirEntryFileinfo (t, file_id.fileName_gg00, fi, true);
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            IF  (f_not_accessible IN fi.fi_state)
                            THEN
                                BEGIN
                                trError_gg00 := e_file_not_accessible;
                                ErrorRoot    := fi.fi_root;
                                END;
                            (*ENDIF*) 
                            bSearchNext := fi.fi_root = NIL_PAGE_NO_GG00
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_file_not_found
                    THEN
                        BEGIN
                        bCheckBlobFiles       := true;
                        trError_gg00          := e_ok;
                        file_id.fileName_gg00 := cgg_zero_fn;
                        startBlobVerify       := true;
                        g01optextmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
                              csp3_n_check, MSG_START_CHECK_BLOB)
                        END;
                    (*ENDIF*) 
                UNTIL
                    (trError_gg00 <> e_ok) OR bCheckBlobFiles OR (NOT bSearchNext);
                (*ENDREPEAT*) 
            (*ENDIF*) 
            IF  bCheckBlobFiles
            THEN
                REPEAT
                    bd17GetNextBlob (t, file_id.fileName_gg00, fi);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        IF  (f_not_accessible IN fi.fi_state)
                        THEN
                            BEGIN
                            trError_gg00 := e_file_not_accessible;
                            ErrorRoot    := fi.fi_root;
                            END;
                        (*ENDIF*) 
                        b30fdir_to_treeid (fi, file_id);
                        bSearchNext := (fi.fi_root = NIL_PAGE_NO_GG00) OR
                              ( ftsArchive_egg00 IN file_id.fileType_gg00 )
                        END;
                    (*ENDIF*) 
                UNTIL
                    (trError_gg00 <> e_ok) OR (NOT bSearchNext);
                (*ENDREPEAT*) 
            (*ENDIF*) 
            IF  trError_gg00 = e_file_not_found
            THEN
                BEGIN
                finish       := true;
                trError_gg00 := e_ok
                END;
            (*ENDIF*) 
            END;
        (* set dummy file version to avoid e_old_fileversion during *)
        (* check data                                               *)
        (*ENDIF*) 
        file_id.fileVersion_gg00.ci2_gg00 := cgg_dummy_file_version;
        file_id.fileLeafNodes_gg00        := cgg_nil_leafnodes;
        IF  (
            (trError_gg00 = e_ok                      ) OR
            (trError_gg00 = e_no_server_task_available)
            )
            AND
            (NOT finish                    )
        THEN
            bd30_SendFileId (t, pCheckDataCoordinator, file_id, retry_cnt,
                  send_cnt, bWithUpdate, bWithExtendedCheck);
        (*ENDIF*) 
        IF  ((trError_gg00 = e_ok) AND (send_cnt = max_server))
            OR
            ((finish) AND (send_cnt > 0))
            OR
            ((trError_gg00 = e_no_server_task_available) AND (send_cnt > 0))
        THEN
            BEGIN
            bd30wait_for_reply (t, pCheckDataCoordinator, send_cnt, ErrorRoot, max_server, finish);
            END;
        (*ENDIF*) 
        IF  (NOT finish                               )
            AND
            (
            (trError_gg00 = e_no_server_task_available) AND
            (send_cnt = 0                             ) AND
            (retry_cnt >= c_max_retries               )
            )
        THEN
            BEGIN
            (* no server available *)
            trError_gg00 := e_ok;
            retry_cnt    := 0;
            b01pverify_participant (t, file_id, bWithUpdate, bWithExtendedCheck);
            (* PTS 1105359 TS 2000-01-17 *)
            IF  trError_gg00 <> e_ok
            THEN
                ErrorRoot := file_id.fileRoot_gg00;
            (* PTS 1105359 *)
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  (ErrorRoot    <> NIL_PAGE_NO_GG00          ) AND
            (trError_gg00 <> e_ok                      ) AND
            (trError_gg00 <> e_no_server_task_available) AND
            (trError_gg00 <> e_shutdown                ) AND
            (trError_gg00 <> e_disk_not_accessible     ) AND
            (trError_gg00 <> e_cancelled               )
        THEN
            BEGIN
            total_bad_cnt := succ (total_bad_cnt);
            IF  trError_gg00 = e_file_not_accessible
            THEN
                bad_index_cnt := succ (bad_index_cnt)
            ELSE
                IF  verify_error = e_ok
                THEN
                    verify_error := trError_gg00;
                (*ENDIF*) 
            (*ENDIF*) 
            bd30_PnoCheckOpmsg (ErrorRoot, trError_gg00);
            ErrorRoot := NIL_PAGE_NO_GG00;
            (* *)
            IF  NOT finish
            THEN
                trError_gg00 := e_ok;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (trRteCommPtr_gg00^.to_cancel)
        THEN
            BEGIN
            trError_gg00 := e_cancelled;
            g01opmsg (sp3p_knldiag, sp3m_info, bd30Cancel_1_csp03,
                  csp3_n_btree, 'Check data canceled     ', trTaskId_gg00);
            END
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    bd998DestroyFileDirIterator (t, pFileDirIter);
    IF  trError_gg00 <> e_ok
    THEN
        BEGIN
        kb900AbortCheckDataJobs(t, pCheckDataCoordinator);
        send_cnt := 0;
        END;
    (*ENDIF*) 
    kb900DeleteCheckDataCoordinator(t, pCheckDataCoordinator);
    IF  (finish) AND (trError_gg00 = e_ok)
    THEN
        trError_gg00 := e_file_not_found;
    (*ENDIF*) 
    IF  bd30FileIdForBlobFileIds.fileCreated (* PTS 1133300 UH 2005-01-11 *)
    THEN
        BEGIN
        auxError     := trError_gg00;
        trError_gg00 := e_ok;
        bd30DropUnreferencedBlobs(t);
        trError_gg00 := e_ok;
        b01pdestroy_perm_file (t, bd30FileIdForBlobFileIds.fileid);
        bd30FileIdForBlobFileIds.fileCreated := false;
        trError_gg00 := auxError;
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30fdir_to_treeid (VAR fi : tbd_fileinfo;
            VAR file_id : tgg00_FileId);
 
BEGIN
WITH file_id DO
    BEGIN
    fileRoot_gg00 := fi.fi_root;
    fileType_gg00 := fi.fi_type;
    IF  fileRoot_gg00 = NIL_PAGE_NO_GG00
    THEN
        fileRootCheck_gg00 := ROOT_CHECK_GG00
    ELSE
        bd300SetRootCheck (file_id);
    (*ENDIF*) 
&   ifdef trace
    t01int4 (bi, '30n_root_che', fileRootCheck_gg00);
&   endif
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30init_load (VAR rightmost_leaf : tsp00_PageNo;
            VAR current : tbd_current_tree);
 
VAR
      recIndexForLeaf : tsp00_Int4;
      nptr            : tbd_node_ptrs;
      neighbs         : tbd_neighbors;
      fullkey         : tgg00_Lkey;
 
BEGIN
nptr.np_ptr         := NIL;
nptr.np_cbptr       := NIL;
rightmost_leaf      := NIL_PAGE_NO_GG00;
fullkey.keyLen_gg00 := PERM_KEY_MXSP00;
fullkey.keyVal_gg00 := b01fullkey;
bd50FindLeaf (fullkey.keyVal_gg00, fullkey.keyLen_gg00, NOT LOCK_LEAF_EXCL_BD00,
      nptr, neighbs, recIndexForLeaf, current);
IF  current.curr_trans^.trError_gg00 = e_ok
THEN
    BEGIN
    rightmost_leaf := nptr.np_ptr^.nd_id;
    b13r_release_node (nptr, current, lru_normal)
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30load_table (
            VAR lnptr          : tbd_node_ptrs;
            VAR nptr           : tbd_node_ptrs;
            only_left          : boolean;
            VAR current        : tbd_current_tree);
 
VAR
      bUpdateLeftLinkage : boolean;
      rightmost_leaf     : tsp00_PageNo;
      sep                : tgg00_Lkey;
      indexorderlist     : tbd00_OrderList;
      save_bottom        : tgg00_PagePos;
      save_list_top      : tsp00_Int4;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    bUpdateLeftLinkage := (ftsTemp_egg00 IN fileType_gg00) OR
          (eftsClustered_egg00 IN currExtendedFileTypeSet_bd00);
    (* *)
    (* only one page is given via sql packet *)
    IF  only_left
    THEN
        lnptr.np_ptr^.nd_right := NIL_PAGE_NO_GG00
    ELSE
        BEGIN
        curr_lvl_1_pno := NIL_PAGE_NO_GG00;
        indexorderlist.olstCount_bd00 := 0;
        WITH nptr.np_ptr^ DO
            BEGIN
            (* h.b. 19.02.99                          *)
            (* changed initialisation for FASTLOAD:   *)
            (* list_top and bottom are already filled *)
            (* by FASTLOAD                            *)
            save_bottom      := nd_bottom;
            save_list_top    := nd_record_cnt;
            b13init_default_data_page (curr_tree_id, LEAF_LEVEL_BD00, nd_id, nptr);
            nd_bottom        := save_bottom;
            nd_record_cnt    := save_list_top;
            IF  bUpdateLeftLinkage
            THEN
                nd_left  := lnptr.np_ptr^.nd_id;
            (*ENDIF*) 
            IF  (nd_id = fileRoot_gg00)
            THEN
                nd_file_version := fileVersion_gg00;
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
        lnptr.np_ptr^.nd_right := nptr.np_ptr^.nd_id;
        sep.keyLen_gg00        := 0; (* sep.lksep.len := 0; *)
        bd53NewLeafIndex (lnptr.np_ptr, nptr.np_ptr, sep, curr_trans);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            b54add_index (@sep.keyVal_gg00, sep.keyLen_gg00, nptr.np_ptr^.nd_id,
                  LEAF_LEVEL_BD00, indexorderlist);
            b13w_release_node (lnptr, current);
            (* *)
            (* PTS XXXX TS 2000-12-27 *)
            (* release pages to avoid illegal request in data cache *)
            rightmost_leaf := nptr.np_ptr^.nd_id;
            b13w_release_node (nptr, current);
            (* *)
            b54execute_indexorder (indexorderlist, current);
            IF  trError_gg00 = e_ok
            THEN
                bd13GetNode (current, rightmost_leaf, plmLock_ebd00, nr_for_update, lnptr);
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30new_tree (VAR fi : tbd_fileinfo;
            VAR current   : tbd_current_tree);
 
VAR
      nptr : tbd_node_ptrs;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL;
    b13new_root (nptr, current);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        fi.fi_root    := np_ptr^.nd_id;
        fileRoot_gg00 := np_ptr^.nd_id;
        IF  kb560IsCatalogTable (fileTabId_gg00)
        THEN
            BEGIN
            np_ptr^.nd_pmode   := np_ptr^.nd_pmode + [pmCatalog_egg00];
            np_ptr^.nd_trailer := np_ptr^.nd_header
            END;
        (*ENDIF*) 
        np_ptr^.nd_file_state := fi.fi_state;
        bd300SetRootCheck (curr_tree_id);
        b13w_release_node (nptr, current)
        END;
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30AddFileState (
            VAR current : tbd_current_tree;
            fileState   : tbd_file_state_set);
 
BEGIN
WITH current, currRootNptrs_bd00.np_ptr^ DO
    BEGIN
    nd_file_state        := nd_file_state + fileState;
    currRootUpdated_bd00 := true;
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30AddToTempTree (
            bCountDuplicates : boolean;
            VAR rec          : tgg00_Rec;
            VAR current      : tbd_current_tree);
 
VAR
      searchResult    : tbd_searchresult;
      recIndex        : tsp00_Int4;
      duplicateCnt    : tsp00_Int4;
      pRec            : tgg00_RecPtr;
      nptr            : tbd_node_ptrs;
      neighbs         : tbd_neighbors;
      dummyRef        : tgg91_PageRef;
 
BEGIN
(* ATTENTION: THE CALLER OF THIS PROCEDURE HAS TO *)
(* ENSURE THAT THE ROOT PAGE IS LOCKED EXCLUSIVE! *)
WITH current, curr_trans^ DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
&   ifdef TRACE
    IF  bCountDuplicates
    THEN
        t01key( bi, 'TempRecKey  ', rec.recKey_gg00);
    (*ENDIF*) 
    IF  ftsConcurrent_egg00 IN curr_tree_id.fileType_gg00
    THEN
        g01abort (csp3_bd_msg, csp3_n_btree, MSG_NO_PRIVATE_FILE,
              curr_tree_id.fileRoot_gg00);
&   endif
    (*ENDIF*) 
    bd30SearchRecord (current, rec.recKey_gg00.keyVal_gg00, rec.recKeyLen_gg00,
          LOCK_LEAF_EXCL_BD00, nptr, recIndex, neighbs, searchResult);
    IF  trError_gg00 = e_ok
    THEN
        WITH neighbs DO
            CASE searchResult OF
                thisfound :
                    BEGIN
                    IF  bCountDuplicates
                    THEN
                        WITH nptr.np_ptr^ DO
                            BEGIN
                            pRec         := @nd_body [nd_pointer_list [MAX_POINTERINDEX_BD00 - recIndex]];
                            duplicateCnt := gg06PnoGet(pRec^.recPno_gg00);
                            IF  duplicateCnt < MAX_INT4_SP00 -1
                            THEN
                                BEGIN
                                gg06PnoPut( pRec^.recPno_gg00, duplicateCnt +1);
                                b13w_release_node (nptr, current);
                                END;
                            (*ENDIF*) 
                            END;
                        (*ENDWITH*) 
                    (*ENDIF*) 
                    trError_gg00 := e_duplicate_key;
                    END;
                nonefound :
                    b31add_to_leaf (rec, nptr, FIRST_REC_INDEX_BD00, ln, current);
                nextfound :
                    b31add_to_leaf (rec, nptr, recIndex, ln, current);
                lastfound :
                    bd31AppendToLeaf (rec, nptr, recIndex, ln, current, NOT c_withBeforeRef, dummyRef);
                END;
            (*ENDCASE*) 
        (*ENDWITH*) 
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30AddToTree (
            VAR recKey    : tgg00_Lkey;
            VAR rec       : tgg00_Rec;
            VAR current   : tbd_current_tree);
 
VAR
      bDoLockHandling  : boolean;
      bReadyForInsert  : boolean;
      searchResult     : tbd_searchresult;
      maximumKeyLen    : tsp00_Int4;
      recIndex         : tsp00_Int4;
      recIndexForLeaf  : tsp00_Int4;
      leaf             : tsp00_PageNo;
      pInsRec          : tgg00_RecPtr;
      nptr             : tbd_node_ptrs;
      neighbs          : tbd_neighbors;
      dummyRef         : tgg91_PageRef;
      packedRow        : tgg00_Rec;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    nptr.np_ptr     := NIL;
    nptr.np_cbptr   := NIL;
    bReadyForInsert := false;
    bDoLockHandling := (NOT bd20IsPageExclusiveLocked (currRootNptrs_bd00.np_cbptr));
    (* *)
    WHILE (trError_gg00 = e_ok) AND NOT bReadyForInsert DO
        BEGIN
        IF  nptr.np_ptr = NIL (* leaf node is not available *)
        THEN
            bd50FindLeaf (recKey.keyVal_gg00, recKey.keyLen_gg00,
                  LOCK_LEAF_EXCL_BD00, nptr, neighbs, recIndexForLeaf, current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b31search_entry (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
                  nptr.np_ptr, recIndex, searchResult);
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (searchResult = thisfound)
        THEN
            trError_gg00 := e_duplicate_key;
        (*ENDIF*) 
        bReadyForInsert := NOT bDoLockHandling;
        IF  (trError_gg00 = e_ok) AND bDoLockHandling
        THEN
            BEGIN
            IF  (
                nptr.np_ptr^.nd_bottom + Data_GetRecLen(@rec) <=
                MAX_BOTTOM_BD00 - ((nptr.np_ptr^.nd_record_cnt+1)*POINTERSIZE_BD00)
                )
                AND
                (
                (nptr.np_ptr^.nd_bottom < NINETY_PERCENT_COV_BD00) OR
                (searchResult <> lastfound                       ) OR
                (nptr.np_ptr^.nd_right <> NIL_PAGE_NO_GG00       )
                )
            THEN
                bReadyForInsert := true (* local update possible *)
            ELSE
                BEGIN
                bDoLockHandling := false;
                maximumKeyLen   := bd30_DetermineMaxKeyLength (nptr.np_ptr);
                b13r_release_node (nptr, current, lru_normal);
                IF  NOT bd50IndexNodeIsSaveForInsert (current,
                    recIndexForLeaf, recKey.keyLen_gg00, maximumKeyLen)
                THEN
                    bd30_LockTreeExclusive (current)
                ELSE
                    BEGIN (* level > FIRST_INDEX_LEVEL_BD00 *)
                    bd30_LockSubTreeExclusive (current);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        bd50DetermineLeafNode (current, @recKey.keyVal_gg00,
                              recKey.keyLen_gg00, recIndexForLeaf, leaf, neighbs.ln);
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            bd13GetNode (current, leaf, plmLock_ebd00, nr_for_update, nptr);
                            IF  trError_gg00 = e_ok
                            THEN
                                BEGIN
                                maximumKeyLen := bd30_DetermineMaxKeyLength (nptr.np_ptr);
                                IF  NOT bd50IndexNodeIsSaveForInsert (current,
                                    recIndexForLeaf, recKey.keyLen_gg00, maximumKeyLen)
                                THEN
                                    BEGIN
                                    b13r_release_node (nptr, current, lru_normal);
                                    bd30_LockTreeExclusive (current)
                                    END
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  eftsRecordsPacked_egg00 in currExtendedFileTypeSet_bd00 (* PTS 1139184 *)
        THEN
            pInsRec := bd999PackRow (rec, packedRow)
        ELSE
            pInsRec := @rec;
        (*ENDIF*) 
        CASE searchResult OF
            nonefound :
                bd31AddToLeaf (pInsRec^, nptr, FIRST_REC_INDEX_BD00, neighbs.ln, current,
                      NOT c_withBeforeRef, dummyRef);
            nextfound :
                bd31AddToLeaf (pInsRec^, nptr, recIndex, neighbs.ln, current,
                      NOT c_withBeforeRef, dummyRef);
            lastfound :
                bd31AppendToLeaf (pInsRec^, nptr, recIndex,
                      neighbs.ln, current, NOT c_withBeforeRef, dummyRef);
            OTHERWISE
                trError_gg00 := e_not_implemented
            END;
        (*ENDCASE*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30AddToTreeWithSpecialKey (
            VAR recKey  : tgg00_Lkey;
            VAR rec     : tgg00_Rec;
            VAR current : tbd_current_tree);
 
VAR
      bDoLockHandling  : boolean;
      bMaxKeyUsed      : boolean;
      bNewTreeAccess   : boolean;
      bReadyForInsert  : boolean;
      auxError         : tgg00_BasisError;
      searchResult     : tbd_searchresult;
      maximumKeyLen    : tsp00_Int4;
      recIndex         : tsp00_Int4;
      recIndexForLeaf  : tsp00_Int4;
      leaf             : tsp00_PageNo;
      pInsRec          : tgg00_RecPtr;
      nptr             : tbd_node_ptrs;
      neighbs          : tbd_neighbors;
      dummyRef         : tgg91_PageRef;
      keyTrace         : tgg11_BdKeyTrace;
      packedRow        : tgg00_Rec;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    nptr.np_ptr     := NIL;
    nptr.np_cbptr   := NIL;
    bMaxKeyUsed     := true; (* key suffix has trailing MAX_UNIQUE_PRIM_ID_GG00 bytes *)
    bReadyForInsert := false;
    bDoLockHandling := (NOT bd20IsPageExclusiveLocked (currRootNptrs_bd00.np_cbptr));
    (* *)
    WHILE (trError_gg00 = e_ok) AND NOT bReadyForInsert DO
        BEGIN
        bNewTreeAccess := false;
        IF  nptr.np_ptr = NIL (* leaf node is not available *)
        THEN
            bd50FindLeaf (recKey.keyVal_gg00, recKey.keyLen_gg00,
                  LOCK_LEAF_EXCL_BD00, nptr, neighbs, recIndexForLeaf, current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b31search_entry (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
                  nptr.np_ptr, recIndex, searchResult);
        (*ENDIF*) 
        IF  (e_ok = trError_gg00) AND ((bMaxKeyUsed) OR (thisfound = searchResult))
        THEN
            BEGIN
            bd30_PrepareSpecialKey (current, recKey, nptr, recIndex, searchResult,
                  bMaxKeyUsed, bNewTreeAccess);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  bNewTreeAccess
                THEN
                    BEGIN
                    IF  nptr.np_ptr <> NIL
                    THEN
                        b13r_release_node (nptr, current, lru_normal);
                    (*ENDIF*) 
                    bd30ReleaseSubTree (current)
                    END;
                (*ENDIF*) 
                IF  bMaxKeyUsed
                THEN (* lock tree exclusive to avoid starvation problems *)
                    BEGIN
                    bd30_LockTreeExclusive( current );
                    bDoLockHandling := false;
                    END;
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        bReadyForInsert := (NOT bDoLockHandling) AND (NOT bNewTreeAccess);
        IF  (e_ok = trError_gg00) AND (bDoLockHandling) AND (NOT bNewTreeAccess)
        THEN
            BEGIN
            IF  (
                nptr.np_ptr^.nd_bottom + Data_GetRecLen(@rec) <=
                MAX_BOTTOM_BD00 - ((nptr.np_ptr^.nd_record_cnt+1)*POINTERSIZE_BD00)
                )
                AND
                (
                (nptr.np_ptr^.nd_bottom < NINETY_PERCENT_COV_BD00) OR
                (searchResult <> lastfound                       ) OR
                (nptr.np_ptr^.nd_right <> NIL_PAGE_NO_GG00       )
                )
            THEN
                bReadyForInsert := true (* local update possible *)
            ELSE
                BEGIN
                bDoLockHandling := false;
                maximumKeyLen   := bd30_DetermineMaxKeyLength (nptr.np_ptr);
                b13r_release_node (nptr, current, lru_normal);
                IF  NOT bd50IndexNodeIsSaveForInsert (current,
                    recIndexForLeaf, recKey.keyLen_gg00, maximumKeyLen)
                THEN
                    bd30_LockTreeExclusive (current)
                ELSE
                    BEGIN (* level > FIRST_INDEX_LEVEL_BD00 *)
                    bd30_LockSubTreeExclusive (current);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        bd50DetermineLeafNode (current, @recKey.keyVal_gg00,
                              recKey.keyLen_gg00, recIndexForLeaf, leaf, neighbs.ln);
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            bd13GetNode (current, leaf, plmLock_ebd00, nr_for_update, nptr);
                            IF  trError_gg00 = e_ok
                            THEN
                                BEGIN
                                maximumKeyLen := bd30_DetermineMaxKeyLength (nptr.np_ptr);
                                IF  (NOT bd50IndexNodeIsSaveForInsert (current,
                                    recIndexForLeaf, recKey.keyLen_gg00, maximumKeyLen))
                                    OR
                                    (bd30_SpecialKeyExist (current, recKey, nptr.np_ptr))
                                THEN
                                    BEGIN
                                    b13r_release_node (nptr, current, lru_normal);
                                    bd30_LockTreeExclusive (current)
                                    END
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    (* *)
    IF  (trError_gg00 = e_ok) AND (g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdPrim_gg00)
    THEN
        BEGIN
        auxError                := e_ok;
        keyTrace.bdkTrType_gg11 := bdtrKey_egg11;
        keyTrace.bdkKeyLen_gg11 := rec.recKeyLen_gg00;
        SAPDB_PascalMove ('VBD30 ',   1,    
              rec.recKeyLen_gg00, sizeof (keyTrace.bdkKey_gg11),
              @rec.recKey_gg00.keyVal_gg00, 1, @keyTrace.bdkKey_gg11, 1,
              gg06Min( rec.recKeyLen_gg00, sizeof( tgg00_VtraceKey )), auxError);
        b120InsertTrace (curr_trans^, bd, b02logadd, sizeof (keyTrace), @keyTrace)
        END;
    (* *)
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  eftsRecordsPacked_egg00 IN currExtendedFileTypeSet_bd00 (* PTS 1139184 *)
        THEN
            pInsRec := bd999PackRow (rec, packedRow)
        ELSE
            pInsRec := @rec;
        (*ENDIF*) 
        CASE searchResult OF
            nonefound :
                bd31AddToLeaf (pInsRec^, nptr, FIRST_REC_INDEX_BD00, neighbs.ln, current,
                      NOT c_withBeforeRef, dummyRef);
            nextfound :
                bd31AddToLeaf (pInsRec^, nptr, recIndex, neighbs.ln, current,
                      NOT c_withBeforeRef, dummyRef);
            lastfound :
                bd31AppendToLeaf (pInsRec^, nptr, recIndex,
                      neighbs.ln, current, NOT c_withBeforeRef, dummyRef);
            OTHERWISE
                trError_gg00 := e_not_implemented
            END;
        (*ENDCASE*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30AddToTreeWithBeforeImage (
            VAR recKey  : tgg00_Lkey;
            VAR rec     : tgg00_Rec;
            VAR m       : tgg00_MessBlock;
            pInsertCmd  : tsp00_Addr;
            grantedLock : tgg00_LockReqMode;
            VAR current : tbd_current_tree);
 
VAR
      auxError          : tgg00_BasisError;
      bCreateSysKey     : boolean;
      bDoLockHandling   : boolean;
      bReadyForInsert   : boolean;
      bFirstTime        : boolean;
      bReplaceRequired  : boolean;
      searchResult      : tbd_searchresult;
      maximumKeyLen     : tsp00_Int4;
      recIndex          : tsp00_Int4;
      recIndexForLeaf   : tsp00_Int4;
      recPos            : tsp00_Int4;
      pInsRec           : tgg00_RecPtr;
      leaf              : tsp00_PageNo;
      pRec              : tsp00_BufAddr;
      nptr              : tbd_node_ptrs;
      neighbs           : tbd_neighbors;
      pTransHistoryInfo : tgg00_ObjTransInfoPtr;
      transHistoryInfo  : tgg00_ObjTransInfo;
      beforeImage       : tgg00_Rec;
      keyTrace          : tgg11_BdKeyTrace;
      packedRow         : tgg00_Rec;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    nptr.np_ptr      := NIL;
    nptr.np_cbptr    := NIL;
    bFirstTime       := true;
    bReadyForInsert  := false;
    bReplaceRequired := false;
    bDoLockHandling  := (NOT bd20IsPageExclusiveLocked (currRootNptrs_bd00.np_cbptr));
    bCreateSysKey    := (m.mb_type2 = mm_nokey);
    IF  bCreateSysKey
    THEN
        BEGIN (* prepare search for greatest key *)
        recKey.keyLen_gg00      := 1;
        recKey.keyVal_gg00[ 1 ] := csp_undef_byte
        END;
    (*ENDIF*) 
    WHILE (trError_gg00 = e_ok) AND NOT bReadyForInsert DO
        BEGIN
        IF  nptr.np_ptr = NIL (* leaf node is not available *)
        THEN
            bd50FindLeaf (recKey.keyVal_gg00, recKey.keyLen_gg00,
                  LOCK_LEAF_EXCL_BD00, nptr, neighbs, recIndexForLeaf, current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b31search_entry (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
                  nptr.np_ptr, recIndex, searchResult);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  searchResult <> thisfound
            THEN
                BEGIN
                IF  bFirstTime
                THEN
                    BEGIN
                    bFirstTime := false;
                    IF  bCreateSysKey
                    THEN
                        bd30_PrepareSyskey (curr_trans^, curr_tree_id, rec,
                              nptr.np_ptr, searchResult, recIndex);
                    (*ENDIF*) 
                    gg06SetNilRef (transHistoryInfo.otrBeforeRef_gg00);
                    transHistoryInfo.otrUpdTransId_gg00 := trWriteTransId_gg00;
                    IF  trError_gg00 = e_ok
                    THEN
                        k61bd_ins (m, pInsertCmd, rec, grantedLock, transHistoryInfo);
                    (*ENDIF*) 
                    IF  bCreateSysKey AND (trError_gg00 = e_ok)
                    THEN
                        BEGIN
                        IF  (g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdPrim_gg00)
                        THEN
                            BEGIN
                            auxError                := e_ok;
                            keyTrace.bdkTrType_gg11 := bdtrKey_egg11;
                            keyTrace.bdkKeyLen_gg11 := rec.recKeyLen_gg00;
                            SAPDB_PascalMove ('VBD30 ',   2,    
                                  rec.recKeyLen_gg00, sizeof (keyTrace.bdkKey_gg11),
                                  @rec.recKey_gg00.keyVal_gg00, 1, @keyTrace.bdkKey_gg11, 1,
                                  gg06Min( rec.recKeyLen_gg00, sizeof( tgg00_VtraceKey )), auxError);
                            b120InsertTrace (curr_trans^, bd, b02logadd, sizeof (keyTrace), @keyTrace)
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                recPos := nptr.np_ptr^.nd_pointer_list[ MAX_POINTERINDEX_BD00 - recIndex ];
                pRec   := @nptr.np_ptr^.nd_body[ recPos ];
                IF  m.mb_type2 <> mm_compare_record
                THEN
                    IF  NOT bd999IsRowDeleted(pRec)
                    THEN
                        trError_gg00 := e_duplicate_key
                    ELSE
                        BEGIN
                        recPos := 1;
                        bd999CopyRecord (@pRec^, NOT c_withBeforeRef,
                              sizeof(beforeImage), @beforeImage, recPos, trError_gg00);
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            bReplaceRequired   := true;
                            pTransHistoryInfo := bd999GetTransHistoryInfo(pRec);
                            transHistoryInfo  := pTransHistoryInfo^;
                            kb611ins_AssignBeforeImage (pInsertCmd, beforeImage);
                            k61bd_ins (m, pInsertCmd, rec, grantedLock, transHistoryInfo);
                            END;
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                ELSE
                    BEGIN
                    bd30compare_record (m, @pRec^, packedRow, 1);
                    (* e_duplicate_record OR e_duplicate_key will be returned *)
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        bReadyForInsert := NOT bDoLockHandling;
        IF  (trError_gg00 = e_ok) AND bDoLockHandling
        THEN
            BEGIN
            IF  (
                nptr.np_ptr^.nd_bottom + Data_GetRecLen(@rec) <=
                MAX_BOTTOM_BD00 - ((nptr.np_ptr^.nd_record_cnt+1)*POINTERSIZE_BD00)
                )
                AND
                (
                (nptr.np_ptr^.nd_bottom < NINETY_PERCENT_COV_BD00) OR
                (searchResult <> lastfound                       ) OR
                (nptr.np_ptr^.nd_right <> NIL_PAGE_NO_GG00       )
                )
            THEN
                bReadyForInsert := true (* local update possible *)
            ELSE
                BEGIN
                bDoLockHandling := false;
                maximumKeyLen   := bd30_DetermineMaxKeyLength (nptr.np_ptr);
                b13r_release_node (nptr, current, lru_normal);
                IF  NOT bd50IndexNodeIsSaveForInsert (current,
                    recIndexForLeaf, recKey.keyLen_gg00, maximumKeyLen)
                THEN
                    bd30_LockTreeExclusive (current)
                ELSE
                    BEGIN (* level > FIRST_INDEX_LEVEL_BD00 *)
                    bd30_LockSubTreeExclusive (current);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        bd50DetermineLeafNode (current, @recKey.keyVal_gg00,
                              recKey.keyLen_gg00, recIndexForLeaf, leaf, neighbs.ln);
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            bd13GetNode (current, leaf, plmLock_ebd00, nr_for_update, nptr);
                            IF  trError_gg00 = e_ok
                            THEN
                                BEGIN
                                maximumKeyLen := bd30_DetermineMaxKeyLength (nptr.np_ptr);
                                IF  NOT bd50IndexNodeIsSaveForInsert (current,
                                    recIndexForLeaf, recKey.keyLen_gg00, maximumKeyLen)
                                THEN
                                    BEGIN
                                    b13r_release_node (nptr, current, lru_normal);
                                    bd30_LockTreeExclusive (current)
                                    END
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  eftsRecordsPacked_egg00 in currExtendedFileTypeSet_bd00 (* PTS 1139184 *)
        THEN
            pInsRec := bd999PackRow (rec, packedRow)
        ELSE
            pInsRec := @rec;
        (*ENDIF*) 
        IF  bReplaceRequired
        THEN
            bd31ReplaceInLeaf (pInsRec^, nptr, recIndex, neighbs.ln, current,
                  transHistoryInfo.otrBeforeRef_gg00, trWriteTransId_gg00)
        ELSE
            CASE searchResult OF
                nonefound :
                    bd31AddToLeaf (pInsRec^, nptr, FIRST_REC_INDEX_BD00, neighbs.ln, current,
                          g01ConsistentReadEnabled, transHistoryInfo.otrBeforeRef_gg00);
                nextfound :
                    bd31AddToLeaf (pInsRec^, nptr, recIndex, neighbs.ln, current,
                          g01ConsistentReadEnabled, transHistoryInfo.otrBeforeRef_gg00);
                lastfound :
                    bd31AppendToLeaf (pInsRec^, nptr, recIndex, neighbs.ln, current,
                          g01ConsistentReadEnabled, transHistoryInfo.otrBeforeRef_gg00);
                OTHERWISE
                    trError_gg00 := e_not_implemented
                END;
            (*ENDCASE*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30AddToTreeWithBeforeImageAndSpecialKey (
            VAR recKey  : tgg00_Lkey;
            VAR rec     : tgg00_Rec;
            VAR m       : tgg00_MessBlock;
            pInsertCmd  : tsp00_Addr;
            grantedLock : tgg00_LockReqMode;
            VAR current : tbd_current_tree);
 
VAR
      auxError           : tgg00_BasisError;
      bMaxKeyUsed        : boolean;
      bDoLockHandling    : boolean;
      bReadyForInsert    : boolean;
      bNewTreeAccess     : boolean;
      searchResult       : tbd_searchresult;
      maximumKeyLen      : tsp00_Int4;
      recIndex           : tsp00_Int4;
      recIndexForLeaf    : tsp00_Int4;
      leaf               : tsp00_PageNo;
      pInsRec            : tgg00_RecPtr;
      nptr               : tbd_node_ptrs;
      neighbs            : tbd_neighbors;
      transHistoryInfo   : tgg00_ObjTransInfo;
      keyTrace           : tgg11_BdKeyTrace;
      packedRow          : tgg00_Rec;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    nptr.np_ptr      := NIL;
    nptr.np_cbptr    := NIL;
    bMaxKeyUsed      := true; (* key suffix has trailing MAX_UNIQUE_PRIM_ID_GG00 bytes *)
    bReadyForInsert  := false;
    bDoLockHandling  := (NOT bd20IsPageExclusiveLocked (currRootNptrs_bd00.np_cbptr));
    WHILE (trError_gg00 = e_ok) AND (NOT bReadyForInsert) DO
        BEGIN
        bNewTreeAccess := false;
        IF  nptr.np_ptr = NIL (* leaf node is not available *)
        THEN
            bd50FindLeaf (recKey.keyVal_gg00, recKey.keyLen_gg00,
                  LOCK_LEAF_EXCL_BD00, nptr, neighbs, recIndexForLeaf, current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b31search_entry (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
                  nptr.np_ptr, recIndex, searchResult);
        (*ENDIF*) 
        IF  (e_ok = trError_gg00) AND ((bMaxKeyUsed) OR (thisfound = searchResult))
        THEN
            BEGIN
            bd30_PrepareSpecialKey (current, recKey, nptr, recIndex, searchResult,
                  bMaxKeyUsed, bNewTreeAccess);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  bNewTreeAccess
                THEN
                    BEGIN
                    IF  nptr.np_ptr <> NIL
                    THEN
                        b13r_release_node (nptr, current, lru_normal);
                    (*ENDIF*) 
                    bd30ReleaseSubTree (current)
                    END;
                (*ENDIF*) 
                IF  bMaxKeyUsed
                THEN (* lock tree exclusive to avoid starvation problems *)
                    BEGIN
                    bd30_LockTreeExclusive( current );
                    bDoLockHandling := false;
                    END;
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        bReadyForInsert := (NOT bDoLockHandling) AND (NOT bNewTreeAccess);
        IF  (e_ok = trError_gg00) AND (bDoLockHandling) AND (NOT bNewTreeAccess)
        THEN
            BEGIN
            IF  (
                nptr.np_ptr^.nd_bottom + rec.recLen_gg00 <=
                MAX_BOTTOM_BD00 - ((nptr.np_ptr^.nd_record_cnt+1)*POINTERSIZE_BD00)
                )
                AND
                (
                (nptr.np_ptr^.nd_bottom < NINETY_PERCENT_COV_BD00) OR
                (searchResult <> lastfound                       ) OR
                (nptr.np_ptr^.nd_right <> NIL_PAGE_NO_GG00       )
                )
            THEN
                bReadyForInsert := true (* local update possible and locks suitable *)
            ELSE
                BEGIN
                bDoLockHandling := false;
                maximumKeyLen   := bd30_DetermineMaxKeyLength (nptr.np_ptr);
                b13r_release_node (nptr, current, lru_normal);
                IF  NOT bd50IndexNodeIsSaveForInsert (current,
                    recIndexForLeaf, recKey.keyLen_gg00, maximumKeyLen)
                THEN
                    bd30_LockTreeExclusive (current)
                ELSE
                    BEGIN (* level > FIRST_INDEX_LEVEL_BD00 *)
                    bd30_LockSubTreeExclusive (current);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        bd50DetermineLeafNode (current, @recKey.keyVal_gg00,
                              recKey.keyLen_gg00, recIndexForLeaf, leaf, neighbs.ln);
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            bd13GetNode (current, leaf, plmLock_ebd00, nr_for_update, nptr);
                            IF  trError_gg00 = e_ok
                            THEN
                                BEGIN
                                maximumKeyLen := bd30_DetermineMaxKeyLength (nptr.np_ptr);
                                IF  (NOT bd50IndexNodeIsSaveForInsert (current,
                                    recIndexForLeaf, recKey.keyLen_gg00, maximumKeyLen))
                                    OR
                                    (bd30_SpecialKeyExist (current, recKey, nptr.np_ptr))
                                THEN
                                    BEGIN
                                    b13r_release_node (nptr, current, lru_normal);
                                    bd30_LockTreeExclusive (current)
                                    END
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  (trError_gg00 = e_ok) AND (g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdPrim_gg00)
    THEN
        BEGIN
        auxError                := e_ok;
        keyTrace.bdkTrType_gg11 := bdtrKey_egg11;
        keyTrace.bdkKeyLen_gg11 := rec.recKeyLen_gg00;
        SAPDB_PascalMove ('VBD30 ',   3,    
              rec.recKeyLen_gg00, sizeof (keyTrace.bdkKey_gg11),
              @rec.recKey_gg00.keyVal_gg00, 1, @keyTrace.bdkKey_gg11, 1,
              gg06Min( rec.recKeyLen_gg00, sizeof( tgg00_VtraceKey )), auxError);
        b120InsertTrace (curr_trans^, bd, b02logadd, sizeof (keyTrace), @keyTrace)
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        gg06SetNilRef (transHistoryInfo.otrBeforeRef_gg00);
        transHistoryInfo.otrUpdTransId_gg00 := trWriteTransId_gg00;
        k61bd_ins (m, pInsertCmd, rec, grantedLock, transHistoryInfo);
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  eftsRecordsPacked_egg00 in currExtendedFileTypeSet_bd00 (* PTS 1139184 *)
        THEN
            pInsRec := bd999PackRow (rec, packedRow)
        ELSE
            pInsRec := @rec;
        (*ENDIF*) 
        CASE searchResult OF
            nonefound :
                bd31AddToLeaf (pInsRec^, nptr, FIRST_REC_INDEX_BD00, neighbs.ln, current,
                      g01ConsistentReadEnabled, transHistoryInfo.otrBeforeRef_gg00);
            nextfound :
                bd31AddToLeaf (pInsRec^, nptr, recIndex, neighbs.ln, current,
                      g01ConsistentReadEnabled, transHistoryInfo.otrBeforeRef_gg00);
            lastfound :
                bd31AppendToLeaf (pInsRec^, nptr, recIndex, neighbs.ln, current,
                      g01ConsistentReadEnabled, transHistoryInfo.otrBeforeRef_gg00);
            OTHERWISE
                trError_gg00 := e_not_implemented
            END;
        (*ENDCASE*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30BuildCurrent (
            VAR trans   : tgg00_TransContext;
            VAR fileId  : tgg00_FileId;
            VAR current : tbd_current_tree);
 
BEGIN
bd01SetToNilCurrent (current);
current.curr_trans   := @trans;
current.curr_tree_id := fileId;
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30CheckTree (
            VAR trans           : tgg00_TransContext;
            VAR fileId          : tgg00_FileId;
            VAR treeStatistic   : tbd00_TreeStatistic;
            longColCnt          : tsp00_Int2;
            newLongColCnt       : tsp00_Int2;
            bWithExtendedCheck  : boolean;
            bCheckLongExistence : boolean;
            bQuiet              : boolean;
            bUpdateLeaves       : boolean);
 
VAR
      bDumpPage         : boolean;
      bFileWasBad       : boolean;
      bLongIsBad        : boolean;
      len               : integer;
      scanCount         : tsp00_Int4;
      boundNeighborLeaf : tsp00_PageNo;
      current           : tbd_current_tree;
      msg               : tsp00_C40;
      fileInfo          : tbd_fileinfo;
      reEntranceKey     : tgg00_Lkey;
      checkKey          : tgg00_Lkey;
 
BEGIN
WITH treeStatistic DO
    BEGIN
    ts_IndexPages_bd00  := 0;
    ts_LeafPages_bd00   := 0;
    ts_RecordCount_bd00 := 0;
    END;
(*ENDWITH*) 
bDumpPage                 := false;
bFileWasBad               := false;
bLongIsBad                := false;
boundNeighborLeaf         := NIL_PAGE_NO_GG00;
reEntranceKey.keyLen_gg00 := 0;
WITH trans DO
    BEGIN
    b17state_fdir (fileId.fileName_gg00, fileInfo,
          ftsShared_egg00 IN fileId.fileType_gg00, trans);
    IF  (trError_gg00 = e_ok) AND (f_bad IN fileInfo.fi_state)
    THEN
        bFileWasBad := true;
    (*ENDIF*) 
    REPEAT
        IF  b01downfilesystem
        THEN
            trError_gg00 := e_shutdown
        ELSE
            BEGIN
            trError_gg00                     := e_ok;
            scanCount                        := 0;
            checkKey.keyLen_gg00             := 0;
            boundNeighborLeaf                := NIL_PAGE_NO_GG00;
            fileId.fileVersion_gg00.ci2_gg00 := cgg_dummy_file_version;
            fileId.fileLeafNodes_gg00        := cgg_nil_leafnodes;
            bd30GetTree (trans, fileId, current, m_verify,
                  NOT LOCK_TREE_EXCL_BD00, NOT SYNC_TREE_LOCK_BD00);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  (reEntranceKey.keyLen_gg00 = 0) AND (NOT bQuiet)
                THEN
                    b06file_opmsg (csp3_check_file, current.curr_tree_id);
                (*ENDIF*) 
                bFileWasBad :=  bFileWasBad OR (f_bad IN current.currRootNptrs_bd00.np_ptr^.nd_file_state);
                IF  bCheckLongExistence
                THEN
                    bd998SetLobPageCount (trans, current.curr_tree_id.fileTabId_gg00, 0);
                (*ENDIF*) 
                bd50CheckSubTree (current.curr_tree_id.fileRoot_gg00, NIL_PAGE_NO_GG00,
                      longColCnt, newLongColCnt, scanCount, boundNeighborLeaf, bDumpPage, bLongIsBad,
                      reEntranceKey, checkKey, current, treeStatistic, bWithExtendedCheck,
                      bCheckLongExistence, bUpdateLeaves );
                END;
            (*ENDIF*) 
            bd30ReleaseTree (current);
            IF  trError_gg00 = e_bd_leaf_unlocked
            THEN
                BEGIN
                fileId.fileRoot_gg00 := NIL_PAGE_NO_GG00; (* PTS 1124752 TS 2003-10-22 *)
                vsleep (trTaskId_gg00, 0)
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
    UNTIL
        trError_gg00 <> e_bd_leaf_unlocked;
    (*ENDREPEAT*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        fileId := current.curr_tree_id;
        IF  bFileWasBad
        THEN
            bd30ResetBadFile (trans, fileId)
        (*ENDIF*) 
        END
    ELSE
        IF  (trError_gg00 <> e_disk_not_accessible) AND
            (trError_gg00 <> e_cancelled          ) AND
            (trError_gg00 <> e_shutdown           )
        THEN
            BEGIN
            b06write_filename_and_root( current.curr_tree_id );
            msg := bsp_c40;
            len := 0;
            g17nameto_line ('Base error:       ', len, msg);
            len := len + 1;
            g17basis_err_to_line (trError_gg00, len, msg);
            g01optextmsg (sp3p_console, sp3m_error, csp3_bd30_2_bad_file, csp3_n_btree, msg);
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND bLongIsBad
    THEN
        trError_gg00 := e_bad_file
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30DelFromTree (
            VAR recKey  : tgg00_Lkey;
            VAR current : tbd_current_tree);
 
VAR
      nilRef : tgg91_PageRef;
 
BEGIN
gg06SetNilRef (nilRef);
bd30DelGarbageFromTree (recKey, current, nilRef);
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30DelGarbageFromTree (
            VAR recKey    : tgg00_Lkey;
            VAR current   : tbd_current_tree;
            VAR wantedRef : tgg91_PageRef);
 
VAR
      bDoLockHandling : boolean;
      bReadyForDelete : boolean;
      searchResult    : tbd_searchresult;
      maximumKeyLen   : tsp00_Int4;
      recIndex        : tsp00_Int4;
      recIndexForLeaf : tsp00_Int4;
      leaf            : tsp00_PageNo;
      nptr            : tbd_node_ptrs;
      neighbs         : tbd_neighbors;
      pRec            : tgg00_RecPtr;
      pHistoryInfo    : tgg00_ObjTransInfoPtr;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    nptr.np_ptr     := NIL;
    nptr.np_cbptr   := NIL;
    bReadyForDelete := false;
    bDoLockHandling := (NOT bd20IsPageExclusiveLocked (currRootNptrs_bd00.np_cbptr));
    WHILE (trError_gg00 = e_ok) AND NOT bReadyForDelete DO
        BEGIN
        IF  nptr.np_ptr = NIL (* leaf node is not available *)
        THEN
            bd50FindLeaf (recKey.keyVal_gg00, recKey.keyLen_gg00,
                  LOCK_LEAF_EXCL_BD00, nptr, neighbs, recIndexForLeaf, current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b31search_entry (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
                  nptr.np_ptr, recIndex, searchResult);
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (searchResult <> thisfound)
        THEN
            trError_gg00 := e_key_not_found;
        (*ENDIF*) 
        bReadyForDelete := NOT bDoLockHandling;
        IF  (trError_gg00 = e_ok) AND bDoLockHandling
        THEN
            BEGIN
            WITH nptr.np_ptr^ DO
                pRec := @nd_body [ nd_pointer_list[ MAX_POINTERINDEX_BD00 - recIndex ]];
            (*ENDWITH*) 
            IF  (
                (nptr.np_ptr^.nd_bottom - Data_GetRecLen(pRec) - BODY_BEG_BD00 +
                ((nptr.np_ptr^.nd_record_cnt -1) * POINTERSIZE_BD00)) >= HALF_COVERING_BD00
                )
                OR
                (nptr.np_ptr^.nd_id = fileRoot_gg00)
            THEN
                bReadyForDelete := true (* local delete possible *)
            ELSE
                BEGIN
                bDoLockHandling := false;
                maximumKeyLen   := bd30_DetermineMaxKeyLength (nptr.np_ptr);
                b13r_release_node (nptr, current, lru_normal);
                IF  NOT bd50IndexNodeIsSaveForDelete (current, recIndexForLeaf, maximumKeyLen)
                THEN
                    bd30_LockTreeExclusive (current)
                ELSE
                    BEGIN (* level > FIRST_INDEX_LEVEL_BD00 *)
                    bd30_LockSubTreeExclusive (current);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        bd50DetermineLeafNode (current, @recKey.keyVal_gg00,
                              recKey.keyLen_gg00, recIndexForLeaf, leaf, neighbs.ln);
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            bd13GetNode (current, leaf, plmLock_ebd00, nr_for_update, nptr);
                            IF  trError_gg00 = e_ok
                            THEN
                                BEGIN
                                maximumKeyLen := bd30_DetermineMaxKeyLength (nptr.np_ptr);
                                IF  NOT bd50IndexNodeIsSaveForDelete (current, recIndexForLeaf,
                                    maximumKeyLen)
                                THEN
                                    BEGIN
                                    b13r_release_node (nptr, current, lru_normal);
                                    bd30_LockTreeExclusive (current)
                                    END
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  NOT gg06IsNilRef (wantedRef)
        THEN
            BEGIN
            pHistoryInfo := bd999GetTransHistoryInfo (@pRec^);
            IF  pHistoryInfo <> NIL
            THEN
                BEGIN
                IF  pHistoryInfo^.otrBeforeRef_gg00 <> wantedRef
                THEN
                    trError_gg00 := e_key_not_found
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b31del_from_leaf (nptr, recIndex, neighbs.ln, current);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30DelFromTreeWithBeforeImage (
            VAR recKey  : tgg00_Lkey;
            VAR oldRec  : tgg00_Rec;
            VAR m       : tgg00_MessBlock;
            pDeleteCmd  : tsp00_Addr;
            grantedLock : tgg00_LockReqMode;
            VAR current : tbd_current_tree);
 
VAR
      bDoLockHandling : boolean;
      bReadyForDelete : boolean;
      bFirstTime      : boolean;
      searchResult    : tbd_searchresult;
      maximumKeyLen   : tsp00_Int4;
      recIndex        : tsp00_Int4;
      recIndexForLeaf : tsp00_Int4;
      recPos          : tsp00_Int4;
      leaf            : tsp00_PageNo;
      nptr            : tbd_node_ptrs;
      neighbs         : tbd_neighbors;
      pRec            : tgg00_RecPtr;
      transHistoryInfo: tgg00_ObjTransInfo;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    nptr.np_ptr     := NIL;
    nptr.np_cbptr   := NIL;
    bFirstTime      := true;
    bReadyForDelete := false;
    bDoLockHandling := (NOT bd20IsPageExclusiveLocked (currRootNptrs_bd00.np_cbptr));
    WHILE (trError_gg00 = e_ok) AND NOT bReadyForDelete DO
        BEGIN
        IF  nptr.np_ptr = NIL (* leaf node is not available *)
        THEN
            bd50FindLeaf (recKey.keyVal_gg00, recKey.keyLen_gg00,
                  LOCK_LEAF_EXCL_BD00, nptr, neighbs, recIndexForLeaf, current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b31search_entry (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
                  nptr.np_ptr, recIndex, searchResult);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  searchResult <> thisfound
            THEN
                trError_gg00 := e_key_not_found
            ELSE
                IF  bFirstTime
                THEN
                    BEGIN
                    bFirstTime := false;
                    recPos     := nptr.np_ptr^.nd_pointer_list[ MAX_POINTERINDEX_BD00 - recIndex ];
                    pRec       := @nptr.np_ptr^.nd_body [ recPos ];
                    bd999CopyRecordAndTransHistoryInfo (pRec, transHistoryInfo, oldRec, trError_gg00);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        k61bd_del (m, pDeleteCmd, oldRec, transHistoryInfo, grantedLock);
&                       ifdef TRACE
                        t01buf (bi, oldRec, 1, oldRec.recLen_gg00);
&                       endif
                        END
                    ELSE
                        BEGIN
                        trError_gg00 := e_data_page_corrupted;
                        b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                              nptr.np_ptr^.nd_id, nptr.np_ptr, 1)
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        bReadyForDelete := NOT bDoLockHandling;
        IF  (trError_gg00 = e_ok) AND bDoLockHandling
        THEN
            BEGIN
            WITH nptr.np_ptr^ DO
                pRec := @nd_body [ nd_pointer_list[ MAX_POINTERINDEX_BD00 - recIndex ]];
            (*ENDWITH*) 
            IF  (
                (nptr.np_ptr^.nd_bottom - Data_GetRecLen(pRec) - BODY_BEG_BD00 +
                ((nptr.np_ptr^.nd_record_cnt -1) * POINTERSIZE_BD00)) >= HALF_COVERING_BD00
                )
                OR
                (nptr.np_ptr^.nd_id = fileRoot_gg00)
            THEN
                bReadyForDelete := true (* local delete possible *)
            ELSE
                BEGIN
                bDoLockHandling := false;
                maximumKeyLen   := bd30_DetermineMaxKeyLength (nptr.np_ptr);
                b13r_release_node (nptr, current, lru_normal);
                IF  NOT bd50IndexNodeIsSaveForDelete (current, recIndexForLeaf, maximumKeyLen)
                THEN
                    bd30_LockTreeExclusive (current)
                ELSE
                    BEGIN (* level > FIRST_INDEX_LEVEL_BD00 *)
                    bd30_LockSubTreeExclusive (current);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        bd50DetermineLeafNode (current, @recKey.keyVal_gg00,
                              recKey.keyLen_gg00, recIndexForLeaf, leaf, neighbs.ln);
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            bd13GetNode (current, leaf, plmLock_ebd00, nr_for_update, nptr);
                            IF  trError_gg00 = e_ok
                            THEN
                                BEGIN
                                maximumKeyLen := bd30_DetermineMaxKeyLength (nptr.np_ptr);
                                IF  NOT bd50IndexNodeIsSaveForDelete (current, recIndexForLeaf,
                                    maximumKeyLen)
                                THEN
                                    BEGIN
                                    b13r_release_node (nptr, current, lru_normal);
                                    bd30_LockTreeExclusive (current)
                                    END
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  trError_gg00 = e_ok
    THEN
        b31del_from_leaf (nptr, recIndex, neighbs.ln, current);
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30DropTree (
            VAR current     : tbd_current_tree;
            longColumnCount : integer;
            bOnlyEmpty      : boolean);
 
VAR
      bIsPerm : boolean;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    bIsPerm := ftsPerm_egg00 IN fileType_gg00;
    IF  (fileRoot_gg00 = bd17GetBlobFdirRoot) AND (bIsPerm)
    THEN
        trError_gg00 := e_do_not_drop_fdir;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  (bIsPerm) AND (NOT bOnlyEmpty)
        THEN (* avoid prolonged blockade of SVP if root is already marked as changed *)
            bd13WriteExclusiveLockedRoot (curr_trans^, curr_tree_id, currRootNptrs_bd00);
        (*ENDIF*) 
        bd50DropSubTree (fileRoot_gg00, longColumnCount, bOnlyEmpty, current);
        END;
    (*ENDIF*) 
    IF  (trError_gg00 <> e_disk_not_accessible) AND
        (trError_gg00 <> e_do_not_drop_fdir   ) AND
        (trError_gg00 <> e_ok                 )
    THEN
        BEGIN
        IF  ftsPerm_egg00 IN fileType_gg00
        THEN
            BEGIN
            g01opmsg (sp3p_knldiag, sp3m_info, bd30ErrorDuringDrop_csp03,
                  csp3_n_btree, MSG_1_DROP, trError_gg00);
            g01optextmsg (sp3p_knldiag, sp3m_info, bd30ErrorDuringDrop_csp03,
                  csp3_n_btree, MSG_2_DROP)
            END;
        (*ENDIF*) 
        trError_gg00 := e_ok
        END;
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND bOnlyEmpty
    THEN
        BEGIN
        bd998SetPageAndRecordCount (curr_trans^, fileTabId_gg00, 1, 0, 0);
        trError_gg00 := e_ok;
        END;
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30ExistRecord (
            VAR recKey  : tgg00_Lkey;
            VAR current : tbd_current_tree);
 
VAR
      searchResult : tbd_searchresult;
      recIndex     : tsp00_Int4;
      nptr         : tbd_node_ptrs;
      neighbs      : tbd_neighbors;
 
BEGIN
WITH current, curr_trans^  DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    bd30SearchRecord (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
          NOT LOCK_LEAF_EXCL_BD00, nptr, recIndex, neighbs, searchResult);
    IF  (trError_gg00 = e_ok) AND (searchResult <> thisfound)
    THEN
        trError_gg00 := e_key_not_found;
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30FindLeaf (
            VAR key     : tgg00_Lkey;
            VAR current : tbd_current_tree);
 
VAR
      recIndexForLeaf : tsp00_Int4;
      nptr            : tbd_node_ptrs;
      neighbs         : tbd_neighbors;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    IF  trError_gg00 = e_ok
    THEN
        bd50FindLeaf (key.keyVal_gg00, key.keyLen_gg00, NOT LOCK_LEAF_EXCL_BD00,
              nptr, neighbs, recIndexForLeaf, current);
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30GetFromTreeWithTreepos (
            VAR recKey   : tgg00_Lkey;
            VAR rec      : tgg00_Rec;
            VAR tree_pos : tgg00_FilePos;
            VAR current  : tbd_current_tree;
            wantedLock   : tgg00_LockReqMode);
 
VAR
      searchResult : tbd_searchresult;
      recIndex     : tsp00_Int4;
      nptr         : tbd_node_ptrs;
      neighbs      : tbd_neighbors;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    bd30SearchRecord (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
          NOT LOCK_LEAF_EXCL_BD00, nptr, recIndex, neighbs, searchResult);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  searchResult <> thisfound
        THEN
            trError_gg00 := e_key_not_found
        ELSE
            BEGIN
            tree_pos.tpsPno_gg00   := nptr.np_ptr^.nd_id;
            tree_pos.tpsIndex_gg00 := recIndex;
            b31get_from_leaf (nptr, recIndex, wantedLock <> lckFree_egg00,
                  rec, current);
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30GetFromTree (
            VAR recKey  : tgg00_Lkey;
            VAR rec     : tgg00_Rec;
            VAR current : tbd_current_tree;
            wantedLock  : tgg00_LockReqMode);
 
VAR
      searchResult : tbd_searchresult;
      recIndex     : tsp00_Int4;
      nptr         : tbd_node_ptrs;
      neighbs      : tbd_neighbors;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    bd30SearchRecord (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
          NOT LOCK_LEAF_EXCL_BD00, nptr, recIndex, neighbs, searchResult);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  searchResult <> thisfound
        THEN
            trError_gg00 := e_key_not_found
        ELSE
            BEGIN
            b31get_from_leaf (nptr, recIndex, wantedLock <> lckFree_egg00,
                  rec, current);
            IF  bd999IsRowDeleted (@rec) (* TODO, real consistent read ?? *)
            THEN
                trError_gg00 := e_key_not_found
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30GetNextLeafPage (
            VAR nextLeafPage : tsp00_PageNo;
            VAR nptr         : tbd_node_ptrs;
            VAR current      : tbd_current_tree);
 
VAR
      recIndexForLeaf : tsp00_Int4;
      nextIndexPage   : tsp00_PageNo;
      neighbs         : tbd_neighbors;
      startKey        : tgg00_Lkey;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    IF  nextLeafPage = curr_tree_id.fileRoot_gg00
    THEN
        BEGIN (* first access *)
        startKey.keyLen_gg00 := 0;
        bd50FindLeaf (startKey.keyVal_gg00, startKey.keyLen_gg00,
              NOT LOCK_LEAF_EXCL_BD00, nptr, neighbs, recIndexForLeaf, current)
        END
    ELSE
        BEGIN
        nextIndexPage := NIL_PAGE_NO_GG00;
        IF  nptr.np_ptr <> NIL
        THEN
            BEGIN
            IF  (ftsPerm_egg00 IN curr_tree_id.fileType_gg00) AND
                (currRightBound_bd00 = nptr.np_ptr^.nd_id   ) AND
                (currIndexNptrs_bd00.np_ptr <> NIL          )
            THEN
                nextIndexPage := currIndexNptrs_bd00.np_ptr^.nd_right;
            (*ENDIF*) 
            b13r_release_node (nptr, current, lru_last);
            END;
        (*ENDIF*) 
        IF  nextIndexPage <> NIL_PAGE_NO_GG00
        THEN
            BEGIN
            bd30ReleaseSubTree (current);
            bd30GetSubTree (current, nextIndexPage)
            END;
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (nextLeafPage <> NIL_PAGE_NO_GG00)
        THEN
            bd13GetNode (current, nextLeafPage, plmLock_ebd00, nr_for_read, nptr)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        IF  trError_gg00 = e_ok
        THEN
            nextLeafPage := nptr.np_ptr^.nd_right
        ELSE
            b13r_release_node (nptr, current, lru_normal)
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30GetNextLong (
            VAR recKey      : tgg00_Lkey;
            numberOfLongs   : integer;
            VAR currentLong : integer;
            VAR longFileId  : tgg00_FileId;
            VAR filePos     : tgg00_FilePos;
            VAR current     : tbd_current_tree);
 
VAR
      bFound       : boolean;
      searchResult : tbd_searchresult;
      recPos       : tsp00_Int4;
      longPos      : tsp00_Int4;
      recIndex     : tsp00_Int4;
      nextLeaf     : tsp00_PageNo;
      nptr         : tbd_node_ptrs;
      longFileInfo : tbd_fileinfo;
      neighbs      : tbd_neighbors;
      pRec         : tgg00_RecPtr;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    bFound        := false;
    IF  filePos.tpsPno_gg00 = NIL_PAGE_NO_GG00
    THEN
        BEGIN
        bd30SearchRecord (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
              NOT LOCK_LEAF_EXCL_BD00, nptr, recIndex, neighbs, searchResult);
        IF  (trError_gg00 = e_ok) AND (searchResult = nonefound)
        THEN
            trError_gg00 := e_no_next_record
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        bd13GetNode (current, filePos.tpsPno_gg00, plmLock_ebd00, nr_for_read, nptr);
        recIndex  := filePos.tpsIndex_gg00
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        REPEAT
            WHILE (recIndex < nptr.np_ptr^.nd_record_cnt) AND (NOT bFound) DO
                WITH nptr, np_ptr^ DO
                    BEGIN
                    recPos      := nd_pointer_list[ MAX_POINTERINDEX_BD00 - recIndex ];
                    pRec        := @nptr.np_ptr^.nd_body [ recPos ];
                    longPos     := recPos + cgg_rec_key_offset + pRec^.recKeyLen_gg00;
                    longPos     := longPos + currentLong *  cgg_col_fd_size;
                    currentLong := currentLong + 1;
                    (* *)
                    WHILE (currentLong <= numberOfLongs) AND (NOT bFound) DO
                        BEGIN
                        IF  nd_body[longPos] = csp_undef_byte
                        THEN
                            BEGIN
                            longPos     := longPos +  cgg_col_fd_size;
                            currentLong := currentLong + 1
                            END
                        ELSE
                            BEGIN
                            longFileId               := b01niltree_id;
                            longFileId.fileTfn_gg00  := tfnColumn_egg00;
                            longFileId.fileType_gg00 := [ftsByteStr_egg00, ftsConcurrent_egg00];
                            SAPDB_PascalMove ('VBD30 ',   4,    
                                  sizeof (np_ptr^), sizeof (longFileId.fileName_gg00),
                                  @np_ptr^, longPos + 1,
                                  @longFileId.fileName_gg00, 3, SURROGATE_MXGG00, trError_gg00);
                            IF  trError_gg00 = e_move_error
                            THEN
                                BEGIN
                                trError_gg00 := e_data_page_corrupted;
                                b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1)
                                END
                            ELSE
                                b17state_fdir (longFileId.fileName_gg00, longFileInfo,
                                      ftsShared_egg00 in longFileId.fileType_gg00, curr_trans^);
                            (*ENDIF*) 
                            IF  trError_gg00 = e_ok
                            THEN
                                bFound := true
                            ELSE
                                BEGIN
                                IF  trError_gg00 = e_file_not_found
                                THEN
                                    trError_gg00 := e_ok;
                                (*ENDIF*) 
                                longPos     := longPos + cgg_col_fd_size;
                                currentLong := currentLong + 1
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END;
                    (*ENDWHILE*) 
                    IF  bFound AND (trError_gg00 = e_ok)
                    THEN
                        BEGIN
                        filePos.tpsIndex_gg00 := recIndex;
                        filePos.tpsPno_gg00   := nd_id;
                        recKey.keyLen_gg00    := pRec^.recKeyLen_gg00;
                        SAPDB_PascalMove ('VBD30 ',   5,    
                              sizeof (np_ptr^), recKey.keyLen_gg00,
                              @np_ptr^, recPos + cgg_rec_key_offset,
                              @recKey.keyVal_gg00, 1, recKey.keyLen_gg00, trError_gg00);
                        IF  trError_gg00 = e_move_error
                        THEN
                            BEGIN
                            trError_gg00 := e_data_page_corrupted;
                            b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1)
                            END
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        currentLong := 0;
                        recIndex    := recIndex + 1
                        END
                    (*ENDIF*) 
                    END;
                (*ENDWITH*) 
            (*ENDWHILE*) 
            IF  (NOT bFound) AND (trError_gg00 = e_ok)
            THEN
                BEGIN
                nextLeaf := nptr.np_ptr^.nd_right;
                b13r_release_node (nptr, current, lru_last);
                IF  nextLeaf <> NIL_PAGE_NO_GG00
                THEN
                    bd13GetNode (current, nextLeaf, plmLock_ebd00, nr_for_read, nptr)
                ELSE
                    trError_gg00 := e_no_next_record;
                (*ENDIF*) 
                recIndex := FIRST_REC_INDEX_BD00
                END
            (*ENDIF*) 
        UNTIL
            (trError_gg00 <> e_ok) OR bFound;
        (*ENDREPEAT*) 
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30NewTree (
            VAR trans            : tgg00_TransContext;
            VAR fileId           : tgg00_FileId;
            VAR current          : tbd_current_tree;
            bLockTreeExcl        : boolean;
            bSynchronizeTreeLock : boolean);
 
VAR
      nodeRequest         : tbd_node_request;
      rootSynchronizeMode : tbd00_PageLockMode;
      pNewNodes           : tbd_node_ptrs;
 
BEGIN
IF  ftsPerm_egg00 IN fileId.fileType_gg00
THEN
    fileId.fileType_gg00 := fileId.fileType_gg00 + [ftsConcurrent_egg00];
(*ENDIF*) 
fileId.fileRoot_gg00 := NIL_PAGE_NO_GG00;
bd01SetToNilCurrent (current);
WITH current DO
    BEGIN
    curr_trans         := @trans;
    curr_tree_id       := fileId;
    curr_action        := m_create_table;
    pNewNodes.np_ptr   := NIL;
    pNewNodes.np_cbptr := NIL;
    (* *)
    b13new_root (pNewNodes, current);
    (* *)
    IF  trans.trError_gg00 = e_ok
    THEN
        BEGIN
        WITH pNewNodes.np_ptr^ DO
            BEGIN
            curr_tree_id.fileRoot_gg00 := nd_id;
            IF  kb560IsCatalogTable (curr_tree_id.fileTabId_gg00)
            THEN
                BEGIN
                nd_pmode   := nd_pmode + [pmCatalog_egg00];
                nd_trailer := nd_header
                END;
            (*ENDIF*) 
            bd300SetRootCheck (curr_tree_id);
            b13w_release_node (pNewNodes, current);
            fileId := curr_tree_id;
            END;
        (*ENDWITH*) 
        (* Get access to new root page. Beware that the page *)
        (* is changed in the data cache !                    *)
        IF  bSynchronizeTreeLock
        THEN
            rootSynchronizeMode := plmLockWithSVPSync_ebd00
        ELSE
            rootSynchronizeMode := plmLock_ebd00;
        (*ENDIF*) 
        IF  bLockTreeExcl
        THEN
            nodeRequest := nr_for_update
        ELSE
            nodeRequest := nr_for_read;
        (*ENDIF*) 
        bd13GetNode (current, fileId.fileRoot_gg00, rootSynchronizeMode,
              nodeRequest, currRootNptrs_bd00);
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30GetTree (
            VAR trans            : tgg00_TransContext;
            VAR fileId           : tgg00_FileId;
            VAR current          : tbd_current_tree;
            messType             : tgg00_MessType;
            bLockTreeExcl        : boolean;
            bSynchronizeTreeLock : boolean);
 
VAR
      bFileDirAvailable : boolean;
      bUseLOBDir        : boolean;
      bStopLoop         : boolean;
      fileState         : tbd_file_state_set;
      fileVersion       : tgg91_FileVersion;
 
BEGIN
bStopLoop           := false;
bd01SetToNilCurrent (current);
current.curr_trans  := @trans;
current.curr_action := messType;
(* DANGER: in case of drop and create the Set is not available! TODO *)
bFileDirAvailable   :=
      (NOT (bd_release_acc IN fileId.fileBdUse_gg00)) AND
      (m_create_table <> messType) AND (fileId.fileRoot_gg00 <> bd17GetBlobFdirRoot);
bUseLOBDir := (fileId.fileTfn_gg00 = tfnColumn_egg00) OR
      (fileId.fileTfn_gg00 = tfnAux_egg00) OR (fileId.fileTfn_gg00 = tfnTempAux_egg00);
WITH trans DO
    BEGIN
    IF  fileId.fileRoot_gg00 <> NIL_PAGE_NO_GG00
    THEN
        BEGIN
        IF  fileId.fileRootCheck_gg00 <> ROOT_CHECK_GG00
        THEN
            bd300FileIdRootCheck (fileId, trError_gg00)
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  bUseLOBDir
        THEN
            bd17GetBlobFileInfo (trans, fileId, fileVersion, fileState)
        ELSE
            bd998GetFileInfo (trans, fileId.fileTabId_gg00, fileId,
                  fileVersion, fileState);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  ftsConcurrent_egg00 IN fileId.fileType_gg00
            THEN
                BEGIN
                IF  (fileId.fileVersion_gg00          <> fileVersion           ) AND
                    (fileId.fileVersion_gg00.ci2_gg00 <> cgg_dummy_file_version)
                THEN
                    trError_gg00 := e_old_fileversion
                ELSE
                    IF  (ftsByteStr_egg00 IN fileId.fileType_gg00) AND
                        (fileId.fileRoot_gg00 = NIL_PAGE_NO_GG00 )
                    THEN
                        trError_gg00 := e_file_empty
                    ELSE
                        IF  bd_write_acc IN fileId.fileBdUse_gg00
                        THEN
                            BEGIN
                            IF  f_bad IN fileState
                            THEN
                                BEGIN
                                trError_gg00 := e_bad_file;
                                b06file_opmsg (csp3_bd30_1_bad_file, fileId);
                                END
                            ELSE
                                IF  (
                                    (f_read_only IN fileState                       ) AND
                                    (NOT (bd_load_nolog IN fileId.fileBdUse_gg00   )) AND
                                    (NOT (hsNoLog_egg00 IN fileId.fileHandling_gg00))
                                    )
                                THEN
                                    trError_gg00 := e_file_read_only
                                ELSE
                                    IF  (hsNoLog_egg00 IN fileId.fileHandling_gg00  ) AND
                                        (NOT (ftsTemp_egg00 IN fileId.fileType_gg00)) AND
                                        (NOT(f_read_only IN fileState              ))
                                    THEN
                                        bd30SetReadOnly (trans, fileId)
                                    (*ENDIF*) 
                                (*ENDIF*) 
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND (bFileDirAvailable) AND (NOT bUseLOBDir)
    THEN
        BEGIN
        WITH current DO
            bd998GetExtendedFiletypeSet (curr_trans^, fileId.fileTabId_gg00, currExtendedFileTypeSet_bd00);
        (*ENDWITH*) 
        trError_gg00 := e_ok; (* TODO *)
        END;
    (*ENDIF*) 
    WHILE  (trError_gg00 = e_ok) AND NOT bStopLoop DO
        WITH current DO
            BEGIN
            curr_tree_id := fileId;
            IF  bSynchronizeTreeLock
            THEN
                currRootPageLockMode_bd00 := plmLockWithSVPSync_ebd00
            ELSE
                currRootPageLockMode_bd00 := plmLock_ebd00;
            (*ENDIF*) 
            IF  bLockTreeExcl
            THEN
                bd13GetNode (current, fileId.fileRoot_gg00, currRootPageLockMode_bd00,
                      nr_for_update, currRootNptrs_bd00)
            ELSE
                bd13GetNode (current, fileId.fileRoot_gg00, currRootPageLockMode_bd00,
                      nr_for_read, currRootNptrs_bd00);
            (*ENDIF*) 
            IF  trError_gg00 = e_file_must_be_read_only
            THEN
                BEGIN
                trError_gg00 := e_ok;
                bd30ReleaseTree (current);
                bd30SetReadOnly (trans, fileId)
                END
            ELSE
                bStopLoop := true; (* common case *)
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
    (*ENDWHILE*) 
&   ifdef torsten
    IF  trError_gg00 = e_ok
    THEN
        bd30_CheckStatisticCounter (current, c_bIsGetTree);
&   endif
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30GetSubTree (
            VAR current : tbd_current_tree;
            indexPageNo : tsp00_PageNo);
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    bd13GetNode (current, indexPageNo, plmLock_ebd00,
          nr_for_read, currIndexNptrs_bd00);
    IF  trError_gg00 = e_ok
    THEN
        WITH currIndexNptrs_bd00 DO
            BEGIN
            currLeftBound_bd00  := bd52SubtreePno (np_ptr, FIRST_REC_INDEX_BD00);
            currRightBound_bd00 := bd52SubtreePno (np_ptr, np_ptr^.nd_record_cnt - 1);
            IF  np_ptr^.nd_level <> FIRST_INDEX_LEVEL_BD00
            THEN
                g01abort (bd30x1IllegalLockHandling_csp03, csp3_n_btree,
                      MSG_WRONG_LEVEL, np_ptr^.nd_level);
            (*ENDIF*) 
            IF  indexPageNo = curr_tree_id.fileRoot_gg00
            THEN
                g01abort (bd30x1IllegalLockHandling_csp03, csp3_n_btree,
                      MSG_2_WRONG_LEVEL, indexPageNo);
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
&   ifdef TRACE
    (*ENDIF*) 
    t01int4 (bd_index,   'indexNode   ', indexPageNo);
    t01p2int4 (bd_index, 'currLeft    ', currLeftBound_bd00, 'currRight   ', currRightBound_bd00);
&   endif
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30MarkDeletedFromTree (
            VAR recKey    : tgg00_Lkey;
            VAR current   : tbd_current_tree;
            markForDelete : boolean;
            VAR beforeRef : tgg91_PageRef;
            VAR updTrans  : tgg91_TransNo;
            pRec          : tgg00_RecPtr);
 
VAR
      searchResult    : tbd_searchresult;
      pos             : tsp00_Int4;
      recIndex        : tsp00_Int4;
      recIndexForLeaf : tsp00_Int4;
      nptr            : tbd_node_ptrs;
      neighbs         : tbd_neighbors;
      pRecord         : tgg00_RecPtr;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    nptr.np_ptr     := NIL;
    nptr.np_cbptr   := NIL;
    bd50FindLeaf (recKey.keyVal_gg00, recKey.keyLen_gg00,
          LOCK_LEAF_EXCL_BD00, nptr, neighbs, recIndexForLeaf, current);
    IF  trError_gg00 = e_ok
    THEN
        b31search_entry (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
              nptr.np_ptr, recIndex, searchResult);
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND (searchResult <> thisfound)
    THEN
        trError_gg00 := e_key_not_found;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        WITH nptr.np_ptr^ DO
            pRecord := @nd_body [ nd_pointer_list[ MAX_POINTERINDEX_BD00 - recIndex ]];
        (*ENDWITH*) 
        bd999MarkRowDeleted (curr_trans^, nptr.np_ptr^, pRecord, beforeRef, updTrans, markForDelete);
        IF  pRec <> NIL
        THEN
            BEGIN
            pos := 1;
            bd999CopyRecord (pRecord, false, sizeof(pRec^), @pRec^, pos, trError_gg00);
            END;
        (*ENDIF*) 
        b13w_release_node (nptr, current);
        END;
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30NextFromTree (
            VAR recKey   : tgg00_Lkey;
            bInclusive   : boolean;
            bWithSQLLock : boolean;
            VAR rec      : tgg00_Rec;
            VAR current  : tbd_current_tree);
 
VAR
      searchResult : tbd_searchresult;
      recIndex     : tsp00_Int4;
      nptr         : tbd_node_ptrs;
      neighbs      : tbd_neighbors;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    bd30SearchRecord (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
          NOT LOCK_LEAF_EXCL_BD00, nptr, recIndex, neighbs, searchResult);
    IF  (trError_gg00 = e_ok) AND (searchResult = nonefound)
    THEN
        trError_gg00 := e_no_next_record;
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND (searchResult <> nextfound)
        AND
        (NOT bInclusive OR (searchResult = lastfound))
    THEN
        b31next_search (nptr, recIndex, current, lru_normal);
    (*might return b_no_next_record*)
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        b31get_from_leaf (nptr, recIndex, bWithSQLLock, rec, current);
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND (searchResult <> thisfound)
    THEN
        trError_gg00 := e_key_not_found;
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30PrevFromTree (
            VAR recKey   : tgg00_Lkey;
            bInclusive   : boolean;
            bWithSQLLock : boolean;
            VAR rec      : tgg00_Rec;
            VAR current  : tbd_current_tree);
 
VAR
      searchResult : tbd_searchresult;
      recIndex     : tsp00_Int4;
      prevLeaf     : tsp00_PageNo;
      nptr         : tbd_node_ptrs;
      neighbs      : tbd_neighbors;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    bd30SearchRecord (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
          NOT LOCK_LEAF_EXCL_BD00, nptr, recIndex, neighbs, searchResult);
    IF  (trError_gg00 = e_ok) AND (searchResult = nonefound)
    THEN
        trError_gg00 := e_no_prev_record;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  (searchResult <> lastfound)
            AND
            (NOT bInclusive OR (searchResult <> thisfound))
        THEN
            IF  ftsTemp_egg00 IN curr_tree_id.fileType_gg00
            THEN
                b31t_prev_temp_search (nptr, recIndex, current)
            ELSE
                bd31PrevSearch (recKey.keyVal_gg00, recKey.keyLen_gg00,
                      nptr, recIndex, prevLeaf, current, NOT c_bGetLeafForUpdate);
            (*ENDIF*) 
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b31get_from_leaf (nptr, recIndex, bWithSQLLock, rec, current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  (trError_gg00 = e_ok) AND (searchResult <> thisfound)
            THEN
                trError_gg00 := e_key_not_found
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30ReleaseTree (VAR current : tbd_current_tree);
 
BEGIN
WITH current, curr_trans^, curr_tree_id DO
    BEGIN
&   ifdef torsten
    IF  trError_gg00 = e_ok
    THEN
        bd30_CheckStatisticCounter (current, NOT c_bIsGetTree);
&   endif
    (*ENDIF*) 
    bd30ReleaseSubTree (current);
    IF  currRootNptrs_bd00.np_ptr <> NIL
    THEN
        BEGIN
        IF  (trError_gg00 = e_ok) AND currRootUpdated_bd00
        THEN
            bd13WReleaseRoot (current)
        ELSE
            bd13RReleaseRoot (current);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  currFreeQueue_bd00.fqTop_bd00 > 1
    THEN
        bd13FreePnosAfterUnlock (current);
    (*ENDIF*) 
    IF  (currCounter_bd00 <> 0) AND g01glob.bd_lock_check
    THEN
        BEGIN
        IF  (bd_release_acc IN curr_tree_id.fileBdUse_gg00) OR
            (ftsTemp_egg00  IN curr_tree_id.fileType_gg00 )
        THEN (* Drop/Delete: caused by b13free_node and bd13FreePageNo mix *)
            currCounter_bd00 := 0
        ELSE
            BEGIN
            b06write_filename_and_root (curr_tree_id);
            g01abort (bd30x3IllegalLockHandling_csp03, csp3_n_btree,
                  MSG_RELEASE_MISSING, currCounter_bd00)
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (e_bad_datapage = trError_gg00                      ) AND
        (
        (ftsPerm_egg00 IN curr_tree_id.fileType_gg00        ) OR
        (ftsByteStr_egg00 IN curr_tree_id.fileType_gg00     )
        )
        AND
        (NOT (bd_release_acc IN curr_tree_id.fileBdUse_gg00))
        AND
        (NOT (bd_IgnoreSetToBad IN curr_tree_id.fileBdUse_gg00))
    THEN
        bd30BadFile (curr_trans^, curr_tree_id);
    (*ENDIF*) 
    IF  trError_gg00 <> e_ok
    THEN
        IF  (trError_gg00 = e_no_converter_entry   ) OR
            (trError_gg00 = e_invalid_root         ) OR
            (trError_gg00 = e_page_in_wrong_tree   ) OR
            (trError_gg00 = e_inconsistent_nodetype)
        THEN
            bd06IllegalRootAccess (curr_trans^, curr_tree_id,
                  m_verify <> curr_action)
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30ReleaseSubTree(
            VAR current : tbd_current_tree);
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    IF  currIndexNptrs_bd00.np_ptr <> NIL
    THEN
        BEGIN
        currLeftBound_bd00  := NIL_PAGE_NO_GG00;
        currRightBound_bd00 := NIL_PAGE_NO_GG00;
        curr_lvl_1_pno      := NIL_PAGE_NO_GG00;
        IF  (trError_gg00 = e_ok) AND currIndexUpdated_bd00
        THEN
            bd13WReleaseSubRoot (current)
        ELSE
            bd13RReleaseSubRoot (current);
        (*ENDIF*) 
        currIndexPageLockMode_bd00 := plmLock_ebd00
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30ReplaceInTreeWithTreepos (
            VAR rec      : tgg00_Rec;
            VAR tree_pos : tgg00_FilePos;
            VAR current  : tbd_current_tree);
 
VAR
      recIndex : tsp00_Int4;
      nptr     : tbd_node_ptrs;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    nptr.np_ptr     := NIL;
    nptr.np_cbptr   := NIL;
    IF  tree_pos.tpsPno_gg00 = fileRoot_gg00
    THEN
        nptr := currRootNptrs_bd00
    ELSE
        bd13GetNode (current, tree_pos.tpsPno_gg00, plmLock_ebd00, nr_for_update, nptr);
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        recIndex := tree_pos.tpsIndex_gg00;
        b31repl_in_leaf (rec, nptr, recIndex, NIL_PAGE_NO_GG00, current);
        END;
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30ReplaceInTree (
            VAR recKey    : tgg00_Lkey;
            VAR rec       : tgg00_Rec;
            VAR current   : tbd_current_tree;
            VAR beforeRef : tgg91_PageRef;
            VAR updTrans  : tgg91_TransNo);
 
VAR
      bDoLockHandling : boolean;
      bIsGrowing      : boolean;
      bReadyForUpdate : boolean;
      searchResult    : tbd_searchresult;
      difference      : tsp00_Int4;
      maximumKeyLen   : tsp00_Int4;
      recIndex        : tsp00_Int4;
      recIndexForLeaf : tsp00_Int4;
      leaf            : tsp00_PageNo;
      nptr            : tbd_node_ptrs;
      neighbs         : tbd_neighbors;
      pRec            : tgg00_RecPtr;
      pNewRec         : tgg00_RecPtr;
      packedRow       : tgg00_Rec;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    nptr.np_ptr     := NIL;
    nptr.np_cbptr   := NIL;
    bReadyForUpdate := false;
    pNewRec         := @rec;
    bDoLockHandling := (NOT bd20IsPageExclusiveLocked (currRootNptrs_bd00.np_cbptr));
    WHILE (trError_gg00 = e_ok) AND NOT bReadyForUpdate DO
        BEGIN
        IF  nptr.np_ptr = NIL (* leaf node is not available *)
        THEN
            bd50FindLeaf (recKey.keyVal_gg00, recKey.keyLen_gg00,
                  LOCK_LEAF_EXCL_BD00, nptr, neighbs, recIndexForLeaf, current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b31search_entry (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
                  nptr.np_ptr, recIndex, searchResult);
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (searchResult <> thisfound)
        THEN
            trError_gg00 := e_key_not_found;
        (*ENDIF*) 
        bReadyForUpdate := NOT bDoLockHandling;
        IF  (trError_gg00 = e_ok) AND bDoLockHandling
        THEN
            BEGIN
            WITH nptr.np_ptr^ DO
                BEGIN
                pRec := @nd_body [ nd_pointer_list[ MAX_POINTERINDEX_BD00 - recIndex ]];
                IF  eftsRecordsPacked_egg00 in currExtendedFileTypeSet_bd00 (* PTS 1139184 *)
                THEN
                    pNewRec := bd999PackRow (rec, packedRow);
                (*ENDIF*) 
                difference := abs(Data_GetRecLen(pRec) -  pNewRec^.recLen_gg00);
                IF  Data_GetRecLen(pRec) <= pNewRec^.recLen_gg00
                THEN
                    BEGIN
                    bIsGrowing      := true;
                    bReadyForUpdate := ((nd_bottom + difference) <=
                          MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00))
                    END
                ELSE (* record shrinks *)
                    BEGIN
                    bIsGrowing      := false;
                    bReadyForUpdate :=
                          ((nd_bottom - difference - BODY_BEG_BD00 +
                          (nd_record_cnt * POINTERSIZE_BD00)) >= HALF_COVERING_BD00)
                          OR
                          (nd_id = fileRoot_gg00)
                    END
                (*ENDIF*) 
                END;
            (*ENDWITH*) 
            IF  NOT bReadyForUpdate
            THEN
                BEGIN
                bDoLockHandling := false;
                maximumKeyLen   := bd30_DetermineMaxKeyLength (nptr.np_ptr);
                b13r_release_node (nptr, current, lru_normal);
                IF  NOT bd50IndexNodeIsSaveForReplace (current, bIsGrowing,
                    recIndexForLeaf, recKey.keyLen_gg00, maximumKeyLen)
                THEN
                    bd30_LockTreeExclusive (current)
                ELSE
                    BEGIN (* level > FIRST_INDEX_LEVEL_BD00 *)
                    bd30_LockSubTreeExclusive (current);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        bd50DetermineLeafNode (current, @recKey.keyVal_gg00,
                              recKey.keyLen_gg00, recIndexForLeaf, leaf, neighbs.ln);
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            bd13GetNode (current, leaf, plmLock_ebd00, nr_for_update, nptr);
                            IF  trError_gg00 = e_ok
                            THEN
                                BEGIN
                                maximumKeyLen := bd30_DetermineMaxKeyLength (nptr.np_ptr);
                                IF  NOT bd50IndexNodeIsSaveForReplace (current, bIsGrowing,
                                    recIndexForLeaf, recKey.keyLen_gg00, maximumKeyLen)
                                THEN
                                    BEGIN
                                    b13r_release_node (nptr, current, lru_normal);
                                    bd30_LockTreeExclusive (current)
                                    END
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  trError_gg00 = e_ok
    THEN
        bd31ReplaceInLeaf (pNewRec^, nptr, recIndex, neighbs.ln, current, beforeRef, updTrans);
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30ReplaceInTreeWithBeforeImage (
            VAR recKey  : tgg00_Lkey;
            VAR oldRec  : tgg00_Rec;
            VAR newRec  : tgg00_Rec;
            VAR m       : tgg00_MessBlock;
            pUpdateCmd  : tsp00_Addr;
            grantedLock : tgg00_LockReqMode;
            VAR current : tbd_current_tree);
 
VAR
      bDoLockHandling : boolean;
      bIsGrowing      : boolean;
      bReadyForUpdate : boolean;
      bFirstTime      : boolean;
      searchResult    : tbd_searchresult;
      difference      : tsp00_Int4;
      maximumKeyLen   : tsp00_Int4;
      recIndex        : tsp00_Int4;
      recIndexForLeaf : tsp00_Int4;
      recPos          : tsp00_Int4;
      leaf            : tsp00_PageNo;
      nptr            : tbd_node_ptrs;
      neighbs         : tbd_neighbors;
      pRec            : tgg00_RecPtr;
      pNewRec         : tgg00_RecPtr;
      packedRow       : tgg00_Rec;
      transHistoryInfo: tgg00_ObjTransInfo;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    nptr.np_ptr     := NIL;
    nptr.np_cbptr   := NIL;
    bFirstTime      := true;
    bReadyForUpdate := false;
    bDoLockHandling := (NOT bd20IsPageExclusiveLocked (currRootNptrs_bd00.np_cbptr));
    WHILE (trError_gg00 = e_ok) AND NOT bReadyForUpdate DO
        BEGIN
        IF  nptr.np_ptr = NIL (* leaf node is not available *)
        THEN
            bd50FindLeaf (recKey.keyVal_gg00, recKey.keyLen_gg00,
                  LOCK_LEAF_EXCL_BD00, nptr, neighbs, recIndexForLeaf, current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b31search_entry (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
                  nptr.np_ptr, recIndex, searchResult);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  searchResult <> thisfound
            THEN
                trError_gg00 := e_key_not_found
            ELSE
                BEGIN
                IF  bFirstTime
                THEN
                    BEGIN
                    bFirstTime := false;
                    recPos     := nptr.np_ptr^.nd_pointer_list[ MAX_POINTERINDEX_BD00 - recIndex ];
                    pRec       := @nptr.np_ptr^.nd_body[ recPos ];
                    bd999CopyRow (pRec^, oldRec, trError_gg00);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        k63bd_upd (m, pUpdateCmd, oldRec, newRec, grantedLock, transHistoryInfo);
&                       ifdef TRACE
                        t01buf (bi, oldRec, 1, oldRec.recLen_gg00);
                        t01buf (bi, newRec, 1, newRec.recLen_gg00);
&                       endif
                        END
                    ELSE
                        BEGIN
                        trError_gg00 := e_data_page_corrupted;
                        b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                              nptr.np_ptr^.nd_id, nptr.np_ptr, 1)
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        bReadyForUpdate := NOT bDoLockHandling;
        IF  (trError_gg00 = e_ok) AND bDoLockHandling
        THEN
            BEGIN
            WITH nptr.np_ptr^ DO
                BEGIN
                pRec := @nd_body [ nd_pointer_list[ MAX_POINTERINDEX_BD00 - recIndex ]];
                IF  eftsRecordsPacked_egg00 in currExtendedFileTypeSet_bd00 (* PTS 1139184 *)
                THEN
                    pNewRec := bd999PackRow (newRec, packedRow)
                ELSE
                    pNewRec := @newRec;
                (*ENDIF*) 
                difference := abs( Data_GetRecLen(pRec) -  pNewRec^.recLen_gg00);
                IF  Data_GetRecLen(pRec) <= pNewRec^.recLen_gg00
                THEN
                    BEGIN
                    bIsGrowing      := true;
                    bReadyForUpdate := ((nd_bottom + difference) <=
                          MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00))
                    END
                ELSE (* record shrinks *)
                    BEGIN
                    bIsGrowing      := false;
                    bReadyForUpdate :=
                          ((nd_bottom - difference - BODY_BEG_BD00 +
                          (nd_record_cnt * POINTERSIZE_BD00)) >= HALF_COVERING_BD00)
                          OR
                          (nd_id = fileRoot_gg00)
                    END
                (*ENDIF*) 
                END;
            (*ENDWITH*) 
            IF  NOT bReadyForUpdate
            THEN
                BEGIN
                bDoLockHandling := false;
                maximumKeyLen   := bd30_DetermineMaxKeyLength (nptr.np_ptr);
                b13r_release_node (nptr, current, lru_normal);
                IF  NOT bd50IndexNodeIsSaveForReplace (current, bIsGrowing,
                    recIndexForLeaf, recKey.keyLen_gg00, maximumKeyLen)
                THEN
                    bd30_LockTreeExclusive (current)
                ELSE
                    BEGIN (* level > FIRST_INDEX_LEVEL_BD00 *)
                    bd30_LockSubTreeExclusive (current);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        bd50DetermineLeafNode (current, @recKey.keyVal_gg00,
                              recKey.keyLen_gg00, recIndexForLeaf, leaf, neighbs.ln);
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            bd13GetNode (current, leaf, plmLock_ebd00, nr_for_update, nptr);
                            IF  trError_gg00 = e_ok
                            THEN
                                BEGIN
                                maximumKeyLen := bd30_DetermineMaxKeyLength (nptr.np_ptr);
                                IF  NOT bd50IndexNodeIsSaveForReplace (current, bIsGrowing,
                                    recIndexForLeaf, recKey.keyLen_gg00, maximumKeyLen)
                                THEN
                                    BEGIN
                                    b13r_release_node (nptr, current, lru_normal);
                                    bd30_LockTreeExclusive (current)
                                    END
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  trError_gg00 = e_ok
    THEN
        bd31ReplaceInLeaf (pNewRec^, nptr, recIndex, neighbs.ln, current,
              transHistoryInfo.otrBeforeRef_gg00,
              transHistoryInfo.otrUpdTransId_gg00);
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30ResetBadFile (
            VAR trans  : tgg00_TransContext;
            VAR fileId : tgg00_FileId);
 
VAR
      current : tbd_current_tree;
 
BEGIN
WITH trans DO
    BEGIN
    bd30GetTree (trans, fileId, current, m_set,
          LOCK_TREE_EXCL_BD00, NOT SYNC_TREE_LOCK_BD00 );
    b06file_opmsg (csp3_bd30_reset_bad_file, current.curr_tree_id);
    IF  trError_gg00 = e_ok
    THEN
        bd30SubFileState (current, [f_bad]);
    (*ENDIF*) 
    bd30ReleaseTree (current);
    IF  trError_gg00 = e_ok
    THEN
        b17fsub_file_state (trans, fileId, [f_bad]);
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30SearchRecord(
            VAR current       : tbd_current_tree;
            VAR recKey        : tsp00_Key;
            recKeyLen         : tsp00_Int4;
            bLockLeafExcl     : boolean;
            VAR nptr          : tbd_node_ptrs;
            VAR recIndex      : tsp00_Int4;
            VAR neighbs       : tbd_neighbors;
            VAR searchResult  : tbd_searchresult);
 
VAR
      recIndexForLeaf : tsp00_Int4;
 
BEGIN
IF  current.curr_trans^.trError_gg00 = e_ok
THEN
    bd50FindLeaf (recKey, recKeyLen, bLockLeafExcl, nptr, neighbs, recIndexForLeaf, current);
(*ENDIF*) 
IF  current.curr_trans^.trError_gg00 = e_ok
THEN
    b31search_entry (current, recKey, recKeyLen, nptr.np_ptr, recIndex, searchResult);
&ifdef TRACE
(*ENDIF*) 
t01p2int4 (bd_index, 'recIndex    ', recIndex, 'searchResult', ord (searchResult));
t01p2int4 (bd_index, 'leftNeighbor', neighbs.ln, 'rightNeighbo', neighbs.rn);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30SetReadOnly (
            VAR trans  : tgg00_TransContext;
            VAR fileId : tgg00_FileId);
 
VAR
      bIsWriteAccess : boolean;
      len            : integer;
      id_pos         : integer;
      n              : tsp00_Name;
      msg            : tsp00_C40;
      current        : tbd_current_tree;
 
BEGIN
WITH trans DO
    BEGIN
    trError_gg00 := e_ok;
    b17fadd_file_state (trans, fileId, [f_read_only]);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        bIsWriteAccess := bd_write_acc IN fileId.fileBdUse_gg00;
        IF  bIsWriteAccess
        THEN (* avoid endless loop during bd30GetTree call *)
            fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 - [bd_write_acc];
        (*ENDIF*) 
        bd30GetTree (trans, fileId, current, m_set,
              LOCK_TREE_EXCL_BD00, NOT SYNC_TREE_LOCK_BD00);
        IF  trError_gg00 = e_ok
        THEN
            bd30AddFileState (current, [f_read_only]);
        (*ENDIF*) 
        bd30ReleaseTree (current);
        IF  bIsWriteAccess
        THEN
            fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 + [bd_write_acc];
        (* *)
        (*ENDIF*) 
        n   := 'SET READ ONLY:    ';
        msg := bsp_c40;
        len := 0;
        g17nameto_line (n, len, msg);
        len := len + 1;
        FOR id_pos := 1 TO 10 DO
            BEGIN
            g17hexto_line (current.curr_tree_id.fileName_gg00 [id_pos], len, msg);
            IF  id_pos = 2
            THEN
                len := len + 1;
            (*ENDIF*) 
            END;
        (*ENDFOR*) 
        g01optextmsg (sp3p_knldiag, sp3m_info, csp3_b30_1_set_read_only, csp3_n_btree, msg);
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30SetFileVersion (
            VAR current    : tbd_current_tree;
            newfileVersion : tgg91_FileVersion);
 
BEGIN
WITH current, currRootNptrs_bd00.np_ptr^  DO
    BEGIN
    nd_file_version      := newfileVersion;
    currRootUpdated_bd00 := true
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30SubFileState (
            VAR current : tbd_current_tree;
            fileState   : tbd_file_state_set);
 
BEGIN
WITH current, currRootNptrs_bd00.np_ptr^ DO
    BEGIN
    nd_file_state        := nd_file_state - fileState;
    currRootUpdated_bd00 := true;
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30_LockTreeExclusive (
            VAR current : tbd_current_tree);
 
BEGIN
(* ftsConcurrent_egg00 IN fileType_gg00 only *)
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    IF  NOT bd20IsPageExclusiveLocked (currRootNptrs_bd00.np_cbptr)
    THEN
        BEGIN
        bd30ReleaseTree (current);
        IF  trError_gg00 = e_ok
        THEN
            bd13GetNode (current, fileRoot_gg00, currRootPageLockMode_bd00,
                  nr_for_update, currRootNptrs_bd00)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30_LockSubTreeExclusive (
            VAR current : tbd_current_tree);
 
VAR
      subRoot : tsp00_PageNo;
 
BEGIN
(* ftsConcurrent_egg00 IN fileType_gg00 only *)
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    IF  FIRST_INDEX_LEVEL_BD00 >= currRootNptrs_bd00.np_ptr^.nd_level
    THEN
        g01abort (bd30x2IllegalLockHandling_csp03,
              csp3_n_btree, MSG_1_WRONG_LEVEL, fileRoot_gg00);
    (*ENDIF*) 
    IF  NOT bd20IsPageExclusiveLocked (currIndexNptrs_bd00.np_cbptr)
    THEN
        BEGIN
        (* caused by the root share lock it is guaranteed that the structure *)
        (* of the b*tree index part won't be modified. Only the number of    *)
        (* leaves could be changed.                                          *)
        (* *)
        subRoot := currIndexNptrs_bd00.np_ptr^.nd_id;
        bd30ReleaseSubTree (current);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            bd13GetNode (current, subRoot, currIndexPageLockMode_bd00,
                  nr_for_update, currIndexNptrs_bd00);
            IF  trError_gg00 = e_ok
            THEN
                WITH currIndexNptrs_bd00 DO
                    BEGIN
                    currLeftBound_bd00  := bd52SubtreePno (np_ptr, FIRST_REC_INDEX_BD00);
                    currRightBound_bd00 := bd52SubtreePno (np_ptr, np_ptr^.nd_record_cnt - 1);
                    IF  np_ptr^.nd_level <> FIRST_INDEX_LEVEL_BD00
                    THEN
                        g01abort (bd30x4IllegalLockHandling_csp03, csp3_n_btree,
                              MSG_WRONG_LEVEL, np_ptr^.nd_level);
                    (*ENDIF*) 
                    END
                (*ENDWITH*) 
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30VerifyTree (
            VAR trans          : tgg00_TransContext;
            VAR fileId         : tgg00_FileId;
            VAR treeStatistic  : tbd00_TreeStatistic;
            bUpdateConverter   : boolean;
            bWithExtendedCheck : boolean);
 
VAR
      bDumpPage         : boolean;
      bFileWasBad       : boolean;
      bIsFileDirectory  : boolean;
      scanCount         : tsp00_Int4;
      boundNeighborLeaf : tsp00_PageNo;
      current           : tbd_current_tree;
      fileInfo          : tbd_fileinfo;
      reEntranceKey     : tgg00_Lkey;
      checkKey          : tgg00_Lkey;
 
BEGIN
WITH treeStatistic DO
    BEGIN
    ts_IndexPages_bd00  := 0;
    ts_LeafPages_bd00   := 0;
    ts_RecordCount_bd00 := 0;
    END;
(*ENDWITH*) 
bDumpPage                 := false;
bFileWasBad               := false;
reEntranceKey.keyLen_gg00 := 0;
bIsFileDirectory          := fileId.fileRoot_gg00 = bd17GetBlobFdirRoot;
fileInfo.fi_col_cnt       := 0;
WITH trans  DO
    BEGIN
    IF  NOT bIsFileDirectory
    THEN
        BEGIN
        (* if 'check data' is called directly after a migration without *)
        (* having restarted, there might still be some renamed tables   *)
        (* around that are stored in the blob file directory            *)
        IF  (fileId.fileTfn_gg00 <> tfnColumn_egg00 ) AND
            (fileId.fileTfn_gg00 <> tfnAux_egg00    ) AND
            (fileId.fileTfn_gg00 <> tfnTempAux_egg00)
        THEN
            bd998GcGetFDirEntryFileinfo (trans, fileId.fileName_gg00, fileInfo,
                  ftsShared_egg00 IN fileId.fileType_gg00)
        ELSE
            b17state_fdir (fileId.fileName_gg00, fileInfo,
                  ftsShared_egg00 IN fileId.fileType_gg00, trans);
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (f_bad IN fileInfo.fi_state)
        THEN
            bFileWasBad := true;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    REPEAT
        IF  b01downfilesystem
        THEN
            trError_gg00 := e_shutdown
        ELSE
            BEGIN
            trError_gg00                     := e_ok;
            scanCount                        := 0;
            checkKey.keyLen_gg00             := 0;
            boundNeighborLeaf                := NIL_PAGE_NO_GG00;
            fileId.fileVersion_gg00.ci2_gg00 := cgg_dummy_file_version;
            fileId.fileLeafNodes_gg00        := cgg_nil_leafnodes;
            bd30GetTree (trans, fileId, current, m_verify,
                  NOT LOCK_TREE_EXCL_BD00, NOT SYNC_TREE_LOCK_BD00);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  (NOT bIsFileDirectory)AND (reEntranceKey.keyLen_gg00 = 0)
                THEN
                    b06file_opmsg (csp3_check_file, current.curr_tree_id);
                (*ENDIF*) 
                bFileWasBad := bFileWasBad OR (f_bad IN current.currRootNptrs_bd00.np_ptr^.nd_file_state);
                bd50VerifySubTree (current.curr_tree_id.fileRoot_gg00, NIL_PAGE_NO_GG00,
                      bUpdateConverter, bWithExtendedCheck,
                      bd30FileIdForBlobFileIds.fileCreated, fileInfo.fi_col_cnt,
                      reEntranceKey, checkKey,
                      boundNeighborLeaf, bDumpPage, current, treeStatistic, scanCount);
                END;
            (*ENDIF*) 
            bd30ReleaseTree (current);
            IF  trError_gg00 = e_bd_leaf_unlocked
            THEN
                BEGIN
                IF  NOT bIsFileDirectory (* do not search fileDirRoot in fileDirectory ! *)
                THEN
                    fileId.fileRoot_gg00 := NIL_PAGE_NO_GG00; (* PTS 1124752 TS 2003-10-22 *)
                (*ENDIF*) 
                vsleep (trTaskId_gg00, 0)
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
    UNTIL
        trError_gg00 <> e_bd_leaf_unlocked;
    (*ENDREPEAT*) 
    IF  (trError_gg00 = e_ok) AND bFileWasBad
    THEN
        BEGIN
        fileId := current.curr_tree_id;
        bd30ResetBadFile (trans, fileId)
        END
    ELSE
        BEGIN
        IF  (trError_gg00 = e_file_not_found) AND (NOT bUpdateConverter)
        THEN
            BEGIN
            (* During online CheckData a file could be removed *)
            trError_gg00 := e_ok;
            END;
        (*ENDIF*) 
        IF  (trError_gg00 <> e_ok                 ) AND
            (trError_gg00 <> e_disk_not_accessible) AND
            (trError_gg00 <> e_cancelled          ) AND
            (trError_gg00 <> e_shutdown           )
        THEN
            b06write_filename_and_root( fileId )
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30compare_record (VAR m : tgg00_MessBlock;
            rec_ptr          : tgg00_RecPtr;
            VAR unpackedRow  : tgg00_Rec;
            pos              : integer);
 
VAR
      comp_result    : tsp00_LcompResult;
      col            : integer;
      col_pos_buf    : integer;
      col_len_buf    : integer;
      col_pos_node   : integer;
      col_len_node   : integer;
      old_varcol_pos : tgg00_VarColPosList;
      new_varcol_pos : tgg00_VarColPosList;
 
BEGIN
WITH m, mb_trns^ DO
    BEGIN
    IF  rec_ptr^.recVarcolOffset_gg00 < 0 (* PTS 1139184 *)
    THEN
        rec_ptr := bd999UnpackRow (rec_ptr^, unpackedRow);
    (*ENDIF*) 
    comp_result              := l_equal;
    col                      := mb_qual^.mupd_pos;
    trError_gg00             := e_duplicate_record;
    old_varcol_pos.vpl_last  := -1;
    new_varcol_pos.vpl_last  := -1;
    WHILE (col < mb_qual^.mupd_pos + mb_qual^.mupd_cnt)
          AND (trError_gg00 = e_duplicate_record) DO
        BEGIN
        g04locate_col (mb_qual^.mst_addr^[ col ], @mb_data^.mbp_rec,
              new_varcol_pos, col_pos_buf, col_len_buf);
        g04locate_col (mb_qual^.mst_addr^[ col ], @rec_ptr^.recBuf_gg00[pos],
              old_varcol_pos, col_pos_node, col_len_node);
        s30cmp (mb_data^.mbp_buf, col_pos_buf, col_len_buf,
              rec_ptr^, col_pos_node, col_len_node, comp_result);
        IF  comp_result <> l_equal
        THEN
            trError_gg00 := e_duplicate_key;
        (*ENDIF*) 
        col := col + 1
        END
    (*ENDWHILE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30wait_for_reply (
            VAR t                 : tgg00_TransContext;
            pCheckDataCoordinator : tsp00_Addr;
            VAR send_cnt          : integer;
            VAR ErrorRoot         : tsp00_PageNo;
            max_server            : integer;
            finish                : boolean);
 
VAR
      aux_err      : tgg00_BasisError;
      joberror     : tgg00_BasisError;
      old_send_cnt : integer;
 
BEGIN
IF  t.trError_gg00 <> e_ok
THEN
    BEGIN
    (* *)
    (* trError_gg00 = e_no_server_task_available *)
    (* *)
    aux_err        := t.trError_gg00;
    t.trError_gg00 := e_ok
    END
ELSE
    aux_err := e_ok;
(*ENDIF*) 
old_send_cnt := send_cnt;
WHILE (
      (t.trError_gg00 = e_ok                   ) AND
      ((send_cnt > 0) AND finish               ) OR
      ((send_cnt = max_server) AND (NOT finish))
      )
      OR
      (
      (aux_err = e_no_server_task_available    ) AND
      (send_cnt = old_send_cnt                 )
      )
      DO
    BEGIN
    joberror := e_ok;
    (*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=*)
    kb900WaitForAnyCheckDataJob(t, pCheckDataCoordinator, joberror, ErrorRoot);
    (*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=*)
    IF  t.trError_gg00 = e_ok
    THEN
        BEGIN
        send_cnt := pred (send_cnt);
        IF  joberror <> e_ok
        THEN
            BEGIN
            (* ErrorRoot contains corresponding root *)
            t.trError_gg00 := joberror;
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
IF  (t.trError_gg00 = e_ok) AND (aux_err <> e_ok)
THEN
    t.trError_gg00 := aux_err;
&ifdef TRACE
(*ENDIF*) 
t01basis_error (bi, 'bd30wait end', t.trError_gg00);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30BadFile (
            VAR trans  : tgg00_TransContext;
            VAR fileId : tgg00_FileId);
 
VAR
      current : tbd_current_tree;
 
BEGIN
WITH trans DO
    BEGIN
    IF  (fileId.fileName_gg00 <> cgg_zero_fn) AND (fileId.fileRoot_gg00 <> NIL_PAGE_NO_GG00)
    THEN
        BEGIN
        IF  fileId.fileRoot_gg00 = bd17GetBlobFdirRoot
        THEN
            BEGIN
            g01optextmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg,
                  csp3_n_btree, MSG_FDIR_CORRUPTED);
            END
        ELSE
            BEGIN
            trError_gg00 := e_ok;
            bd30GetTree (trans, fileId, current, m_set,
                  LOCK_TREE_EXCL_BD00, NOT SYNC_TREE_LOCK_BD00);
            b06file_opmsg (csp3_bad_file, current.curr_tree_id);
            IF  trError_gg00 = e_ok
            THEN
                bd30AddFileState (current, [f_bad]);
            (*ENDIF*) 
            IF  e_bad_datapage = trError_gg00
            THEN
                trError_gg00 := e_ok (* root page is bad ! *)
            ELSE
                bd30ReleaseTree (current);
            (*ENDIF*) 
            (* *)
            IF  trError_gg00 = e_ok
            THEN
                b17fadd_file_state (trans, fileId, [f_bad])
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        trError_gg00 := e_bad_datapage
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd30_DetermineMaxKeyLength (pNode : tbd_nodeptr) : tsp00_Int4;
 
VAR
      maxKeyLen : tsp00_Int4;
      recIndex  : tsp00_Int4;
      recPos    : tsp00_Int4;
      pRec      : tgg00_RecPtr;
 
BEGIN
maxKeyLen := 0;
IF  g01glob.bd_subtree
THEN
    BEGIN
    recIndex := FIRST_REC_INDEX_BD00;
    WHILE (recIndex <= (pNode^.nd_record_cnt - 1)) DO
        BEGIN
        recPos := pNode^.nd_pointer_list [MAX_POINTERINDEX_BD00 - recIndex];
        pRec   := @pNode^.nd_body [recPos];
        IF  maxKeyLen < pRec^.recKeyLen_gg00
        THEN
            maxKeyLen := pRec^.recKeyLen_gg00;
        (*ENDIF*) 
        recIndex := succ (recIndex)
        END
    (*ENDWHILE*) 
    END;
(*ENDIF*) 
bd30_DetermineMaxKeyLength := maxKeyLen;
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30_PrepareSyskey (
            VAR trans    : tgg00_TransContext;
            VAR fileId   : tgg00_FileId;
            VAR rec      : tgg00_Rec;
            pNode        : tbd_nodeptr;
            searchResult : tbd_searchresult;
            recIndex     : tsp00_Int4);
 
VAR
      recPos    : tsp00_Int4;
      newSysKey : tgg00_Surrogate;
 
BEGIN
IF  NOT bd998GetNewSysKeyForFile( trans, fileId.fileTabId_gg00, newSysKey )
THEN
    BEGIN
    IF  trans.trError_gg00 <> e_ok
    THEN
        trans.trError_gg00 := e_system_error
    ELSE
        BEGIN (* file not found in syskey cache *)
        (* *)
        IF  searchResult = nonefound
        THEN
            newSysKey := NIL_SYSKEY_GG00
        ELSE
            BEGIN
            recPos := pNode^.nd_pointer_list[ MAX_POINTERINDEX_BD00 - recIndex ];
            SAPDB_PascalMove ('VBD30 ',   6,    
                  sizeof (pNode^), sizeof (newSysKey),
                  @pNode^, recPos + cgg_rec_key_offset + 1, (* do not copy define byte! *)
                  @newSysKey, 1 , sizeof (tgg00_Surrogate), trans.trError_gg00);
            END;
        (*ENDIF*) 
        IF  trans.trError_gg00 = e_move_error
        THEN
            BEGIN
            trans.trError_gg00 := e_data_page_corrupted;
            b06dump_bad_page (trans.trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                  pNode^.nd_id, pNode, 1)
            END
        ELSE
            BEGIN
            IF  NOT bd998AddAndGetNewSysKeyForFile( trans,
                fileId.fileTabId_gg00, newSysKey )
            THEN
                trans.trError_gg00 := e_system_error;
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  trans.trError_gg00 = e_ok
THEN
    BEGIN
    rec.recKey_gg00.keyVal_gg00[1] := csp_defined_byte; (* set define byte *)
    rec.recKeyLen_gg00             := SURROGATE_MXGG00 + 1;
    SAPDB_PascalMove ('VBD30 ',   7,    
          sizeof (newSysKey), sizeof (rec.recKey_gg00.keyVal_gg00),
          @newSysKey, 1, @rec.recKey_gg00.keyVal_gg00, 2, (* do not touch define byte *)
          sizeof (tgg00_Surrogate), trans.trError_gg00)
    END
ELSE
    IF  trans.trError_gg00 = e_system_error
    THEN
        g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg,
              csp3_n_btree, MSG_CREATE_SYSKEY, fileId.fileRoot_gg00)
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30_PrepareSpecialKey (
            VAR current        : tbd_current_tree;
            VAR recKey         : tgg00_Lkey;
            VAR pNodes         : tbd_node_ptrs;
            VAR recIndex       : tsp00_Int4;
            VAR searchResult   : tbd_searchresult;
            VAR bMaxKeyUsed    : boolean; (* search key suffix is filled with \FF\FF.. *)
            VAR bNewTreeAccess : boolean);
 
VAR
      compareResult : tsp00_LcompResult;
      uniqueId      : tgg00_UniquePrimId;
      recPos        : tsp00_Int4;
      prevLeafPage  : tsp00_PageNo;
      pRec          : tgg00_RecPtr;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    IF  thisfound <> searchResult
    THEN
        g01check (csp3_bd_msg, csp3_n_btree,
              'no max key suffix given ', ord(searchResult), bMaxKeyUsed );
    (*ENDIF*) 
    bMaxKeyUsed    := false;
    bNewTreeAccess := false;
    CASE searchResult OF
        nonefound :
            BEGIN
            uniqueId := NIL_UNIQUE_PRIM_ID_GG00;
            bd30_IncrementAndAssignSpecialKey( uniqueId, recKey, trError_gg00 )
            END;
        thisfound : (* given key is already in use, search a new one *)
            BEGIN
            uniqueId := MAX_UNIQUE_PRIM_ID_GG00;
            SAPDB_PascalMove ('VBD30 ',   8,    
                  sizeof (uniqueId), recKey.keyLen_gg00,
                  @uniqueId, 1, @recKey.keyVal_gg00, recKey.keyLen_gg00 - sizeof(uniqueId) + 1,
                  sizeof (uniqueId), trError_gg00);
            (* start new key determination and lock tree exclusive to avoid starvation effects *)
            bMaxKeyUsed    := true;
            bNewTreeAccess := true;
            END;
        lastfound : (* look at this record to determine the unique id *)
            BEGIN
            recPos  := pNodes.np_ptr^.nd_pointer_list[ MAX_POINTERINDEX_BD00 - recIndex ];
            pRec    := @pNodes.np_ptr^.nd_body[ recPos ];
            s30cmp1 (recKey.keyVal_gg00, 1, recKey.keyLen_gg00 - sizeof (uniqueId),
                  pRec^.recBody_gg00, 1, pRec^.recKeyLen_gg00 - sizeof (uniqueId), compareResult);
            IF  l_equal = compareResult
            THEN (* current record has same key prefix *)
                BEGIN
                SAPDB_PascalMove ('VBD30 ',   9,    
                      pRec^.recKeyLen_gg00, sizeof (uniqueId),
                      @pRec^.recBody_gg00, pRec^.recKeyLen_gg00 - sizeof(uniqueId) + 1,
                      @uniqueId, 1 , sizeof (uniqueId), trError_gg00)
                END
            ELSE (* no record with same key prefix exist *)
                uniqueId := NIL_UNIQUE_PRIM_ID_GG00;
            (*ENDIF*) 
            bd30_IncrementAndAssignSpecialKey( uniqueId, recKey, trError_gg00 )
            END;
        nextfound : (* look at the predecessor record to determine the unique id *)
            BEGIN
            IF  (FIRST_REC_INDEX_BD00 = recIndex) AND (NIL_PAGE_NO_GG00 = pNodes.np_ptr^.nd_left)
            THEN
                BEGIN (* no_prev_record, because leftmost tree edge is reached *)
                uniqueId := NIL_UNIQUE_PRIM_ID_GG00;
                bd30_IncrementAndAssignSpecialKey( uniqueId, recKey, trError_gg00 )
                END
            ELSE
                BEGIN
                (* if prev record is on previous leaf page, it may contain a record *)
                (* with the same key prefix. Caused by the added "\FF\FF\FF\FF" key *)
                (* suffix as searchKey it is possible that the real insert position *)
                (* is on this previous page, therefore a new tree access with the   *)
                (* new key suffix is needed.                                        *)
                bNewTreeAccess := (FIRST_REC_INDEX_BD00 = recIndex);
                bd31PrevSearch (recKey.keyVal_gg00, recKey.keyLen_gg00, pNodes,
                      recIndex, prevLeafPage, current, c_bGetLeafForUpdate);
                IF  e_ok = trError_gg00
                THEN
                    BEGIN
                    recPos  := pNodes.np_ptr^.nd_pointer_list[ MAX_POINTERINDEX_BD00 - recIndex ];
                    pRec    := @pNodes.np_ptr^.nd_body[ recPos ];
                    s30cmp1 (recKey.keyVal_gg00, 1, recKey.keyLen_gg00 - sizeof (uniqueId),
                          pRec^.recBody_gg00, 1, pRec^.recKeyLen_gg00 - sizeof (uniqueId), compareResult);
                    IF  l_equal = compareResult
                    THEN (* current record has same key prefix => use his unique Id as basis for increment *)
                        BEGIN
                        SAPDB_PascalMove ('VBD30 ',  10,    
                              pRec^.recKeyLen_gg00, sizeof (uniqueId),
                              @pRec^.recBody_gg00, pRec^.recKeyLen_gg00 - sizeof(uniqueId) + 1,
                              @uniqueId, 1 , sizeof (uniqueId), trError_gg00)
                        END
                    ELSE (* no record with same key prefix exist *)
                        uniqueId := NIL_UNIQUE_PRIM_ID_GG00;
                    (*ENDIF*) 
                    bd30_IncrementAndAssignSpecialKey( uniqueId, recKey, trError_gg00 );
                    IF  (e_ok = trError_gg00) AND (NOT bNewTreeAccess)
                    THEN
                        b31search_entry (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
                              pNodes.np_ptr, recIndex, searchResult)
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        OTHERWISE
            trError_gg00 := e_not_implemented
        END;
    (*ENDCASE*) 
    IF  (e_move_error = trError_gg00) OR (e_system_error = trError_gg00)
    THEN
        BEGIN
        g01optextmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_btree, MSG_CREATE_SPECIALKEY);
        b06write_filename_and_root (curr_tree_id);
        b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, pNodes.np_ptr^.nd_id, pNodes.np_ptr, 1)
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30_PnoCheckOpmsg (
            root    : tsp00_PageNo;
            trError : tgg00_BasisError);
 
VAR
      len    : integer;
      msg_no : tsp00_Int4;
      msg    : tsp00_C40;
 
BEGIN
msg_no := csp3_verify_check;
msg    := bsp_c40;
len    := 0;
g17nameto_line ('Base error:       ', len, msg);
len    := len + 1;
g17basis_err_to_line (trError, len, msg);
g01optextmsg (sp3p_console, sp3m_error, msg_no, csp3_n_check, msg);
(* *)
msg := bsp_c40;
len := 0;
g17nameto_line ('Root pageNo:      ', len, msg);
len    := len + 1;
g17trimint4_to_line (root, len, msg);
g01optextmsg (sp3p_console, sp3m_error, msg_no, csp3_n_check, msg);
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30_SendFileId (
            VAR t                 : tgg00_TransContext;
            pCheckDataCoordinator : tsp00_Addr;
            VAR FileId            : tgg00_FileId;
            VAR RetryCnt          : integer;
            VAR SendCnt           : integer;
            bWithUpdate           : boolean;
            bExtendedCheck        : boolean);
 
VAR
      AuxError : tgg00_BasisError;
 
BEGIN
AuxError       := t.trError_gg00;
t.trError_gg00 := e_ok;
(*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*)
kb900ExecuteCheckDataJob(t, pCheckDataCoordinator, FileId, bWithUpdate, bExtendedCheck);
(*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*)
IF  t.trError_gg00 = e_ok
THEN
    SendCnt := succ (SendCnt)
ELSE
    IF  t.trError_gg00 = e_no_server_task_available
    THEN
        BEGIN
        RetryCnt := succ (RetryCnt);
        vsleep (t.trTaskId_gg00, 1)
        END;
    (*ENDIF*) 
(*ENDIF*) 
IF  (t.trError_gg00 = e_ok) AND (AuxError = e_no_server_task_available)
THEN
    BEGIN
    RetryCnt     := 0;
    t.trError_gg00 := e_ok
    END;
&ifdef TRACE
(*ENDIF*) 
t01basis_error (bi, 'bd30_Send   ', t.trError_gg00);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30_CheckStatisticCounter(
            VAR current : tbd_current_tree;
            bIsGetTree  : boolean);
 
VAR
      bDoCrash       : boolean;
      leafPageCount  : tsp00_Int4;
      indexPageCount : tsp00_Int4;
      entryCount     : tsp00_Int4;
      recIndex       : tsp00_Int4;
      calcIndexCount : tsp00_Int4;
      calcLeafCount  : tsp00_Int4;
      pageNo         : tsp00_PageNo;
      pIndex         : tbd_node_ptrs;
 
BEGIN
WITH current, curr_trans^, curr_tree_id DO
    BEGIN
    IF  (NOT ((fileRoot_gg00 = bd17GetBlobFdirRoot) AND (ftsPerm_egg00 IN fileType_gg00)))
        AND
        (NOT (ftsByteStr_egg00 IN fileType_gg00)) AND (NOT (bd_release_acc IN fileBdUse_gg00))
    THEN
        BEGIN
        bd998GetPageAndRecordCount (curr_trans^, fileTabId_gg00,
              leafPageCount, indexPageCount, entryCount);
        IF  trError_gg00 <> e_ok
        THEN
            trError_gg00 := e_ok
        ELSE
            BEGIN
            bDoCrash := false;
&           ifdef TRACE
            t01int4 (bi, 'level       ', currRootNptrs_bd00.np_ptr^.nd_level);
            t01int4 (bi, 'leafCnt(F)  ', leafPageCount);
            t01int4 (bi, 'indexCnt(F) ', indexPageCount);
            t01int4 (bi, 'leafCnt(De) ', currLeafPageCountDelta_bd00);
            t01int4 (bi, 'indexCnt(De)', currIndexPageCountDelta_bd00);
&           endif
            IF  ((currRootNptrs_bd00.np_ptr^.nd_level = 0) AND
                (
                (leafPageCount  <> 1 ) OR
                (indexPageCount <> 0 ) OR
                (entryCount     <> currRootNptrs_bd00.np_ptr^.nd_record_cnt)
                ))
            THEN
                BEGIN
                g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
                      csp3_n_btree, 'level                   ', currRootNptrs_bd00.np_ptr^.nd_level);
                g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
                      csp3_n_btree, 'leaf page count (fdir)  ', leafPageCount);
                g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
                      csp3_n_btree, 'index page count (fdir) ', indexPageCount);
                g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
                      csp3_n_btree, 'entry count (fdir)      ', entryCount);
                g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
                      csp3_n_btree, 'entry count             ', currRootNptrs_bd00.np_ptr^.nd_record_cnt);
                bDoCrash := true;
                END;
            (*ENDIF*) 
            IF  (
                (currRootNptrs_bd00.np_ptr^.nd_level = 1) AND
                ((leafPageCount  <> currRootNptrs_bd00.np_ptr^.nd_record_cnt) OR
                (indexPageCount <> 1)
                ))
            THEN
                BEGIN
                g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
                      csp3_n_btree, 'level                   ', currRootNptrs_bd00.np_ptr^.nd_level);
                g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
                      csp3_n_btree, 'leaf page count (fdir)  ', leafPageCount);
                g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
                      csp3_n_btree, 'leaf page count         ', currRootNptrs_bd00.np_ptr^.nd_record_cnt);
                g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
                      csp3_n_btree, 'index page count (fdir) ', indexPageCount);
                bDoCrash := true;
                END;
            (*ENDIF*) 
            IF  currRootNptrs_bd00.np_ptr^.nd_level = 2
            THEN
                BEGIN
                calcIndexCount := 1; (* because of root *)
                calcLeafCount  := 0;
                FOR recIndex := 0 TO (currRootNptrs_bd00.np_ptr^.nd_record_cnt -1) DO
                    BEGIN
                    pageNo := bd52SubtreePno (currRootNptrs_bd00.np_ptr, recIndex);
                    bd13GetNode (current, pageNo, plmLock_ebd00, nr_for_read, pIndex);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        calcIndexCount := calcIndexCount + 1;
                        calcLeafCount  := calcLeafCount  + pIndex.np_ptr^.nd_record_cnt;
                        END;
                    (*ENDIF*) 
                    IF  pIndex.np_ptr <> NIL
                    THEN
                        b13r_release_node (pIndex, current, lru_normal)
                    (*ENDIF*) 
                    END;
                (*ENDFOR*) 
                IF  (calcIndexCount <> indexPageCount) OR (calcLeafCount <> leafPageCount)
                THEN
                    BEGIN
                    g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
                          csp3_n_btree, 'level                   ', currRootNptrs_bd00.np_ptr^.nd_level);
                    g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
                          csp3_n_btree, 'index page count (fdir) ', indexPageCount);
                    g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
                          csp3_n_btree, 'index page count (calc) ', calcIndexCount);
                    g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
                          csp3_n_btree, 'leaf page count (fdir)  ', leafPageCount);
                    g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
                          csp3_n_btree, 'leaf page count (calc)  ', calcLeafCount);
                    bDoCrash := true;
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  bDoCrash
            THEN
                BEGIN
                b06write_filename_and_root( curr_tree_id );
                IF  bIsGetTree
                THEN
                    g01abort (csp3_bd_msg, csp3_n_btree,
                          MSG_WRONG_STATISTIC1, currRootNptrs_bd00.np_ptr^.nd_id)
                ELSE
                    g01abort (csp3_bd_msg, csp3_n_btree,
                          MSG_WRONG_STATISTIC2, currRootNptrs_bd00.np_ptr^.nd_id);
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30_IncrementAndAssignSpecialKey(
            VAR uniqueId : tgg00_UniquePrimId;
            VAR recKey   : tgg00_Lkey;
            VAR trError  : tgg00_BasisError );
 
VAR
      i      : integer;
      bFound : boolean;
 
BEGIN
bFound := false;
i      := sizeof(uniqueId);
REPEAT
    IF  ord (uniqueId[ i ]) < 255
    THEN
        BEGIN
        bFound := true;
        uniqueId [ i ] := succ (uniqueId[ i ])
        END
    ELSE
        BEGIN
        IF  i = sizeof(uniqueId)
        THEN
            uniqueId [ i ] := chr(1)
        ELSE
            uniqueId [ i ] := chr(0);
        (*ENDIF*) 
        i := i - 1
        END
    (*ENDIF*) 
UNTIL
    bFound OR (i <= 0);
(*ENDREPEAT*) 
IF  bFound
THEN
    BEGIN (* store unique id in given record key *)
    SAPDB_PascalMove ('VBD30 ',  11,    
          sizeof (uniqueId), recKey.keyLen_gg00,
          @uniqueId, 1, @recKey.keyVal_gg00, recKey.keyLen_gg00 - sizeof(uniqueId) + 1,
          sizeof (uniqueId), trError)
    END
ELSE
    trError := e_system_error
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd30_SpecialKeyExist (
            VAR current : tbd_current_tree;
            VAR recKey  : tgg00_Lkey;
            VAR pNode   : tbd_nodeptr ) : boolean;
 
VAR
      searchResult  : tbd_searchresult;
      recIndex      : tsp00_Int4;
 
BEGIN
b31search_entry (current, recKey.keyVal_gg00, recKey.keyLen_gg00, pNode, recIndex, searchResult);
bd30_SpecialKeyExist := thisfound = searchResult;
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
