.ad 8
.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$VBD50$
.tt 2 $$$
.tt 3 $JuergenP$indexhandling$$2000-09-13$
***********************************************************
.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  : indexhandling
=========
.sp
Purpose : operations on a B* tree index
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        PROCEDURE
              bd50CalculatePageCount (
                    VAR current   : tbd_current_tree;
                    VAR startSep  : tgg00_Lkey;
                    VAR stopSep   : tgg00_Lkey;
                    VAR pageCount : tsp00_Int4);
 
        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;
                    bWithExtendedCheck    : boolean;
                    bCheckLongExistence   : boolean);
 
        PROCEDURE
              bd50DetermineKeyRangeForServer (
                    VAR PrimCurrent       : tbd_current_tree;
                    VAR StartPrimKey      : tsp00_Key (* ptocSynonym tsp00_KeyPtr *);
                    VAR StartPrimKeyLen   : tsp00_Int4;
                    VAR StopPrimKey       : tsp00_Key (* ptocSynonym tsp00_KeyPtr *);
                    VAR StopPrimKeyLen    : tsp00_Int4;
                    VAR NumLeavesToScan   : tsp00_Int4;
                    VAR AvgRecordsPerLeaf : tsp00_Int4;
                    VAR bFinish           : 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 (
                    subRoot       : tsp00_PageNo;
                    numberOfLongs : integer;
                    bOnlyEmpty    : boolean;
                    VAR current   : tbd_current_tree);
 
        PROCEDURE
              bd50EvalPageCount (
                    VAR start_key    : tgg00_Lkey;
                    VAR stop_key     : tgg00_Lkey;
                    count_records    : boolean;
                    VAR page_count   : tsp00_Int4;
                    VAR all_page_cnt : tsp00_Int4;
                    VAR record_cnt   : tsp00_Int4;
                    VAR current      : tbd_current_tree);
 
        FUNCTION
              bd50GetRecPtr (
                    VAR Current : tbd_current_tree;
                    VAR Nptr    : tbd_node_ptrs;
                    RecIndex    : tsp00_Int4) : tgg00_RecPtr;
 
        PROCEDURE
              bd50ExtractForeignKey (
                    VAR m           : tgg00_MessBlock;
                    VAR current     : tbd_current_tree;
                    VAR tempCurrent : tbd_current_tree);
 
        PROCEDURE
              bd50ExtractTable (
                    VAR current      : tbd_current_tree;
                    VAR hostFileName : tsp00_VFilename);
 
        PROCEDURE
              bd50FindBranchNode (
                    VAR sepkey            : tsp00_Key;
                    keyLen                : tsp00_Int4;
                    wantedLevel           : tsp00_Int2;
                    VAR nptrs             : tbd_node_ptrs;
                    VAR neighbs           : tbd_neighbors;
                    VAR bWantedLevelFound : boolean;
                    VAR current           : tbd_current_tree);
 
        PROCEDURE
              bd50FindFirstLevelIndexNode (
                    VAR sepkey  : tsp00_Key;
                    keyLen      : tsp00_Int4;
                    VAR nptrs   : tbd_node_ptrs;
                    VAR neighbs : tbd_neighbors;
                    VAR bFound  : boolean;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd50FindLeaf (
                    VAR sepKey          : tsp00_Key (* ptocSynonym tsp00_KeyPtr *);
                    keyLen              : tsp00_Int4;
                    bLockLeafExcl       : boolean;
                    VAR nptrs           : tbd_node_ptrs;
                    VAR neighbs         : tbd_neighbors;
                    VAR recIndexForLeaf : tsp00_Int4;
                    VAR current         : tbd_current_tree);
 
        PROCEDURE
              bd50PositionLeaf (
                    leafpos           : tsp00_Int4;
                    leafnodes         : tsp00_Int4;
                    VAR left_estimate : tsp00_Int4;
                    VAR rightestimate : tsp00_Int4;
                    VAR nptrs         : tbd_node_ptrs;
                    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
              bd50MoveFileContent (
                    VAR sourceCurrent : tbd_current_tree;
                    VAR destCurrent   : tbd_current_tree;
                    VAR subRoot       : tsp00_PageNo);
 
        PROCEDURE
              bd50ReorgTreeIndex (
                    VAR truncRecKey : tgg00_Lkey;
                    longColCnt      : integer;
                    VAR current     : tbd_current_tree);
 
        PROCEDURE
              bd50VerifySubTree (
                    subRoot               : tsp00_PageNo;
                    right                 : tsp00_PageNo;
                    bUpdateConverter      : boolean;
                    bWithExtendedCheck    : boolean;
                    VAR reEntranceKey     : tgg00_Lkey;
                    VAR checkKey          : tgg00_Lkey;
                    VAR boundNeighborLeaf : tsp00_PageNo;
                    VAR bDumpParent       : boolean;
                    VAR current           : tbd_current_tree;
                    VAR scanCount         : tsp00_Int4;
                    VAR numPages          : tsp00_Int4);
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
        FROM
              filesysteminterface_1 : VBD01;
 
        VAR
              b01niltree_id : tgg00_FileId;
 
        PROCEDURE
              b01b_check_bytestr (VAR t : tgg00_TransContext;
                    VAR file_id : tgg00_FileId);
 
        PROCEDURE
              b01ldestroy_long_file (VAR t : tgg00_TransContext;
                    VAR file_id : tgg00_FileId);
 
      ------------------------------ 
 
        FROM
              error_text_handling : VBD06;
 
        PROCEDURE
              b06write_filename_and_root (VAR file_id : 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);
 
      ------------------------------ 
 
        FROM
              pagestore : VBD10;
 
        PROCEDURE
              b10use_pno (VAR t : tgg00_TransContext;
                    data_pno : tsp00_PageNo);
 
      ------------------------------ 
 
        FROM
              nodehandling : VBD13;
 
        PROCEDURE
              bd13CheckNode (
                    taskId         : tsp00_TaskId;
                    VAR trError    : tgg00_BasisError;
                    VAR pNodes     : tbd_node_ptrs;
                    VAR fileId     : tgg00_FileId;
                    bExtendedCheck : boolean);
 
        PROCEDURE
              bd13GetNode (VAR Current : tbd_current_tree;
                    Pno          : tsp00_PageNo;
                    PageLockMode : tbd00_PageLockMode;
                    NodeReq      : tbd_node_request;
                    VAR Nptrs    : tbd_node_ptrs);
 
        PROCEDURE
              bd13FreePageNo(
                    pageNo               : tsp00_PageNo;
                    pageConverterVersion : tsp00_Int4;
                    VAR current          : tbd_current_tree );
 
        PROCEDURE
              bd13FreeTempPageNo(
                    pageNo      : tsp00_PageNo;
                    VAR current : tbd_current_tree );
 
        PROCEDURE
              b13free_node (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);
 
      ------------------------------ 
 
        FROM
              systembufferinterface : VBD20;
 
        FUNCTION
              bd20IsPageExclusiveLocked (
                    pCBlock : tbd_nodeptr) : boolean;
 
        FUNCTION
              bd20IsPageRequested (
                    cbptr : tbd_nodeptr ) : boolean;
 
      ------------------------------ 
 
        FROM
              treehandling : VBD30;
 
        PROCEDURE
              bd30AddToTempTree (
                    bCountDuplicates : boolean;
                    VAR rec          : tgg00_Lkey;
                    VAR current      : tbd_current_tree);
 
        PROCEDURE
              bd30GetSubTree (
                    VAR current : tbd_current_tree;
                    indexPageNo : tsp00_PageNo);
 
        PROCEDURE
              bd30ExistRecord (
                    VAR recKey  : tgg00_Lkey;
                    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;
                    bSynchronizeExclLock : boolean);
 
        PROCEDURE
              bd30ReleaseSubTree(
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30ReleaseTree (
                    VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              leafhandling : VBD31;
 
        PROCEDURE
              b31next_search (
                    VAR nptr    : tbd_node_ptrs;
                    VAR index   : integer;
                    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);
 
      ------------------------------ 
 
        FROM
              branchnodehandling : VBD51;
 
        PROCEDURE
              bd51SearchBranch (VAR Current : tbd_current_tree;
                    pSepKey      : tsp00_KeyAddr;
                    KeyLen       : tsp00_Int4;
                    VAR Nptr     : tbd_nodeptr;
                    VAR RecIndex : tsp00_Int4);
 
        PROCEDURE
              b51next_branch (VAR nptr : tbd_nodeptr;
                    VAR index : integer;
                    VAR last  : boolean);
 
      ------------------------------ 
 
        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
              Trace : VBD120;
 
        PROCEDURE
              b120InsertTrace (VAR t   : tgg00_TransContext;
                    trace_layer  : tgg00_Debug;
                    trace_object : tgg00_VtraceType;
                    body_len     : tsp00_Int2;
                    trace_body   : tsp00_Addr);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01glob : tgg00_KernelGlobals;
 
        PROCEDURE
              g01abort (msg_no : tsp00_Int4;
                    msg_label : tsp00_C8;
                    msg_text  : tsp00_C24;
                    bad_value : tsp00_Int4);
 
        PROCEDURE
              g01key_assign (VAR source_key : tgg00_Lkey;
                    VAR target_key : tgg00_Lkey;
                    VAR e          : tgg00_BasisError);
 
        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);
 
      ------------------------------ 
 
        FROM
              GG_cpp_auxiliary_functions : VGG06;
 
        FUNCTION
              gg06PnoGet (VAR Cint4 : tgg90_Cint4): tsp00_Int4;
 
        FUNCTION
              gg06Max (
                    value1 : tsp00_Int4;
                    value2 : tsp00_Int4 ) : tsp00_Int4;
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              g10mv (
                    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
              g17sname_to_line (
                    n             : tsp00_Sname;
                    VAR ln_len    : integer;
                    VAR ln        : tsp00_Line);
 
        PROCEDURE
              g17trimint4_to_line (
                    int        : tsp00_Int4;
                    VAR ln_len : integer;
                    VAR ln     : tsp00_Line);
 
      ------------------------------ 
 
        FROM
              KB_index_handling : VKB33;
 
        PROCEDURE
              k33mult_inv_key (
                    VAR t         : tgg00_TransContext;
                    VAR prim_tree : tgg00_FileId;
                    VAR inv_tree  : tgg00_FileId;
                    init_inv_tree : boolean;
                    st_addr       : tgg00_StackListPtr;
                    rec_buf_ptr   : tgg00_RecPtr;
                    first_st      : integer;
                    last_st       : integer;
                    VAR inv_key   : tgg00_Lkey;
                    VAR bIsUndef  : boolean;
                    VAR move_err  : tgg00_BasisError);
 
      ------------------------------ 
 
        FROM
              RTE-Extension-30 : VSP30;
 
        PROCEDURE
              s30cmp (VAR buf1  : tsp00_Key;
                    fieldpos1    : tsp00_Int4;
                    fieldlength1 : tsp00_Int4;
                    VAR buf2     : tsp00_Key;
                    fieldpos2    : tsp00_Int4;
                    fieldlength2 : tsp00_Int4;
                    VAR l_result : tsp00_LcompResult);
 
      ------------------------------ 
 
        FROM
              RTE_kernel : VEN101;
 
        PROCEDURE
              vfopen (
                    VAR hostfile   : tsp00_VFilename;
                    VAR hostfileno : tsp00_Int4;
                    VAR error      : tsp00_VfReturn;
                    VAR errtext    : tsp00_ErrText);
 
        PROCEDURE
              vfwrite (hostfileno : tsp00_Int4;
                    buf         : tsp00_VfBufaddr;
                    VAR error   : tsp00_VfReturn;
                    VAR errtext : tsp00_ErrText);
 
        PROCEDURE
              vfclose (
                    hostfileno  : tsp00_Int4;
                    VAR error   : tsp00_VfReturn;
                    VAR errtext : tsp00_ErrText);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01buf (debug  : tgg00_Debug;
                    VAR buf  : tsp00_Key;
                    startpos : integer;
                    endpos   : integer);
 
        PROCEDURE
              t01int4 (debug : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int4     : tsp00_Int4);
 
        PROCEDURE
              t01p2int4 (debug : tgg00_Debug;
                    nam_1 : tsp00_Sname;
                    int_1 : tsp00_Int4;
                    nam_2 : tsp00_Sname;
                    int_2 : tsp00_Int4);
 
        PROCEDURE
              t01real (debug : tgg00_Debug;
                    nam      : tsp00_Sname;
                    re       : tsp00_Longreal;
                    digits   : integer);
 
        PROCEDURE
              t01sname (debug : tgg00_Debug; nam : tsp00_Sname);
&       endif
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
        PROCEDURE
              b06dump_bad_page;
 
              tbd_univ_ptr tbd_nodeptr
 
        FUNCTION
              bd20IsPageExclusiveLocked;
 
              tbd02_pDataCBlock tbd_nodeptr
 
        FUNCTION
              bd20IsPageRequested;
 
              tbd02_pDataCBlock tbd_nodeptr
 
        PROCEDURE
              bd30AddToTempTree (;
 
              tgg00_Rec tgg00_Lkey
 
        PROCEDURE
              b120InsertTrace;
 
              tgg11_VtraceBodyPtr tsp00_Addr
 
        PROCEDURE
              s30cmp;
 
              tsp00_MoveObj tsp00_Key
              tsp00_MoveObj tsp00_Key
 
        PROCEDURE
              vfwrite;
 
              tsp_vf_bufaddr tsp00_VfBufaddr
&             ifdef TRACE
 
        PROCEDURE
              t01buf;
 
              tsp00_Buf tsp00_Key;
&             endif
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : JuergenP
.sp
.cp 3
Created : 1979-11-14
.sp
.cp 3
.sp
.cp 3
Release :      Date : 2000-09-13
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
 
   bd50EvalPageCount
      (start_key, stop_key, page_count, all_page_cnt, current)
.sp
The number of leaf nodes in the current B* tree from start_key to
stop_key are counted.
.br;If the tree consists of one leaf only, page_count := 1 and
all_page_cnt := 1 is returned.
.br;If the tree consists of 3 or more index level 1 nodes, page_count as
input parameter limits the counted leaf nodes.
.br;The counting starts with start_key and finishes with stop_key or
as soon as the number of counted leaves passes over page_count.
.br;If this number of leaf nodes < page_count, page_count is set to this
number of leaf nodes, otherwise page_count is not changed.
.br;all_page_cnt contains a minimal number of leaf nodes for this tree.
.sp2
   bd50FindLeaf(sepkey, lock_type, node_req, subtree_handling,
                left_estimate, rightestimate, nptr, neighbs, current)
.sp
This routine requires that the current B* tree consist of at least
one leaf.  It supplies nptr with the leaf that is responsible for the
key and supplies neighbs,
if they are present, with the leaf numbers of the neighbor leaves to
which there are referencees in the B* index, i.e. no purely appended
leaves and, therefore, not necessarily the direct neighbors;
otherwise, nil_page_no is supplied.
.br
node_req is passed to B13GET_NODE.
.br;which works correctly only, if there is a tree lock on the current
tree (r_lock_tree).
.br;Output parameters left_estimate and rightestimate supply estimations
for the number of nodes left and right of the one node which is supplied
in nptr excluding this one. The estimation assumes the amount of entries
in all nodes from the same index or leaf level to be the same. This
amount is calculated with the average entry length of the one inspected
node of this level and with the assumption of a 80% rsp. 50% filling of
dynamic rsp. static trees.
.sp 2;
   b50bfind_branchnode(k,lno,n,left,right,found,current,e)
.sp
This routine requires that the current B* tree consist of at least
a root.  If the level number specified in lno is higher than the
level number of the root, 'found' is set to FALSE and n supplies
the root; otherwise, 'found' is set to TRUE and n supplies the node
with the level number lno that forms the root of the subtree that
contains the leaf responsible for the key k (length kl).  In the
latter case, 'left' and 'right' supply the page numbers of the
left and right neighbor nodes of n or, if n has no right and/or left
neighbor, they supply nil_page_no.
Acknowledgements in e:
.br
   - e_ok
   - b_disk_not_accessible
.sp 2
   bd50PositionLeaf(leafpos,leafnodes,
         left_estimate,rightestimate,nptr,current)
.sp
This routine requires that the current B* tree consist of at least
one leaf.  It supplies nptr with the leaf that is estimated to be the
'leafpos' leaf counted from left within 'leafnodes' leaves in all the
tree and supplies neighbs,
if they are present, with the leaf numbers of the neighbor leaves to
which there are referencees in the B* index, i.e. no purely appended
leaves and, therefore, not necessarily the direct neighbors;
otherwise, nil_page_no is supplied.
.br
node_req is passed to B13GET_NODE.
.br;If the current tree is already locked,
.br;which works correctly only, if there is a tree lock on the current
tree (r_lock_tree).
.br;Output parameters left_estimate and rightestimate supply estimations
for the number of nodes left and right of the one node which is supplied
in nptr excluding this one. The estimation assumes the amount of entries
in all nodes from the same index or leaf level to be the same as the
amount of entries in the one inspected node of every level.
.sp 2
   bd50DropSubTree(root,current,e)
.sp
This routine requires that the B* index consist of at least one node.
The routine removes all nodes belonging to the B* index from the
B* tree and releases the associated secondary-storage pages.
Acknowledgements in e:
   - e_ok
   - b_disk_not_accessible
.sp 2
 
.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
 
The entries of the nodes of the B* index are called branches.  Each
branch consists of a key, called a separator, and a pointer to the
root of a subtree.  The call b52get_subtree retrieves the page
number of this root.  In the body of the node, the branches are
sorted in ascending order by separators.  The first branch
begins at 'top' (see nodehandling) and, when the routine
b51next_branch is repeatedly called (until last = true), it is
possible to run through all the branches that begin in the node.  A
node in the B* index always contains at least two branches; for
any pair of consecutive branches with the separators s1 and s2
(s1 < s2), the following applies:  the branch with s1 points to the
subtree that contains all leaves responsible for keys in the interval
between s1 (inclusive) and s2 (exclusive).  The search for a
responsible leaf begins in the root and continues downwards level by
level into smaller and smaller subtrees until finally only the leaf
being searched for remains.  A path beginning at the root and following
the pointers of each first branch leads to the leaf that is
responsible for the lowest key.
.sp
The release of the nodes of the B* index occurs via the obvious
recursive algorithm; it must be noted that only one node buffer is
used!  As long as nothing prevents the use of recursion, this solution
uses less codes (and is more elegant) than a corresponding iterative
algorithm.
.sp
The routines for setting up and dismantling the B* index and for
managing the associated order list is described in the module
indexupdateorders.
.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:
 
.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :
 
 
CONST
      MSG_1_WRONG_LOCK     = 'Excl Tree Lock needed   ';
      MSG_1_WRONG_LEVEL    = 'Tree level is <= 1      ';
      MSG_1_IDX_LOCK_EXIST = 'Index Lock already exist';
      (* *)
      c_count_duplicates        = true;
      c_upb_pages_to_count_recs = 3;
 
 
(*------------------------------*) 
 
PROCEDURE
      bd50CalculatePageCount (
            VAR current   : tbd_current_tree;
            VAR startSep  : tgg00_Lkey;
            VAR stopSep   : tgg00_Lkey;
            VAR pageCount : tsp00_Int4);
 
VAR
      compResult       : tsp00_LcompResult;
      scanCount        : integer;
      recPos           : tsp00_Int4;
      pRec             : tgg00_RecPtr;
      startRecIndex    : tsp00_Int4;
      stopRecIndex     : tsp00_Int4;
      nextIndexPage    : tsp00_PageNo;
      subRoot          : tsp00_PageNo;
      startIndexPage   : tsp00_PageNo;
      nptrs            : tbd_node_ptrs;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    scanCount        := 0;
    startIndexPage   := NIL_PAGE_NO_GG00;
    subRoot          := fileRoot_gg00;
    nptrs.np_ptr     := NIL;
    nptrs.np_cbptr   := NIL;
    REPEAT
        IF  subRoot = fileRoot_gg00
        THEN
            nptrs := currRootNptrs_bd00
        ELSE
            BEGIN
            IF  nptrs.np_ptr <> currRootNptrs_bd00.np_ptr
            THEN
                b13r_release_node (nptrs, current, lru_normal);
            (*ENDIF*) 
            bd13GetNode (current, subRoot, plmLock_ebd00, nr_for_read, nptrs)
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            CASE nptrs.np_ptr^.nd_level OF
                LEAF_LEVEL_BD00: (* e_root_is_leaf *)
                    BEGIN
                    trError_gg00 := e_no_next_record;
                    pageCount    := 1
                    END;
                FIRST_INDEX_LEVEL_BD00:
                    BEGIN
                    bd51SearchBranch (current, @startSep.keyVal_gg00, startSep.keyLen_gg00,
                          nptrs.np_ptr, startRecIndex);
                    startIndexPage := nptrs.np_ptr^.nd_id;
                    b13r_release_node (nptrs, current, lru_normal)
                    END;
                OTHERWISE:
                    BEGIN
                    bd51SearchBranch (current, @startSep.keyVal_gg00, startSep.keyLen_gg00,
                          nptrs.np_ptr, startRecIndex);
                    subRoot := bd52SubtreePno (nptrs.np_ptr, startRecIndex)
                    END
                END
            (*ENDCASE*) 
            END
        (*ENDIF*) 
    UNTIL
        (startIndexPage <> NIL_PAGE_NO_GG00) OR (trError_gg00 <> e_ok);
    (*ENDREPEAT*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        (* *)
        (* level = FIRST_INDEX_LEVEL_BD00 *)
        (* *)
        nextIndexPage := startIndexPage;
        REPEAT
            bd30GetSubTree (current, nextIndexPage);
            IF  trError_gg00 = e_ok
            THEN
                WITH currIndexNptrs_bd00, np_ptr^ DO
                    BEGIN
&                   ifdef TRACE
                    t01int4 (bd_index, 'page  id    ', nd_id);
                    t01int4 (bd_index, 'recs in page', nd_record_cnt);
&                   endif
                    recPos := nd_pointer_list [MAX_POINTERINDEX_BD00 - (nd_record_cnt - 1)];
                    IF  bd50_RecordPositionValid( curr_trans^, curr_tree_id, np_ptr, recPos)
                    THEN
                        BEGIN
                        pRec := @nd_body [recPos];
                        s30cmp (
                              pRec^.recKey_gg00.keyVal_gg00, 1,
                              pRec^.recKey_gg00.keyLen_gg00,
                              stopSep.keyVal_gg00, 1,
                              stopSep.keyLen_gg00, compResult);
                        CASE compResult OF
                            l_less :
                                BEGIN
                                (* trError_gg00 = e_ok  *)
                                END;
                            l_greater :
                                BEGIN
                                trError_gg00 := e_no_next_record;
                                bd51SearchBranch (current, @stopSep.keyVal_gg00,
                                      stopSep.keyLen_gg00, np_ptr, stopRecIndex);
                                END;
                            l_equal :
                                BEGIN
                                trError_gg00 := e_no_next_record;
                                stopRecIndex := nd_record_cnt - 1
                                END;
                            OTHERWISE:
                                ;
                            END;
                        (*ENDCASE*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN (* increment page count and read next page. *)
                            IF  nextIndexPage = startIndexPage
                            THEN
                                pageCount := pageCount + (nd_record_cnt - startRecIndex)
                            ELSE
                                pageCount := pageCount + nd_record_cnt
                            (*ENDIF*) 
                            END
                        ELSE
                            IF  trError_gg00 = e_no_next_record
                            THEN
                                BEGIN (* increment page count and stop reading pages *)
                                IF  nextIndexPage = startIndexPage
                                THEN
                                    pageCount := stopRecIndex - startRecIndex + 1
                                ELSE
                                    pageCount := pageCount + stopRecIndex + 1
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN (* check for interrupt *)
                        nextIndexPage := nd_right;
                        IF  nextIndexPage = NIL_PAGE_NO_GG00
                        THEN
                            trError_gg00 := e_no_next_record
                        ELSE
                            BEGIN
                            scanCount := succ (scanCount);
                            IF  scanCount = MAX_NODE_SCAN_BD00
                            THEN
                                BEGIN
                                IF  trRteCommPtr_gg00^.to_cancel
                                THEN
                                    trError_gg00 := e_cancelled
                                ELSE
                                    IF  NOT bd20IsPageRequested (currRootNptrs_bd00.np_cbptr)
                                    THEN
                                        scanCount := 0
                                    ELSE
                                        BEGIN
                                        g01key_assign (pRec^.recKey_gg00, startSep, trError_gg00);
                                        IF  trError_gg00 = e_ok
                                        THEN
                                            trError_gg00 := e_bd_leaf_unlocked
                                        ELSE
                                            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*) 
                                        (*ENDIF*) 
                                        END
                                    (*ENDIF*) 
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDWITH*) 
            (*ENDIF*) 
            bd30ReleaseSubTree (current);
        UNTIL
            (trError_gg00 <> e_ok) OR (nextIndexPage = NIL_PAGE_NO_GG00)
        (*ENDREPEAT*) 
        END;
    (*ENDIF*) 
    IF  nptrs.np_ptr <> NIL
    THEN
        b13r_release_node (nptrs, current, lru_normal);
    (*ENDIF*) 
    IF  trError_gg00 = e_no_next_record
    THEN
        trError_gg00 := e_ok
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
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;
            bWithExtendedCheck    : boolean;
            bCheckLongExistence   : boolean);
 
VAR
      bWasLastRecord : boolean;
      recIndex       : tsp00_Int4;
      rightRecIndex  : tsp00_Int4;
      nptr           : tbd_node_ptrs;
      rightSubRoot   : tsp00_PageNo;
      pRec           : tgg00_RecPtr;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    trError_gg00  := e_ok;
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    IF  trRteCommPtr_gg00^.to_cancel
    THEN
        trError_gg00 := e_cancelled
    ELSE
        BEGIN
        IF  subRoot = curr_tree_id.fileRoot_gg00
        THEN
            nptr := currRootNptrs_bd00
        ELSE
            bd13GetNode (current, subRoot, plmLock_ebd00, nr_for_read, nptr);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok (* PTS 1125096 TS 2003-11-19 *)
    THEN
        bd50_CheckEntriesOnPage( curr_trans^, curr_tree_id, nptr,
              checkKey, bDumpParent, bWithExtendedCheck );
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        WITH nptr, np_ptr^ DO
            BEGIN
            IF  nd_level = LEAF_LEVEL_BD00
            THEN
                BEGIN
                IF  ((right <> nd_right) AND (subRoot <> currRightBound_bd00))
                    OR
                    ((boundNeighborLeaf <> NIL_PAGE_NO_GG00) AND
                    (subRoot = currLeftBound_bd00) AND (boundNeighborLeaf <> subRoot))
                THEN
                    BEGIN
                    trError_gg00 := e_invalid_leaves_structure;
                    bDumpParent  := true;
                    g01opmsg (sp3p_knldiag, sp3m_error, csp3_b50_1_invalid_structure,
                          csp3_n_btree, 'Invalid leaves structure', nd_id);
                    b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1)
                    END
                ELSE
                    BEGIN
                    IF  subRoot = currRightBound_bd00
                    THEN
                        boundNeighborLeaf := nd_right
                    ELSE
                        boundNeighborLeaf := NIL_PAGE_NO_GG00;
                    (*ENDIF*) 
                    IF  longColCnt > 0
                    THEN
                        BEGIN
                        bd50_CheckLong (curr_tree_id, curr_trans^, np_ptr, longColCnt,
                              newLongColCnt, bCheckLongExistence);
                        IF  (trError_gg00 <> e_ok                 ) AND
                            (trError_gg00 <> e_disk_not_accessible) AND
                            (trError_gg00 <> e_shutdown           ) AND
                            (trError_gg00 <> e_long_column_missing)
                        THEN
                            BEGIN
                            bLongIsBad   := true;
                            trError_gg00 := e_ok;
                            END
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        IF  scanCount < MAX_NODE_SCAN_BD00
                        THEN
                            BEGIN
                            scanCount                 := scanCount + 1;
                            reEntranceKey.keyLen_gg00 := 0
                            END
                        ELSE
                            BEGIN
                            IF  (nptr.np_ptr^.nd_right = NIL_PAGE_NO_GG00             ) OR
                                (NOT bd20IsPageRequested (currRootNptrs_bd00.np_cbptr))
                            THEN
                                scanCount := 0
                            ELSE
                                BEGIN
                                pRec := @nd_body [ nd_pointer_list[ MAX_POINTERINDEX_BD00 ]];
                                g01key_assign (pRec^.recKey_gg00, reEntranceKey, trError_gg00);
                                IF  trError_gg00 = e_ok
                                THEN
                                    trError_gg00 := e_bd_leaf_unlocked
                                ELSE
                                    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*) 
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            ELSE (*  nd_level > leaflevel *)
                IF  (right <> nd_right) AND (reEntranceKey.keyLen_gg00 = 0)
                THEN
                    BEGIN
                    trError_gg00 := e_invalid_index_structure;
                    bDumpParent  := true;
                    g01opmsg (sp3p_knldiag, sp3m_error, csp3_b50_2_invalid_structure,
                          csp3_n_btree, 'Invalid index structure ', nd_id);
                    b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,  nd_id, np_ptr, 1)
                    END
                ELSE
                    BEGIN
                    IF  nd_level = FIRST_INDEX_LEVEL_BD00
                    THEN
                        BEGIN
                        currLeftBound_bd00  := bd52SubtreePno (np_ptr, FIRST_REC_INDEX_BD00);
                        currRightBound_bd00 := bd52SubtreePno (np_ptr, nd_record_cnt - 1)
                        END;
                    (*ENDIF*) 
                    recIndex       := FIRST_REC_INDEX_BD00;
                    bWasLastRecord := false;
                    REPEAT
                        IF  reEntranceKey.keyLen_gg00 <> 0
                        THEN
                            bd51SearchBranch (current, @reEntranceKey.keyVal_gg00,
                                  reEntranceKey.keyLen_gg00, np_ptr, recIndex);
                        (*ENDIF*) 
                        subRoot       := bd52SubtreePno (np_ptr, recIndex);
                        rightRecIndex := recIndex;
                        bd50_GetRightSubTree (current, np_ptr, rightRecIndex, right, rightSubRoot);
                        IF  (trError_gg00 = e_ok) AND bWithExtendedCheck
                        THEN
                            BEGIN (* recPos and recLength were checked before *)
                            pRec := @nd_body [nd_pointer_list [MAX_POINTERINDEX_BD00 - recIndex]];
                            g10mv ('VBD50 ',   1,    
                                  pRec^.recKeyLen_gg00, sizeof (checkKey.keyVal_gg00),
                                  @pRec^.recKey_gg00.keyVal_gg00, 1, @checkKey.keyVal_gg00, 1,
                                  pRec^.recKeyLen_gg00, trError_gg00);
                            checkKey.keyLen_gg00 := pRec^.recKeyLen_gg00;
                            END;
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            bd50CheckSubTree (subRoot, rightSubRoot, longColCnt, newLongColCnt,
                                  scanCount, boundNeighborLeaf, bDumpParent, bLongIsBad,
                                  reEntranceKey, checkKey, current, bWithExtendedCheck,
                                  bCheckLongExistence);
                        (*ENDIF*) 
                        IF  bDumpParent
                        THEN
                            BEGIN
                            bDumpParent := false;
                            g01opmsg (sp3p_knldiag, sp3m_error, csp3_b50_3_invalid_structure,
                                  csp3_n_btree, 'Parent data pageNo      ', nd_id);
                            b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1)
                            END;
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            b51next_branch (np_ptr, recIndex, bWasLastRecord);
                            IF  (NOT bWasLastRecord) AND bWithExtendedCheck
                            THEN
                                bd50_CheckMaxChildKeyAgainstNextSeparator(
                                      curr_trans^, nptr, checkKey, recIndex );
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                    UNTIL
                        bWasLastRecord OR (trError_gg00 <> e_ok);
                    (*ENDREPEAT*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            IF  (e_ok = trError_gg00) AND bWithExtendedCheck
            THEN
                BEGIN (* store max key to check him against next separator key *)
                IF  nd_record_cnt = 0
                THEN
                    checkKey.keyLen_gg00 := 0
                ELSE
                    BEGIN
                    recIndex  := nd_record_cnt - 1;
                    pRec      := @nd_body [nd_pointer_list [MAX_POINTERINDEX_BD00 - recIndex]];
                    g10mv ('VBD50 ',   2,    
                          pRec^.recKeyLen_gg00, sizeof (checkKey.keyVal_gg00),
                          @pRec^.recKey_gg00.keyVal_gg00, 1, @checkKey.keyVal_gg00, 1,
                          pRec^.recKeyLen_gg00, trError_gg00);
                    checkKey.keyLen_gg00 := pRec^.recKeyLen_gg00;
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50DetermineKeyRangeForServer (
            VAR PrimCurrent       : tbd_current_tree;
            VAR StartPrimKey      : tsp00_Key;
            VAR StartPrimKeyLen   : tsp00_Int4;
            VAR StopPrimKey       : tsp00_Key;
            VAR StopPrimKeyLen    : tsp00_Int4;
            VAR NumLeavesToScan   : tsp00_Int4;
            VAR AvgRecordsPerLeaf : tsp00_Int4;
            VAR bFinish           : boolean);
 
VAR
      searchResult    : tbd_searchresult;
      recIndexForLeaf : tsp00_Int4;
      index           : tsp00_Int4;
      pos             : tsp00_Int4;
      pRec            : tgg00_RecPtr;
      nptrs           : tbd_node_ptrs;
      neighbors       : tbd_neighbors;
 
BEGIN
&ifdef TRACE
t01sname (bd_idx_create, 'KeyRange Beg');
IF  StopPrimKeyLen = 0
THEN
    t01sname (bd_idx_create, 'ZEROKEY     ')
ELSE
    t01buf   (bd_idx_create, StopPrimKey, 1, StopPrimKeyLen);
(*ENDIF*) 
&endif
WITH PrimCurrent, curr_trans^, curr_tree_id DO
    BEGIN
    nptrs.np_ptr      := NIL;
    nptrs.np_cbptr    := NIL;
    NumLeavesToScan   := 0;
    AvgRecordsPerLeaf := 0;
    (* *)
    IF  trError_gg00 = e_ok
    THEN
        bd50FindLeaf (StopPrimKey, StopPrimKeyLen, NOT LOCK_LEAF_EXCL_BD00,
              nptrs, neighbors, recIndexForLeaf, PrimCurrent);
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        b31search_entry (PrimCurrent, StopPrimKey, StopPrimKeyLen,
              nptrs.np_ptr, index, searchResult);
        IF  trError_gg00 = e_ok
        THEN
            CASE searchResult OF
                lastfound, thisfound:
                    b31next_search (nptrs, index, PrimCurrent);
                nonefound:
                    trError_gg00 := e_key_not_found;
                OTHERWISE
                    ;
                END;
            (*ENDCASE*) 
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            WITH nptrs, np_ptr^ DO
                BEGIN
&               ifdef TRACE
                t01int4 (bd_idx_create, 'Start Leaf  ', nd_id);
&               endif
                AvgRecordsPerLeaf := nd_record_cnt;
                pos               := nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
                IF  bd50_RecordPositionValid (curr_trans^, curr_tree_id, np_ptr, pos)
                THEN
                    BEGIN
                    pRec            := @nd_body [pos];
                    StartPrimKeyLen := pRec^.recKey_gg00.keyLen_gg00;
                    g10mv ('VBD50 ',   3,    
                          KEY_MXSP00, KEY_MXSP00,
                          @pRec^.recKey_gg00.keyVal_gg00, 1,
                          @StartPrimKey, 1, StartPrimKeyLen, 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
                (*ENDIF*) 
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
        IF  nptrs.np_ptr <> NIL
        THEN
            b13r_release_node (nptrs, PrimCurrent, lru_normal);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            NumLeavesToScan := NumLeavesToScan + currIndexNptrs_bd00.np_ptr^.nd_record_cnt;
        (* *)
        (* Determine stop key *)
        (* *)
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
&           ifdef TRACE
            t01int4 (bd_idx_create, 'Stop Leaf   ', currRightBound_bd00);
&           endif
            bd13GetNode (PrimCurrent, currRightBound_bd00, plmLock_ebd00, nr_for_read, nptrs);
            IF  trError_gg00 = e_ok
            THEN
                WITH nptrs, np_ptr^ DO
                    BEGIN
                    bFinish := (nd_right = NIL_PAGE_NO_GG00);
                    index   := nd_record_cnt - 1;
                    pos     := nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
                    AvgRecordsPerLeaf := (AvgRecordsPerLeaf + nd_record_cnt) DIV 2;
                    IF  bd50_RecordPositionValid (curr_trans^, curr_tree_id, np_ptr, pos)
                    THEN
                        BEGIN
                        pRec           := @nd_body [pos];
                        StopPrimKeyLen := pRec^.recKey_gg00.keyLen_gg00;
                        g10mv ('VBD50 ',   4,    
                              KEY_MXSP00, KEY_MXSP00,
                              @pRec^.recKey_gg00.keyVal_gg00, 1,
                              @StopPrimKey, 1, StopPrimKeyLen, 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
                    (*ENDIF*) 
                    END
                (*ENDWITH*) 
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  nptrs.np_ptr <> NIL
    THEN
        b13r_release_node (nptrs, PrimCurrent, lru_normal);
    (*ENDIF*) 
    bd30ReleaseSubTree (PrimCurrent)
    END;
(*ENDWITH*) 
&ifdef TRACE
IF  StartPrimKeyLen = 0
THEN
    t01sname (bd_idx_create, 'ZEROKEY     ')
ELSE
    t01buf   (bd_idx_create, StartPrimKey, 1, StartPrimKeyLen);
(*ENDIF*) 
IF  StopPrimKeyLen = 0
THEN
    t01sname (bd_idx_create, 'ZEROKEY     ')
ELSE
    t01buf   (bd_idx_create, StopPrimKey, 1, StopPrimKeyLen);
(*ENDIF*) 
&endif
END;
 
(*------------------------------*) 
 
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);
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    IF  FIRST_INDEX_LEVEL_BD00 >= currRootNptrs_bd00.np_ptr^.nd_level
    THEN
        g01abort (bd50x2IllegalLockHandling_csp03, csp3_n_btree,
              MSG_1_WRONG_LEVEL, curr_tree_id.fileRoot_gg00);
    (*ENDIF*) 
    bd51SearchBranch (current, pSepKey, keyLen, currIndexNptrs_bd00.np_ptr, recIndex);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        leaf := bd52SubtreePno (currIndexNptrs_bd00.np_ptr, recIndex);
        IF  recIndex = FIRST_REC_INDEX_BD00
        THEN
            leftLeaf := NIL_PAGE_NO_GG00 (* node will not fulfill saveness condition *)
        ELSE
            leftLeaf := bd52SubtreePno (currIndexNptrs_bd00.np_ptr, recIndex -1)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50DropSubTree (
            subRoot        : tsp00_PageNo;
            numberOfLongs  : integer;
            bOnlyEmpty     : boolean;
            VAR current    : tbd_current_tree);
 
VAR
      last         : boolean;
      aux_error    : tgg00_BasisError;
      level        : tsp00_Int2;
      index        : tsp00_Int4;
      next_subroot : tsp00_PageNo;
      nptr         : tbd_node_ptrs;
 
BEGIN
nptr.np_ptr   := NIL;
nptr.np_cbptr := NIL;
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    IF  subRoot = fileRoot_gg00
    THEN
        nptr := currRootNptrs_bd00
    ELSE
        bd13GetNode (current, subRoot, plmLock_ebd00, nr_for_update, nptr);
    (*ENDIF*) 
    IF  (trError_gg00 = e_file_not_accessible) OR (trError_gg00 = e_bad_file)
    THEN
        trError_gg00 := e_ok;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        level := nptr.np_ptr^.nd_level;
        IF  level = LEAF_LEVEL_BD00
        THEN
            BEGIN
            IF  numberOfLongs > 0
            THEN
                bd50_DropLong (curr_trans^, nptr.np_ptr, numberOfLongs);
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  bOnlyEmpty AND (subRoot = fileRoot_gg00)
                THEN
                    WITH currRootNptrs_bd00.np_ptr^ DO
                        BEGIN
                        nd_sorted            := false;
                        nd_bottom            := BODY_BEG_BD00;
                        nd_record_cnt        := 0;
                        nd_level             := LEAF_LEVEL_BD00;
                        nd_right             := NIL_PAGE_NO_GG00;
                        currRootUpdated_bd00 := true
                        END
                    (*ENDWITH*) 
                ELSE
                    b13free_node (nptr, current)
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        ELSE
            (*  level > leaflevel *)
            BEGIN
            index     := FIRST_REC_INDEX_BD00;
            last      := false;
            aux_error := e_ok;
            REPEAT
                next_subroot := bd52SubtreePno (nptr.np_ptr, index);
                IF  (ftsTemp_egg00 in fileType_gg00   ) AND
                    (numberOfLongs = 0                ) AND
                    (level = FIRST_INDEX_LEVEL_BD00)
                THEN
                    bd13FreeTempPageNo (next_subroot, current)
                ELSE
                    bd50DropSubTree (next_subroot, numberOfLongs,
                          bOnlyEmpty, current);
                (*ENDIF*) 
                IF  trError_gg00 = e_bad_datapage
                THEN
                    BEGIN
                    aux_error := trError_gg00;
                    trError_gg00    := e_ok
                    END;
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    b51next_branch (nptr.np_ptr, index, last)
                (*ENDIF*) 
            UNTIL
                last OR (trError_gg00 <> e_ok);
            (*ENDREPEAT*) 
            IF  trError_gg00 = e_ok
            THEN
                trError_gg00 := aux_error;
            (*ENDIF*) 
            IF  (trError_gg00 = e_ok) OR (trError_gg00 = e_bad_datapage)
            THEN
                BEGIN
                aux_error    := trError_gg00;
                trError_gg00 := e_ok;
                IF  bOnlyEmpty AND (nptr.np_ptr^.nd_id = fileRoot_gg00)
                THEN
                    WITH currRootNptrs_bd00.np_ptr^ DO
                        BEGIN
                        nd_sorted            := false;
                        nd_bottom            := BODY_BEG_BD00;
                        nd_record_cnt        := 0;
                        nd_level             := LEAF_LEVEL_BD00;
                        nd_right             := NIL_PAGE_NO_GG00;
                        currRootUpdated_bd00 := true
                        END
                    (*ENDWITH*) 
                ELSE
                    b13free_node (nptr, current);
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    trError_gg00 := aux_error
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*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
      bd50EvalPageCount (
            VAR start_key    : tgg00_Lkey;
            VAR stop_key     : tgg00_Lkey;
            count_records    : boolean;
            VAR page_count   : tsp00_Int4;
            VAR all_page_cnt : tsp00_Int4;
            VAR record_cnt   : tsp00_Int4;
            VAR current      : tbd_current_tree);
 
CONST
      c_maxlevel_arr_ix = MAX_LEVEL_BD00 + 1;
 
VAR
      found            : boolean;
      level            : tsp00_Int2;
      sep_level        : tsp00_Int2;
      subroot          : tsp00_PageNo;
      startIndexPage   : tsp00_PageNo;
      nptr             : tbd_node_ptrs;
      path             : integer;
      avg_amount       : ARRAY [1..c_maxlevel_arr_ix, 1..3] OF tsp00_Longreal;
      coverings        : ARRAY [1..c_maxlevel_arr_ix, 1..3] OF tsp00_Int4;
      indices          : ARRAY [1..c_maxlevel_arr_ix, 1..3] OF tsp00_Int4;
      maxindices       : ARRAY [1..c_maxlevel_arr_ix, 1..3] OF tsp00_Int4;
      pnos             : ARRAY [1..c_maxlevel_arr_ix, 1..3] OF tsp00_PageNo;
      left_page_cnt    : ARRAY [                      1..3] OF tsp00_Longreal;
      middl_subroot    : tsp00_PageNo;
      startLeafPage    : tsp00_PageNo;
      stopLeafPage     : tsp00_PageNo;
      sum_indices      : integer;
      all_page_cnt_real: tsp00_Longreal;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    all_page_cnt      := 0;
    all_page_cnt_real := 0.0;
    record_cnt        := -1;
    subroot           := fileRoot_gg00;
    startLeafPage     := subroot;
    startIndexPage    := subroot;
    stopLeafPage      := subroot;
    FOR path := 1 TO 3 DO
        BEGIN
        FOR level := 1 TO c_maxlevel_arr_ix DO
            BEGIN
            coverings  [level, path] := MAX_INT4_SP00;
            indices    [level, path] := MAX_INT4_SP00;
            maxindices [level, path] := MAX_INT4_SP00;
            pnos       [level, path] := NIL_PAGE_NO_GG00;
            avg_amount [level, path] := 0
            END;
        (*ENDFOR*) 
        left_page_cnt  [path] := 0;
        END;
    (*ENDFOR*) 
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    (* *)
    (* first access with start key *)
    (* *)
    REPEAT
        IF  subroot = fileRoot_gg00
        THEN
            nptr := currRootNptrs_bd00
        ELSE
            BEGIN
            IF  nptr.np_ptr <> currRootNptrs_bd00.np_ptr
            THEN
                b13r_release_node (nptr, current, lru_normal);
            (*ENDIF*) 
            bd13GetNode (current, subroot, plmLock_ebd00, nr_for_read, nptr)
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            level := nptr.np_ptr^.nd_level;
            IF  level =  LEAF_LEVEL_BD00 (* e_root_is_leaf *)
            THEN
                BEGIN
                trError_gg00 := e_no_next_record;
                all_page_cnt := 1;
                page_count   := 1
                END
            ELSE
                BEGIN
                bd51SearchBranch (current, @start_key.keyVal_gg00, start_key.keyLen_gg00,
                      nptr.np_ptr, indices [level,1]);
                indices    [level, 2] := indices [level, 1];
                pnos       [level, 1] := nptr.np_ptr^.nd_id;
                pnos       [level, 2] := pnos    [level, 1];
                coverings  [level, 1] := nptr.np_ptr^.nd_bottom - BODY_BEG_BD00
                      +                           nptr.np_ptr^.nd_record_cnt*POINTERSIZE_BD00;
                coverings  [level, 2] := coverings  [level, 1];
                maxindices [level, 1] := nptr.np_ptr^.nd_record_cnt - 1;
                maxindices [level, 2] := maxindices [level, 1];
                IF  level > FIRST_INDEX_LEVEL_BD00
                THEN
                    subroot := bd52SubtreePno (nptr.np_ptr, indices  [level,1])
                ELSE
                    BEGIN (* FIRST_INDEX_LEVEL_BD00 *)
                    all_page_cnt   := maxindices [level, 1] + 1;
                    startIndexPage := nptr.np_ptr^.nd_id;
                    IF  count_records
                    THEN
                        startLeafPage := bd52SubtreePno (nptr.np_ptr, indices  [level,1]);
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
    UNTIL
        (level = FIRST_INDEX_LEVEL_BD00) OR (trError_gg00 <> e_ok);
    (*ENDREPEAT*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (* *)
    (* second access with stop key *)
    (* *)
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        subroot       := fileRoot_gg00;
        middl_subroot := NIL_PAGE_NO_GG00;
        REPEAT
            IF  subroot = fileRoot_gg00
            THEN
                nptr := currRootNptrs_bd00
            ELSE
                BEGIN
                IF  nptr.np_ptr <> currRootNptrs_bd00.np_ptr
                THEN
                    b13r_release_node (nptr, current, lru_normal);
                (*ENDIF*) 
                bd13GetNode (current, subroot, plmLock_ebd00, nr_for_read, nptr)
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                level := nptr.np_ptr^.nd_level;
                bd51SearchBranch (current, @stop_key.keyVal_gg00, stop_key.keyLen_gg00,
                      nptr.np_ptr, indices [level,3]);
                pnos       [level, 3] := nptr.np_ptr^.nd_id;
                coverings  [level, 3] := nptr.np_ptr^.nd_bottom - BODY_BEG_BD00
                      +                           nptr.np_ptr^.nd_record_cnt*POINTERSIZE_BD00;
                maxindices [level, 3] := nptr.np_ptr^.nd_record_cnt - 1;
                IF  (
                    (indices  [level,1] <> indices  [level,3]) OR (level = FIRST_INDEX_LEVEL_BD00)
                    )
                    AND (middl_subroot = NIL_PAGE_NO_GG00)
                THEN
                    BEGIN
                    sum_indices := (indices  [level,1] + indices  [level,3]);
                    indices  [level,2] := sum_indices DIV 2;
                    IF  level > FIRST_INDEX_LEVEL_BD00
                    THEN
                        middl_subroot := bd52SubtreePno (nptr.np_ptr, indices  [level,2]);
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  level > FIRST_INDEX_LEVEL_BD00
                THEN
                    subroot := bd52SubtreePno (nptr.np_ptr, indices  [level,3])
                ELSE
                    BEGIN (* FIRST_INDEX_LEVEL_BD00 *)
                    IF  startIndexPage <> nptr.np_ptr^.nd_id
                    THEN
                        all_page_cnt := all_page_cnt + maxindices [level,3] + 1;
                    (*ENDIF*) 
                    IF  count_records
                    THEN
                        stopLeafPage := bd52SubtreePno (nptr.np_ptr, indices  [level,3]);
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
        UNTIL
            (level = FIRST_INDEX_LEVEL_BD00) OR (trError_gg00 <> e_ok)
        (*ENDREPEAT*) 
        END;
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND (middl_subroot <> NIL_PAGE_NO_GG00)
    THEN
        BEGIN
        (* *)
        (* IN this case the tree has more than one indexlevel *)
        (* *)
        subroot := middl_subroot;
        REPEAT
            IF  subroot <> middl_subroot
            THEN
                b13r_release_node (nptr, current, lru_normal);
            (*ENDIF*) 
            bd13GetNode (current, subroot, plmLock_ebd00, nr_for_read, nptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                level                 := nptr.np_ptr^.nd_level;
                pnos       [level, 2] := nptr.np_ptr^.nd_id;
                coverings  [level, 2] := nptr.np_ptr^.nd_bottom - BODY_BEG_BD00
                      +                           nptr.np_ptr^.nd_record_cnt*POINTERSIZE_BD00;
                maxindices [level, 2] := nptr.np_ptr^.nd_record_cnt - 1;
                IF  sum_indices = 2*indices  [succ(level), 2]
                THEN
                    BEGIN
                    sum_indices       := maxindices [level, 2];
                    indices [level,2] := sum_indices DIV 2
                    END
                ELSE
                    BEGIN
                    (* once we took the leaf with smaller keys *)
                    sum_indices       := maxindices [level, 2] * 2;
                    indices [level,2] := maxindices [level, 2]
                    END;
                (*ENDIF*) 
                IF  level > FIRST_INDEX_LEVEL_BD00
                THEN
                    subroot := bd52SubtreePno (nptr.np_ptr, indices  [level, 2])
                (*ENDIF*) 
                END
            (*ENDIF*) 
        UNTIL
            (level = FIRST_INDEX_LEVEL_BD00) OR (trError_gg00 <> e_ok);
        (*ENDREPEAT*) 
        END;
    (* after all estimation with accumulated average *)
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (* *)
    (* start estimation *)
    (* *)
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        FOR level := MAX_LEVEL_BD00 DOWNTO 1 DO
            BEGIN
            FOR  path := 1 TO 3 DO
                BEGIN
                IF  indices [level, path] <> MAX_INT4_SP00
                THEN
                    BEGIN
                    IF  MAX_LEVEL_BD00 = level
                    THEN
                        avg_amount [level, path] := maxindices [level, path] + 1
                    ELSE
                        IF  MAX_INT4_SP00  = indices  [succ(level), path]
                        THEN
                            avg_amount [level, path] := maxindices [level, path] + 1
                        ELSE
                            IF  (pnos [succ(level), path] = fileRoot_gg00)
                                AND
                                (avg_amount [succ(level), path] <= 6)
                                AND
                                (pnos [level, 1] <> pnos [level, 2])
                                AND
                                (pnos [level, 2] <> pnos [level, 3])
                            THEN
                                avg_amount [level, path] := maxindices [level, path] + 1
                            ELSE
                                (* hsNoTreeBalance_egg00 IN curr_tree_id.fileHandling_gg00*)
                                IF  ftsDynamic_egg00 IN curr_tree_id.fileType_gg00
                                THEN
                                    avg_amount [level, path] :=
                                          ((FULLCOVERING_BD00 * 50 / 100)
                                          * (maxindices [level, path] + 1))
                                          /coverings [level, path]
                                ELSE
                                    avg_amount [level, path] :=
                                          ((FULLCOVERING_BD00 * 80 / 100)
                                          * (maxindices [level, path] + 1))
                                          /coverings [level, path]
                                (*ENDIF*) 
                            (*ENDIF*) 
                        (*ENDIF*) 
                    (*ENDIF*) 
                    END;
&               ifdef TRACE
                (*ENDIF*) 
                t01p2int4 (bd_index, 'level:      ', level
                      ,              'path:       ', path);
                t01int4   (bd_index, 'pno         ', pnos [level, path]);
                t01p2int4 (bd_index, 'covering    ', coverings [level, path]
                      ,              'maxindex    ', maxindices [level, path]);
                t01int4   (bd_index, 'index       ', indices [level, path]);
                t01real   (bd_index, 'avg_amount_1', avg_amount [level, path]
                      , 7)
&                     endif
                END;
            (*ENDFOR*) 
            (* PTS 1104630 Alexander Kley *)
            (* IF  (pnos [succ(level), path] = was changed into  : Alexander Kley 98\9\8 *)
            IF  (pnos [succ(level), 3] =  curr_tree_id.fileRoot_gg00)
                AND
                (avg_amount [succ(level), 3] <= 3)
                AND
                (pnos [level, 1] =  pnos [level, 2])
            THEN
                IF  pnos [level, 1] <> pnos [level, 3]
                THEN
                    avg_amount [level, 1] := (maxindices [level, 1] +
                          maxindices [level, 3] + 2) / 2.0
                ELSE
                    avg_amount [level, 1] :=
                          ((FULLCOVERING_BD00 * 75 / 100)
                          * (maxindices [level, 1] + 1))
                          /coverings [level, 1]
                (*ENDIF*) 
            ELSE
                avg_amount [level, 1] := (avg_amount [level, 1]
                      +                      avg_amount [level, 2]
                      +                      avg_amount [level, 3]) / 3.0;
            (*ENDIF*) 
&           ifdef TRACE
            t01int4 (bd_index, 'level:      ', level);
            t01real (bd_index, 'avg_amount_2', avg_amount [level, 1], 7);
&           endif
            END;
        (*ENDFOR*) 
        (* estimate number of pages between start and stop key *)
        sep_level := MAX_LEVEL_BD00;
        found     := false;
        REPEAT
            IF  (pnos[sep_level,1] <> NIL_PAGE_NO_GG00) AND
                (indices [sep_level, 3] <> indices [sep_level, 1])
            THEN
                found := true;
            (*ENDIF*) 
            IF  (NOT found)
            THEN
                sep_level := sep_level - 1;
            (*ENDIF*) 
        UNTIL
            (found OR (sep_level = 1));
        (*ENDREPEAT*) 
        FOR level := sep_level DOWNTO 1 DO
            BEGIN
            left_page_cnt  [1] := left_page_cnt [1]  * avg_amount [level, 1] + indices [level, 1];
            IF  (left_page_cnt [3] = 0)
            THEN
                left_page_cnt [3] := indices [level, 3]
            ELSE
                IF  (pnos[level,1] <> pnos[level,2])
                THEN
                    left_page_cnt [3] := (left_page_cnt [3] - 2) *  avg_amount [level, 1] +
                          maxindices [level,1] + 1 +
                          maxindices [level,2] + 1 +
                          indices [level, 3]
                ELSE
                    left_page_cnt [3] := (left_page_cnt [3] - 1) *  avg_amount [level, 1] +
                          maxindices [level,1] + 1 +
                          indices [level, 3];
                (*ENDIF*) 
            (*ENDIF*) 
&           ifdef TRACE
            t01int4 (bd_index, '----- Level ', level);
            t01real (bd_index, '#LeftPages 1', left_page_cnt [1], 7);
            t01real (bd_index, '#LeftPages 3', left_page_cnt [3], 7);
&           endif
            END;
        (*ENDFOR*) 
        page_count := trunc (left_page_cnt [3] - left_page_cnt [1] + 1.5);
&       ifdef TRACE
        t01int4 (bd_index, 'NewPageCount', page_count);
&       endif
        (* estimate number of all pages in tree *)
        FOR level := MAX_LEVEL_BD00 DOWNTO 1 DO
            BEGIN
            IF  (pnos[level,1] <> NIL_PAGE_NO_GG00)
            THEN
                IF  (all_page_cnt_real < 1)
                THEN
                    all_page_cnt_real := maxindices [level,1] + 1
                ELSE
                    IF  (pnos[level,1] <> pnos[level,2])
                    THEN
                        all_page_cnt_real := (all_page_cnt_real - 3) * avg_amount [level, 1] +
                              maxindices [level,1] + 1 +
                              maxindices [level,2] + 1 +
                              maxindices [level,3] + 1
                    ELSE
                        IF  (pnos[level,1] <> pnos[level,3])
                        THEN
                            all_page_cnt_real := (all_page_cnt_real - 2) * avg_amount [level, 1] +
                                  maxindices [level,1] + 1 +
                                  maxindices [level,3] + 1
                        ELSE
                            all_page_cnt_real := (all_page_cnt_real - 1) * avg_amount [level, 1] +
                                  maxindices [level,1] + 1;
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
&           ifdef TRACE
            (*ENDIF*) 
            t01int4 (bd_index, '----- Level ', level);
            t01real (bd_index, '# All Pages ', all_page_cnt_real , 7);
&           endif
            END;
        (*ENDFOR*) 
        all_page_cnt := trunc (all_page_cnt_real + 0.5);
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_no_next_record
    THEN
        trError_gg00 := e_ok;
    (*ENDIF*) 
    IF  count_records AND (trError_gg00 = e_ok)
    THEN
        bd50_CountRecords (current, start_key, stop_key, startIndexPage,
              startLeafPage, stopLeafPage, record_cnt, page_count);
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd50GetRecPtr (
            VAR Current : tbd_current_tree;
            VAR Nptr    : tbd_node_ptrs;
            RecIndex    : tsp00_Int4) : tgg00_RecPtr;
 
VAR
      RecPos : tsp00_Int4;
      pRec   : tgg00_RecPtr;
 
BEGIN
WITH Current, curr_trans^, Nptr, np_ptr^ DO
    BEGIN
    RecPos := nd_pointer_list [MAX_POINTERINDEX_BD00 - RecIndex];
    IF  (RecPos < BODY_BEG_BD00) OR (RecPos > nd_bottom)
    THEN
        BEGIN
        trError_gg00 := e_illegal_entrypos;
        g01opmsg (sp3p_knldiag, sp3m_error, bd50c9IllegalEntryPos_csp03,
              csp3_n_btree, 'Illegal entry pos       ', RecPos);
        b06dump_bad_page (trTaskId_gg00, 'd',
              FILE_EXT_COR_BD00, nd_id, np_ptr, 1);
        b06write_filename_and_root (curr_tree_id);
        pRec := NIL
        END
    ELSE
        pRec := @nd_body [RecPos];
    (*ENDIF*) 
    bd50GetRecPtr := pRec
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50ExtractForeignKey (
            VAR m           : tgg00_MessBlock;
            VAR current     : tbd_current_tree;
            VAR tempCurrent : tbd_current_tree);
 
CONST
      c_init_inv_tree  = true;
 
VAR
      bStop           : boolean;
      bIsUndef        : boolean;
      recIndex        : tsp00_Int4;
      recPos          : tsp00_Int4;
      recIndexForLeaf : tsp00_Int4;
      nextLeafPage    : tsp00_PageNo;
      nextIndexPage   : tsp00_PageNo;
      nptr            : tbd_node_ptrs;
      pRec            : tgg00_RecPtr;
      neighbs         : tbd_neighbors;
      recKey          : tgg00_Lkey;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    bStop              := false;
    nptr.np_ptr        := NIL;
    nptr.np_cbptr      := NIL;
    recKey.keyLen_gg00 := 0;
    nextIndexPage      := NIL_PAGE_NO_GG00;
    bd50FindLeaf (recKey.keyVal_gg00, recKey.keyLen_gg00,
          NOT LOCK_LEAF_EXCL_BD00, nptr, neighbs, recIndexForLeaf, current);
    WHILE (trError_gg00 = e_ok) AND (NOT bStop) DO
        BEGIN
        recIndex := FIRST_REC_INDEX_BD00;
        WHILE (trError_gg00 = e_ok) AND (recIndex < nptr.np_ptr^.nd_record_cnt) DO
            BEGIN
            WITH nptr, np_ptr^, m.mb_qual^  DO
                BEGIN
                recPos := nd_pointer_list [MAX_POINTERINDEX_BD00 - recIndex];
                IF  bd50_RecordPositionValid (curr_trans^, curr_tree_id, nptr.np_ptr, recPos)
                THEN
                    BEGIN
                    pRec := @nd_body [recPos];
                    k33mult_inv_key( curr_trans^, curr_tree_id, curr_tree_id, NOT c_init_inv_tree,
                          m.mb_st, pRec, mcol_pos, mcol_pos + mcol_cnt - 1, recKey, bIsUndef, trError_gg00);
                    IF  (recKey.keyLen_gg00 > 0) AND (trError_gg00 = e_ok)
                    THEN
                        BEGIN
                        recKey.keyRecLenSpace_gg00 := recKey.keyLen_gg00 +  cgg_rec_key_offset;
                        bd30AddToTempTree (NOT c_count_duplicates, recKey, tempCurrent);
                        IF  trError_gg00 = e_duplicate_key
                        THEN
                            trError_gg00 := e_ok
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    recIndex := recIndex + 1
                    END
                (*ENDIF*) 
                END
            (*ENDWITH*) 
            END;
        (*ENDWHILE*) 
        IF  trRteCommPtr_gg00^.to_cancel
        THEN
            trError_gg00 := e_cancelled;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            nextLeafPage := nptr.np_ptr^.nd_right;
            IF  nextLeafPage = NIL_PAGE_NO_GG00
            THEN
                bStop := true
            ELSE
                BEGIN
                IF  (ftsPerm_egg00 IN curr_tree_id.fileType_gg00) AND
                    (currRightBound_bd00 = nptr.np_ptr^.nd_id   ) AND (* subtree boundary reached *)
                    (currIndexNptrs_bd00.np_ptr <> NIL          )
                THEN
                    nextIndexPage := currIndexNptrs_bd00.np_ptr^.nd_right;
                (*ENDIF*) 
                b13r_release_node (nptr, current, lru_mid);
                IF  nextIndexPage <> NIL_PAGE_NO_GG00
                THEN
                    BEGIN
                    bd30ReleaseSubTree (current);
                    bd30GetSubTree (current, nextIndexPage);
                    nextIndexPage := NIL_PAGE_NO_GG00;
                    END;
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    bd13GetNode (current, nextLeafPage, plmLock_ebd00, nr_for_read, nptr)
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_mid)
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50ExtractTable (
            VAR current      : tbd_current_tree;
            VAR hostFileName : tsp00_VFilename);
 
VAR
      level           : tsp00_Int2;
      nextPageNo      : tsp00_PageNo;
      leftMostPageNo  : tsp00_PageNo;
      pDumpPage       : tsp00_VfBufaddr;
      pNodes          : tbd_node_ptrs;
      hostFile        : tgg00_VfFileref;
      hostFileErr     : tsp00_VfReturn;
      hostFileErrText : tsp00_ErrText;
 
BEGIN
nextPageNo     := current.curr_tree_id.fileRoot_gg00;
leftMostPageNo := NIL_PAGE_NO_GG00;
(* *)
pNodes.np_ptr   := NIL;
pNodes.np_cbptr := NIL;
WITH current.curr_trans^ DO
    BEGIN
    hostFile.buf_cnt := 0;
    vfopen (hostFileName, hostFile.no, hostFileErr, hostFileErrText);
    IF  hostFileErr <> vf_ok
    THEN
        trError_gg00 := e_hostfile_error
    ELSE
        BEGIN
        WHILE (trError_gg00 = e_ok) AND (nextPageNo <> NIL_PAGE_NO_GG00) DO
            BEGIN
            bd13GetNode (current, nextPageNo, plmLock_ebd00, nr_for_read, pNodes);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                pDumpPage := @pNodes.np_ptr^;
                vfwrite (hostFile.no, pDumpPage, hostFileErr, hostFileErrText);
                IF  hostFileErr <> vf_ok
                THEN
                    trError_gg00 := e_hostfile_error
                ELSE
                    BEGIN
                    level      := pNodes.np_ptr^.nd_level;
                    nextPageNo := pNodes.np_ptr^.nd_right;
                    IF  (level <> LEAF_LEVEL_BD00) AND (leftMostPageNo = NIL_PAGE_NO_GG00)
                    THEN
                        leftMostPageNo := bd52SubtreePno (pNodes.np_ptr, FIRST_REC_INDEX_BD00);
                    (*ENDIF*) 
                    IF  (nextPageNo = NIL_PAGE_NO_GG00) AND (leftMostPageNo <> NIL_PAGE_NO_GG00)
                    THEN
                        BEGIN
                        nextPageNo     := leftMostPageNo;
                        leftMostPageNo := NIL_PAGE_NO_GG00;
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  pNodes.np_ptr <> NIL
            THEN
                b13r_release_node (pNodes, current, lru_normal)
            (*ENDIF*) 
            END
        (*ENDWHILE*) 
        END;
    (*ENDIF*) 
    IF  (hostFileErr = vf_ok) OR (hostFileErr = vf_eof)
    THEN
        vfclose (hostFile.no, hostFileErr, hostFileErrText);
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50FindBranchNode (
            VAR sepkey            : tsp00_Key;
            keyLen                : tsp00_Int4;
            wantedLevel           : tsp00_Int2;
            VAR nptrs             : tbd_node_ptrs;
            VAR neighbs           : tbd_neighbors;
            VAR bWantedLevelFound : boolean;
            VAR current           : tbd_current_tree);
 
VAR
      bIsPerm         : boolean;
      bWasLastRecord  : boolean;
      currentLevel    : tsp00_Int2;
      recIndex        : tsp00_Int4;
      subRootRecIndex : tsp00_Int4;
      leftNeighbor    : tsp00_PageNo;
      rightNeighbor   : tsp00_PageNo;
      leftSubRoot     : tsp00_PageNo;
      rightSubRoot    : tsp00_PageNo;
      subRoot         : tsp00_PageNo;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    bWantedLevelFound             := false;
    bIsPerm            := ftsPerm_egg00 IN fileType_gg00;
    currentLevel       := LEAF_LEVEL_BD00;
    subRoot            := fileRoot_gg00;
    rightNeighbor      := NIL_PAGE_NO_GG00;
    leftNeighbor       := NIL_PAGE_NO_GG00;
    rightSubRoot       := NIL_PAGE_NO_GG00;
    leftSubRoot        := NIL_PAGE_NO_GG00;
    neighbs.ln         := NIL_PAGE_NO_GG00;
    neighbs.rn         := NIL_PAGE_NO_GG00;
    (* *)
    IF  (wantedLevel > FIRST_INDEX_LEVEL_BD00) AND
        (ftsConcurrent_egg00 IN fileType_gg00) AND
        (
        (NOT bd20IsPageExclusiveLocked (currRootNptrs_bd00.np_cbptr)) OR
        (currIndexNptrs_bd00.np_ptr <> NIL                          )
        )
    THEN
        g01abort (bd50x1IllegalLockHandling_csp03,
              csp3_n_btree, MSG_1_WRONG_LOCK, fileRoot_gg00);
    (*ENDIF*) 
    REPEAT
        IF  subRoot = fileRoot_gg00
        THEN
            nptrs := currRootNptrs_bd00
        ELSE
            BEGIN
            IF  ((nptrs.np_ptr <> currRootNptrs_bd00.np_ptr ) AND
                (nptrs.np_ptr <> currIndexNptrs_bd00.np_ptr))
            THEN
                b13r_release_node (nptrs, current, lru_normal);
            (*ENDIF*) 
            IF  currentLevel = succ (wantedLevel)
            THEN
                bd13GetNode (current, subRoot, plmLock_ebd00, nr_for_update, nptrs)
            ELSE
                bd13GetNode (current, subRoot, plmLock_ebd00, nr_for_read, nptrs);
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            WITH nptrs, np_ptr^ DO
                BEGIN
                IF  bIsPerm AND (nd_right <> rightNeighbor) AND
                    (nd_id <> fileRoot_gg00) (* caused by tree growing, root has neighbor and level 0 !*)
                THEN
                    BEGIN
                    g01opmsg (sp3p_knldiag, sp3m_error, bd50c1InvalidStructure_csp03,
                          csp3_n_btree,'invalid index structure ', rightNeighbor);
                    b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1);
                    trError_gg00 := e_invalid_index_structure
                    END;
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    currentLevel := nd_level;
                    IF  currentLevel >= succ (wantedLevel)
                    THEN
                        BEGIN
                        bd51SearchBranch (current, @sepkey, keyLen, np_ptr, recIndex);
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            subRootRecIndex := recIndex;
                            subRoot         := bd52SubtreePno (np_ptr, recIndex);
                            b51next_branch (np_ptr, recIndex, bWasLastRecord);
                            IF  bWasLastRecord
                            THEN
                                bd50_GetRightSubTree (current, np_ptr, recIndex,
                                      rightSubRoot, rightNeighbor)
                            ELSE
                                rightNeighbor := bd52SubtreePno (np_ptr, recIndex);
                            (*ENDIF*) 
                            IF  trError_gg00 = e_ok
                            THEN
                                BEGIN
                                rightSubRoot := rightNeighbor;
                                bd50_GetLeftSubTree (current, np_ptr, subRootRecIndex,
                                      leftSubRoot, leftNeighbor);
                                IF  trError_gg00 = e_ok
                                THEN
                                    leftSubRoot := leftNeighbor
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
    UNTIL
        (currentLevel <= wantedLevel) OR (trError_gg00 <> e_ok);
    (*ENDREPEAT*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        neighbs.ln := leftNeighbor;
        neighbs.rn := rightNeighbor;
&       ifdef TRACE
        t01p2int4 (bd_index, 'LeafNeighbor', leftNeighbor
              ,              'RightNeighbo', rightNeighbor);
&       endif
        END;
    (*ENDIF*) 
    bWantedLevelFound := (currentLevel = wantedLevel);
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50FindFirstLevelIndexNode (
            VAR sepkey  : tsp00_Key;
            keyLen      : tsp00_Int4;
            VAR nptrs   : tbd_node_ptrs;
            VAR neighbs : tbd_neighbors;
            VAR bFound  : boolean;
            VAR current : tbd_current_tree);
 
VAR
      bIsPerm         : boolean;
      bWasLastRecord  : boolean;
      recIndex        : tsp00_Int4;
      subRootRecIndex : tsp00_Int4;
      leftNeighbor    : tsp00_PageNo;
      rightNeighbor   : tsp00_PageNo;
      leftSubRoot     : tsp00_PageNo;
      rightSubRoot    : tsp00_PageNo;
      subRoot         : tsp00_PageNo;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    bFound             := false;
    bIsPerm            := ftsPerm_egg00 IN fileType_gg00;
    subRoot            := fileRoot_gg00;
    rightNeighbor      := NIL_PAGE_NO_GG00;
    leftNeighbor       := NIL_PAGE_NO_GG00;
    rightSubRoot       := NIL_PAGE_NO_GG00;
    leftSubRoot        := NIL_PAGE_NO_GG00;
    neighbs.ln         := NIL_PAGE_NO_GG00;
    neighbs.rn         := NIL_PAGE_NO_GG00;
    currLeftBound_bd00 := NIL_PAGE_NO_GG00;
    currRightBound_bd00:= NIL_PAGE_NO_GG00;
    REPEAT
        IF  subRoot = fileRoot_gg00
        THEN
            nptrs := currRootNptrs_bd00
        ELSE
            BEGIN
            IF  ((nptrs.np_ptr <> currRootNptrs_bd00.np_ptr ) AND
                (nptrs.np_ptr <> currIndexNptrs_bd00.np_ptr))
            THEN
                b13r_release_node (nptrs, current, lru_normal);
            (*ENDIF*) 
            bd13GetNode (current, subRoot, plmLock_ebd00, nr_for_read, nptrs);
            IF  (trError_gg00 = e_ok) AND (bIsPerm) AND
                (nptrs.np_ptr^.nd_level = FIRST_INDEX_LEVEL_BD00)
            THEN
                BEGIN
                IF  g01glob.bd_lock_check AND (currIndexNptrs_bd00.np_ptr <> NIL)
                THEN
                    g01abort (bd50x3IllegalLockHandling_csp03, csp3_n_btree,
                          MSG_1_IDX_LOCK_EXIST, currIndexNptrs_bd00.np_ptr^.nd_id);
                (*ENDIF*) 
                currIndexNptrs_bd00 := nptrs
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            WITH nptrs, np_ptr^ DO
                BEGIN
                IF  bIsPerm AND  (nd_right <> rightNeighbor)
                THEN
                    BEGIN
                    g01opmsg (sp3p_knldiag, sp3m_error, bd50c2InvalidStructure_csp03,
                          csp3_n_btree,'invalid index structure ', rightNeighbor);
                    b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1);
                    trError_gg00 := e_invalid_index_structure
                    END;
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    IF  nd_level = FIRST_INDEX_LEVEL_BD00
                    THEN
                        BEGIN
                        bFound     := true;
                        neighbs.ln := leftNeighbor;
                        neighbs.rn := rightNeighbor;
                        IF  bIsPerm
                        THEN
                            BEGIN
                            currLeftBound_bd00  := bd52SubtreePno (np_ptr, FIRST_REC_INDEX_BD00);
                            currRightBound_bd00 := bd52SubtreePno (np_ptr, nd_record_cnt - 1)
                            END
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        bd51SearchBranch (current, @sepkey, keyLen, np_ptr, recIndex );
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            subRootRecIndex := recIndex;
                            subRoot         := bd52SubtreePno (np_ptr, recIndex);
                            b51next_branch (np_ptr, recIndex, bWasLastRecord);
                            IF  bWasLastRecord
                            THEN
                                bd50_GetRightSubTree (current, np_ptr, recIndex,
                                      rightSubRoot, rightNeighbor)
                            ELSE
                                rightNeighbor := bd52SubtreePno (np_ptr, recIndex);
                            (*ENDIF*) 
                            IF  trError_gg00 = e_ok
                            THEN
                                BEGIN
                                rightSubRoot := rightNeighbor;
                                bd50_GetLeftSubTree (current, np_ptr, subRootRecIndex,
                                      leftSubRoot, leftNeighbor);
                                IF  trError_gg00 = e_ok
                                THEN
                                    leftSubRoot := leftNeighbor
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
    UNTIL
        bFound OR (trError_gg00 <> e_ok)
    (*ENDREPEAT*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
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);
 
VAR
      bIsPerm              : boolean;
      bFound               : boolean;
      bWasLastRecord       : boolean;
      bRootLockedExclusive : boolean;
      level                : tsp00_Int2;
      recPosition          : tsp00_Int4;
      recIndex             : tsp00_Int4;
      subRootRecIndex      : tsp00_Int4;
      leftNeighbor         : tsp00_PageNo;
      rightNeighbor        : tsp00_PageNo;
      leftSubRoot          : tsp00_PageNo;
      rightSubRoot         : tsp00_PageNo;
      subRoot              : tsp00_PageNo;
      pRec                 : tgg00_RecPtr;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    subRootRecIndex      := NIL_RECINDEX_BD00;
    bRootLockedExclusive := bd20IsPageExclusiveLocked (currRootNptrs_bd00.np_cbptr);
    bIsPerm              := ftsPerm_egg00 IN fileType_gg00;
    bFound               := false;
    (* *)
    level              := currRootNptrs_bd00.np_ptr^.nd_level;
    subRoot            := fileRoot_gg00;
    rightNeighbor      := NIL_PAGE_NO_GG00;
    leftNeighbor       := NIL_PAGE_NO_GG00;
    rightSubRoot       := NIL_PAGE_NO_GG00;
    leftSubRoot        := NIL_PAGE_NO_GG00;
    neighbs.ln         := NIL_PAGE_NO_GG00;
    neighbs.rn         := NIL_PAGE_NO_GG00;
    curr_lvl_1_pno     := NIL_PAGE_NO_GG00;
    curr_lvl_1_left    := NIL_PAGE_NO_GG00;
    currLeftBound_bd00 := NIL_PAGE_NO_GG00;
    currRightBound_bd00:= NIL_PAGE_NO_GG00;
    (* *)
    IF  (LEAF_LEVEL_BD00 = level ) AND
        (bLockLeafExcl           ) AND
        (NOT bRootLockedExclusive)
    THEN
        BEGIN
        bd30ReleaseTree (current);
        bd13GetNode (current, fileRoot_gg00, plmLock_ebd00,
              nr_for_update, currRootNptrs_bd00)
        END;
    (*ENDIF*) 
    REPEAT
        IF  subRoot = fileRoot_gg00
        THEN
            nptrs := currRootNptrs_bd00
        ELSE
            BEGIN
            IF  ((nptrs.np_ptr <> currRootNptrs_bd00.np_ptr ) AND
                (nptrs.np_ptr <> currIndexNptrs_bd00.np_ptr))
            THEN
                b13r_release_node (nptrs, current, lru_normal);
            (*ENDIF*) 
            IF  (level = FIRST_INDEX_LEVEL_BD00) AND bLockLeafExcl
            THEN
                bd13GetNode (current, subRoot, plmLock_ebd00, nr_for_update, nptrs)
            ELSE
                BEGIN
                bd13GetNode (current, subRoot, plmLock_ebd00, nr_for_read, nptrs);
                IF  (trError_gg00 = e_ok) AND (level = SECOND_INDEX_LEVEL_BD00) AND
                    bIsPerm AND (NOT bRootLockedExclusive)
                THEN
                    BEGIN
                    IF  g01glob.bd_lock_check AND (currIndexNptrs_bd00.np_ptr <> NIL)
                    THEN
                        g01abort (bd50x3IllegalLockHandling_csp03, csp3_n_btree,
                              MSG_1_IDX_LOCK_EXIST, currIndexNptrs_bd00.np_ptr^.nd_id);
                    (*ENDIF*) 
                    currIndexNptrs_bd00 := nptrs
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            WITH nptrs, np_ptr^ DO
                BEGIN
                level := nd_level;
                IF  (bIsPerm AND (nd_right <> rightNeighbor))
                    AND
                    (((level = LEAF_LEVEL_BD00) AND (nd_id <> currRightBound_bd00))
                    OR
                    (level <> LEAF_LEVEL_BD00))
                THEN
                    BEGIN
                    g01opmsg (sp3p_knldiag, sp3m_error, bd50c3InvalidStructure_csp03,
                          csp3_n_btree, 'invalid structure       ', rightNeighbor);
                    b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1);
                    IF  level = LEAF_LEVEL_BD00
                    THEN
                        trError_gg00 := e_invalid_leaves_structure
                    ELSE
                        trError_gg00 := e_invalid_index_structure
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    IF  level = LEAF_LEVEL_BD00
                    THEN
                        bFound := true
                    ELSE
                        BEGIN
                        bd51SearchBranch (current, @sepKey, keyLen, nptrs.np_ptr, recIndex );
                        subRootRecIndex := recIndex;
                        recPosition     := nd_pointer_list [MAX_POINTERINDEX_BD00 - recIndex];
                        IF  bd50_RecordPositionValid( curr_trans^, curr_tree_id,
                            nptrs.np_ptr, recPosition)
                        THEN
                            BEGIN (* neighbor handling *)
                            pRec    := @nd_body [ recPosition ];
                            subRoot := gg06PnoGet (pRec^.recPno_gg00);
                            IF  bIsPerm
                            THEN
                                BEGIN
                                b51next_branch (np_ptr, recIndex, bWasLastRecord);
                                IF  bWasLastRecord
                                THEN
                                    bd50_GetRightSubTree (current, nptrs.np_ptr, recIndex,
                                          rightNeighbor, rightSubRoot)
                                ELSE
                                    BEGIN
                                    recPosition := nd_pointer_list [MAX_POINTERINDEX_BD00 - recIndex];
                                    IF  bd50_RecordPositionValid( curr_trans^, curr_tree_id,
                                        np_ptr, recPosition)
                                    THEN
                                        BEGIN
                                        pRec         := @nd_body [ recPosition ];
                                        rightSubRoot := gg06PnoGet (pRec^.recPno_gg00);
                                        IF  (nd_level = FIRST_INDEX_LEVEL_BD00) AND
                                            ((nd_bottom + (3*pRec^.recLen_gg00)) < MAX_BOTTOM_BD00)
                                        THEN
                                            BEGIN
                                            curr_lvl_1_pno  := nd_id;
                                            curr_lvl_1_left := leftNeighbor
                                            END
                                        (*ENDIF*) 
                                        END
                                    (*ENDIF*) 
                                    END;
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            bd50_GetLeftSubTree (current, nptrs.np_ptr, subRootRecIndex, leftNeighbor, leftSubRoot);
                            IF  trError_gg00 = e_ok
                            THEN
                                BEGIN
                                rightNeighbor := rightSubRoot;
                                leftNeighbor  := leftSubRoot;
                                IF  (level = FIRST_INDEX_LEVEL_BD00) AND bIsPerm AND (NOT bRootLockedExclusive)
                                THEN
                                    BEGIN
                                    currLeftBound_bd00  := bd52SubtreePno (np_ptr, FIRST_REC_INDEX_BD00);
                                    currRightBound_bd00 := bd52SubtreePno (np_ptr, nd_record_cnt - 1)
                                    END
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDWITH*) 
        (*ENDIF*) 
    UNTIL
        bFound OR (trError_gg00 <> e_ok);
    (*ENDREPEAT*) 
    IF  bFound
    THEN
        BEGIN
        neighbs.ln      := leftNeighbor;
        neighbs.rn      := rightNeighbor;
        recIndexForLeaf := subRootRecIndex;
&       ifdef TRACE
        t01p2int4 (bd_index, 'LeafPageNo  ', nptrs.np_ptr^.nd_id, 'LeafPageIdx ', subRootRecIndex);
        t01p2int4 (bd_index, 'LeafNeighbor', leftNeighbor, 'RightNeighbo', rightNeighbor);
&       endif
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50PositionLeaf (
            leafpos           : tsp00_Int4;
            leafnodes         : tsp00_Int4;
            VAR left_estimate : tsp00_Int4;
            VAR rightestimate : tsp00_Int4;
            VAR nptrs         : tbd_node_ptrs;
            VAR current       : tbd_current_tree);
 
VAR
      bFound     : boolean;
      pRec       : tgg00_RecPtr;
      level      : tsp00_Int2;
      recIndex   : tsp00_Int4;
      amount     : tsp00_Int4;
      recPos     : tsp00_Int4;
      subRoot    : tsp00_PageNo;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    subRoot            := fileRoot_gg00;
    bFound             := false;
    level              := LEAF_LEVEL_BD00;
    curr_lvl_1_pno     := NIL_PAGE_NO_GG00;
    curr_lvl_1_left    := NIL_PAGE_NO_GG00;
    currLeftBound_bd00 := NIL_PAGE_NO_GG00;
    currRightBound_bd00:= NIL_PAGE_NO_GG00;
    left_estimate      := 0;
    rightestimate      := 0;
    REPEAT
        IF  subRoot = fileRoot_gg00
        THEN
            nptrs := currRootNptrs_bd00
        ELSE
            BEGIN
            IF  ((nptrs.np_ptr <> currRootNptrs_bd00.np_ptr ) AND
                (nptrs.np_ptr <> currIndexNptrs_bd00.np_ptr))
            THEN
                b13r_release_node (nptrs, current, lru_normal);
            (*ENDIF*) 
            bd13GetNode (current, subRoot, plmLock_ebd00, nr_for_read, nptrs);
            IF  (trError_gg00 = e_ok                            ) AND
                (nptrs.np_ptr^.nd_level = FIRST_INDEX_LEVEL_BD00) AND
                (ftsConcurrent_egg00 IN fileType_gg00           )
            THEN
                BEGIN
                IF  g01glob.bd_lock_check AND (currIndexNptrs_bd00.np_ptr <> NIL)
                THEN
                    g01abort (bd50x3IllegalLockHandling_csp03, csp3_n_btree,
                          MSG_1_IDX_LOCK_EXIST, currIndexNptrs_bd00.np_ptr^.nd_id);
                (*ENDIF*) 
                currIndexNptrs_bd00 := nptrs
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            WITH nptrs, np_ptr^ DO
                BEGIN
                IF  nd_level = LEAF_LEVEL_BD00
                THEN
                    bFound := true
                ELSE
                    BEGIN
                    IF  leafnodes < 1
                    THEN
                        leafnodes := 1;
                    (*ENDIF*) 
                    IF  leafpos <  0
                    THEN
                        leafpos := 0;
                    (*ENDIF*) 
                    IF  leafnodes < leafpos
                    THEN
                        leafpos := leafnodes;
                    (*ENDIF*) 
                    amount        := nd_record_cnt;
                    recIndex      := ((amount -1) * leafpos) DIV leafnodes;
                    recPos        := amount DIV 2;
                    leafpos       := leafpos - (recIndex*leafnodes + recPos) DIV amount;
                    leafnodes     := (leafnodes + recPos) DIV amount;
                    rightestimate := rightestimate * amount + (nd_record_cnt - 1) - recIndex;
                    left_estimate := left_estimate * amount + recIndex;
                    recPos        := nd_pointer_list [MAX_POINTERINDEX_BD00 - recIndex];
                    IF  bd50_RecordPositionValid (curr_trans^, curr_tree_id, np_ptr, recPos)
                    THEN
                        BEGIN
                        pRec    := @nd_body [recPos];
                        subRoot := gg06PnoGet (pRec^.recPno_gg00);
                        IF  (nd_level = FIRST_INDEX_LEVEL_BD00) AND (ftsPerm_egg00 IN fileType_gg00)
                        THEN
                            BEGIN
                            currLeftBound_bd00  := bd52SubtreePno (np_ptr, FIRST_REC_INDEX_BD00);
                            currRightBound_bd00 := bd52SubtreePno (np_ptr, nd_record_cnt - 1)
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDWITH*) 
        (*ENDIF*) 
    UNTIL
        bFound OR (trError_gg00 <> e_ok);
    (*ENDREPEAT*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd50IndexNodeIsSaveForDelete (
            VAR current   : tbd_current_tree;
            recIndex      : tsp00_Int4;
            maximumKeyLen : tsp00_Int4) : boolean;
 
CONST
      c_maxAlignment      = 1; (* maximum alignment space *)
      c_mergeNeighbor     = 1; (* right neighbor of recIndex could be removed in bd34merge_leafnodes *)
      c_maxSepPrefixDelta = 1; (* new sep could be one byte bigger than newKeyLen *)
 
VAR
      bIsSave     : boolean;
      maxSepLen   : tsp00_Int4;
      recPosition : tsp00_Int4;
      usedSpace   : tsp00_Int4;
      pRec        : tgg00_RecPtr;
 
BEGIN
WITH current DO
    BEGIN
    bIsSave := false;
    IF  (g01glob.bd_subtree                                          ) AND
        (FIRST_INDEX_LEVEL_BD00 < currRootNptrs_bd00.np_ptr^.nd_level) AND
        (ftsPerm_egg00 IN curr_tree_id.fileType_gg00                 )
    THEN
        BEGIN
        WITH currIndexNptrs_bd00, np_ptr^ DO
            BEGIN
            IF  (recIndex > FIRST_REC_INDEX_BD00) AND
                (recIndex < ((nd_record_cnt - 1) - c_mergeNeighbor))
            THEN
                BEGIN
                (* check length of destination leaf separator*)
                (* *)
                recPosition := nd_pointer_list [MAX_POINTERINDEX_BD00 - recIndex];
                pRec        := @nd_body[ recPosition ];
                maxSepLen   := pRec^.recLen_gg00;
                (* *)
                (* check length of successor leaf separator, because of bd34merge_leafnodes *)
                (* *)
                recPosition := nd_pointer_list [MAX_POINTERINDEX_BD00 - (recIndex + c_mergeNeighbor)];
                pRec        := @nd_body[ recPosition ];
                IF  pRec^.recLen_gg00 > maxSepLen
                THEN
                    maxSepLen := pRec^.recLen_gg00;
                (*ENDIF*) 
                maxSepLen := maxSepLen + POINTERSIZE_BD00 + c_maxAlignment;
                (* *)
                usedSpace := nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00);
                IF  (nd_id = curr_tree_id.fileRoot_gg00) OR ((usedSpace - maxSepLen) > HALF_COVERING_BD00)
                THEN
                    BEGIN  (* is save against underflow! *)
                    maxSepLen := sizeof (tgg00_HeaderRec) + sizeof (tbd00_SepLeafCount) +
                          maximumKeyLen + c_maxAlignment + c_maxSepPrefixDelta;
                    (* *)
                    (* save against overflow caused by left or right distribution (b54repl) *)
                    (* *)
                    bIsSave   := (nd_bottom + maxSepLen - pRec^.recLen_gg00) <
                          (MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00));
                    IF  g01glob.bd_lock_check AND bIsSave
                    THEN
                        bd50_WriteVtraceForDeleteSaveness (curr_trans^, nd_id, recIndex,
                              maximumKeyLen, maxSepLen, usedSpace);
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END
        (*ENDWITH*) 
        END;
    (*ENDIF*) 
    bd50IndexNodeIsSaveForDelete := bIsSave;
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd50IndexNodeIsSaveForInsert (
            VAR current   : tbd_current_tree;
            recIndex      : tsp00_Int4;
            newKeyLen     : tsp00_Int4;
            maximumKeyLen : tsp00_Int4) : boolean;
 
CONST
      c_maxAddOpsToExecute = 2; (* maximum 2 x b54add_index *)
      c_maxAlignment       = 1; (* maximum alignment space *)
      c_maxSepPrefixDelta  = 1; (* new sep could be one byte bigger than newKeyLen *)
 
VAR
      bIsSave   : boolean;
      maxSepLen : tsp00_Int4;
 
BEGIN
WITH current DO
    BEGIN
    bIsSave := false;
    IF  (g01glob.bd_subtree                                          ) AND
        (FIRST_INDEX_LEVEL_BD00 < currRootNptrs_bd00.np_ptr^.nd_level) AND
        (ftsPerm_egg00 IN curr_tree_id.fileType_gg00                 )
    THEN
        BEGIN
        WITH currIndexNptrs_bd00, np_ptr^ DO
            BEGIN
            IF  (recIndex > FIRST_REC_INDEX_BD00) AND (recIndex < (nd_record_cnt - 1))
            THEN
                BEGIN
                maxSepLen := gg06Max (newKeyLen, maximumKeyLen) +
                      sizeof (tgg00_HeaderRec) + sizeof (tbd00_SepLeafCount) +
                      POINTERSIZE_BD00 + c_maxAlignment + c_maxSepPrefixDelta;
                bIsSave   := (nd_bottom + (maxSepLen * c_maxAddOpsToExecute)) <
                      (MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00));
                IF  g01glob.bd_lock_check AND bIsSave
                THEN
                    bd50_WriteVtraceForInsertSaveness (curr_trans^, nd_id, recIndex,
                          maxSepLen, nd_bottom, nd_record_cnt);
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDWITH*) 
        END;
    (*ENDIF*) 
    bd50IndexNodeIsSaveForInsert := bIsSave;
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd50IndexNodeIsSaveForReplace (
            VAR current   : tbd_current_tree;
            bIsGrowing    : boolean;
            recIndex      : tsp00_Int4;
            newKeyLen     : tsp00_Int4;
            maximumKeyLen : tsp00_Int4) : boolean;
 
VAR
      bIsSave : boolean;
 
BEGIN
IF  bIsGrowing
THEN
    bIsSave := bd50IndexNodeIsSaveForInsert (current, recIndex, newKeyLen, maximumKeyLen)
ELSE
    bIsSave := bd50IndexNodeIsSaveForDelete (current, recIndex, maximumKeyLen);
(*ENDIF*) 
bd50IndexNodeIsSaveForReplace := bIsSave;
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50MoveFileContent (
            VAR sourceCurrent : tbd_current_tree;
            VAR destCurrent   : tbd_current_tree;
            VAR subRoot       : tsp00_PageNo);
 
VAR
      bWasLastRecord    : boolean;
      recIndex          : tsp00_Int4;
      nptrs              : tbd_node_ptrs;
      oldDestPageHeader : tbd_node_header;
 
BEGIN
nptrs.np_ptr   := NIL;
nptrs.np_cbptr := NIL;
WITH sourceCurrent.curr_trans^ DO
    BEGIN
    IF  subRoot <> sourceCurrent.curr_tree_id.fileRoot_gg00
    THEN
        BEGIN (* read non root page of source file *)
        bd13GetNode (sourceCurrent, subRoot, plmLock_ebd00,
              nr_for_update, nptrs)
        END
    ELSE
        BEGIN
        (* copy content of source root page into destination root page *)
        WITH destCurrent.currRootNptrs_bd00 DO
            BEGIN
            oldDestPageHeader  := np_ptr^.nd_full_header;
            np_ptr^            := sourceCurrent.currRootNptrs_bd00.np_ptr^;
            np_ptr^.nd_root    := destCurrent.curr_tree_id.fileRoot_gg00;
            np_ptr^.nd_id      := destCurrent.curr_tree_id.fileRoot_gg00;
            np_ptr^.nd_trailer := np_ptr^.nd_header
            END;
        (*ENDWITH*) 
        destCurrent.currRootUpdated_bd00 := true;
        WITH sourceCurrent.currRootNptrs_bd00 DO
            BEGIN
            np_ptr^.nd_full_header := oldDestPageHeader;
            np_ptr^.nd_root        := sourceCurrent.curr_tree_id.fileRoot_gg00;
            np_ptr^.nd_id          := sourceCurrent.curr_tree_id.fileRoot_gg00;
            np_ptr^.nd_trailer     := np_ptr^.nd_header;
            END;
        (*ENDWITH*) 
        sourceCurrent.currRootUpdated_bd00 := true;
        nptrs := destCurrent.currRootNptrs_bd00;
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  nptrs.np_ptr^.nd_level <> LEAF_LEVEL_BD00
        THEN
            BEGIN
            recIndex       := FIRST_REC_INDEX_BD00;
            bWasLastRecord := false;
            REPEAT
                subRoot := bd52SubtreePno (nptrs.np_ptr, recIndex);
                bd50MoveFileContent (sourceCurrent, destCurrent, subRoot);
                IF  trError_gg00 = e_ok
                THEN
                    b51next_branch (nptrs.np_ptr, recIndex, bWasLastRecord)
                (*ENDIF*) 
            UNTIL
                bWasLastRecord OR (trError_gg00 <> e_ok);
            (*ENDREPEAT*) 
            END;
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (nptrs.np_ptr^.nd_id <> destCurrent.curr_tree_id.fileRoot_gg00)
        THEN
            BEGIN
            nptrs.np_ptr^.nd_root := destCurrent.curr_tree_id.fileRoot_gg00;
            b13w_release_node (nptrs, sourceCurrent)
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptrs.np_ptr <> NIL)
    THEN
        b13r_release_node (nptrs, sourceCurrent, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50ReorgTreeIndex (
            VAR truncRecKey : tgg00_Lkey;
            longColCnt      : integer;
            VAR current     : tbd_current_tree);
 
VAR
      bReCreateTreeIndex : boolean;
      recIndexForLeaf    : tsp00_Int4;
      leaftMostLeaf      : tsp00_PageNo;
      nptrs              : tbd_node_ptrs;
      neighbs            : tbd_neighbors;
      zeroRecKey         : tgg00_Lkey;
 
BEGIN
bReCreateTreeIndex     := true;
nptrs.np_ptr           := NIL;
nptrs.np_cbptr         := NIL;
zeroRecKey.keyLen_gg00 := 0;
WITH current, curr_trans^ DO
    BEGIN
    bd50FindLeaf (zeroRecKey.keyVal_gg00, zeroRecKey.keyLen_gg00,
          NOT LOCK_LEAF_EXCL_BD00, nptrs, neighbs, recIndexForLeaf, current);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        leaftMostLeaf := nptrs.np_ptr^.nd_id;
        b13r_release_node (nptrs, current, lru_normal);
        IF  currRootNptrs_bd00.np_ptr^.nd_level > LEAF_LEVEL_BD00
            (* PTS ? UH 2003-10-17 *)
        THEN
            BEGIN
            bd30ReleaseSubTree (current);
            bd50_DropTreeIndex (current, curr_tree_id.fileRoot_gg00);
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            bd50_TruncLeafPages (current, leaftMostLeaf, longColCnt,
                  truncRecKey, bReCreateTreeIndex);
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND bReCreateTreeIndex
        THEN
            bd50_CreateTreeIndex (current, leaftMostLeaf)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  nptrs.np_ptr <> NIL
    THEN
        b13r_release_node (nptrs, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50VerifySubTree (
            subRoot               : tsp00_PageNo;
            right                 : tsp00_PageNo;
            bUpdateConverter      : boolean;
            bWithExtendedCheck    : boolean;
            VAR reEntranceKey     : tgg00_Lkey;
            VAR checkKey          : tgg00_Lkey;
            VAR boundNeighborLeaf : tsp00_PageNo;
            VAR bDumpParent       : boolean;
            VAR current           : tbd_current_tree;
            VAR scanCount         : tsp00_Int4;
            VAR numPages          : tsp00_Int4);
 
VAR
      bWasLastRecord : boolean;
      recIndex       : tsp00_Int4;
      rightRecIndex  : tsp00_Int4;
      rightSubRoot   : tsp00_PageNo;
      nptr           : tbd_node_ptrs;
      pRec           : tgg00_RecPtr;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    trError_gg00  := e_ok;
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    IF  trRteCommPtr_gg00^.to_cancel
    THEN
        trError_gg00 := e_cancelled
    ELSE
        BEGIN
        IF  subRoot = curr_tree_id.fileRoot_gg00
        THEN
            nptr := currRootNptrs_bd00
        ELSE
            bd13GetNode (current, subRoot, plmLock_ebd00, nr_for_read, nptr);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok (* PTS 112096 TS 2003-11-19 *)
    THEN
        bd50_CheckEntriesOnPage( curr_trans^, curr_tree_id, nptr,
              checkKey, bDumpParent, bWithExtendedCheck );
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        WITH nptr, np_ptr^ DO
            BEGIN
            IF  nd_level = LEAF_LEVEL_BD00
            THEN
                BEGIN
                IF  ((right <> nd_right) AND (subRoot <> currRightBound_bd00))
                    OR
                    ((boundNeighborLeaf <> NIL_PAGE_NO_GG00) AND
                    (subRoot = currLeftBound_bd00) AND (boundNeighborLeaf <> subRoot))
                THEN
                    BEGIN
                    trError_gg00 := e_invalid_leaves_structure;
                    bDumpParent  := true;
                    g01opmsg (sp3p_knldiag, sp3m_error, csp3_b50_1_invalid_structure,
                          csp3_n_btree, 'Invalid leaves structure', nd_id);
                    b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1)
                    END
                ELSE
                    BEGIN
                    IF  subRoot = currRightBound_bd00
                    THEN
                        boundNeighborLeaf := nd_right
                    ELSE
                        boundNeighborLeaf := NIL_PAGE_NO_GG00;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        IF  scanCount < MAX_NODE_SCAN_BD00
                        THEN
                            BEGIN
                            scanCount                 := scanCount + 1;
                            reEntranceKey.keyLen_gg00 := 0
                            END
                        ELSE
                            BEGIN
                            IF  (nd_right = NIL_PAGE_NO_GG00) OR
                                (NOT bd20IsPageRequested (currRootNptrs_bd00.np_cbptr))
                            THEN
                                scanCount := 0
                            ELSE
                                BEGIN
                                pRec := @nd_body [ nd_pointer_list[ MAX_POINTERINDEX_BD00 ]];
                                g01key_assign (pRec^.recKey_gg00, reEntranceKey, trError_gg00);
                                IF  trError_gg00 = e_ok
                                THEN
                                    trError_gg00 := e_bd_leaf_unlocked
                                ELSE
                                    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*) 
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            ELSE (*  nd_level > leaflevel *)
                IF  (right <> nd_right) AND (reEntranceKey.keyLen_gg00 = 0)
                THEN
                    BEGIN
                    trError_gg00 := e_invalid_index_structure;
                    bDumpParent  := true;
                    g01opmsg (sp3p_knldiag, sp3m_error, bd50c4InvalidStructure_csp03,
                          csp3_n_btree, 'Invalid index structure ', nd_id);
                    b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1);
                    END
                ELSE
                    BEGIN
                    IF  nd_level = FIRST_INDEX_LEVEL_BD00
                    THEN
                        BEGIN
                        currLeftBound_bd00  := bd52SubtreePno (np_ptr, FIRST_REC_INDEX_BD00);
                        currRightBound_bd00 := bd52SubtreePno (np_ptr, nd_record_cnt - 1)
                        END;
                    (*ENDIF*) 
                    recIndex       := FIRST_REC_INDEX_BD00;
                    bWasLastRecord := false;
                    REPEAT
                        IF  reEntranceKey.keyLen_gg00 <> 0
                        THEN
                            bd51SearchBranch (current, @reEntranceKey.keyVal_gg00,
                                  reEntranceKey.keyLen_gg00, np_ptr, recIndex);
                        (*ENDIF*) 
                        subRoot       := bd52SubtreePno (np_ptr, recIndex);
                        rightRecIndex := recIndex;
                        bd50_GetRightSubTree (current, np_ptr, rightRecIndex, right, rightSubRoot);
                        IF  (trError_gg00 = e_ok) AND bWithExtendedCheck
                        THEN
                            BEGIN (* recPos and recLength were checked before *)
                            pRec   := @nd_body [nd_pointer_list [MAX_POINTERINDEX_BD00 - recIndex]];
                            g10mv ('VBD50 ',   5,    
                                  pRec^.recKeyLen_gg00, sizeof (checkKey.keyVal_gg00),
                                  @pRec^.recKey_gg00.keyVal_gg00, 1, @checkKey.keyVal_gg00, 1,
                                  pRec^.recKeyLen_gg00, trError_gg00);
                            checkKey.keyLen_gg00 := pRec^.recKeyLen_gg00;
                            END;
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            bd50VerifySubTree (subRoot, rightSubRoot, bUpdateConverter, bWithExtendedCheck,
                                  reEntranceKey, checkKey, boundNeighborLeaf, bDumpParent, current,
                                  scanCount, numPages);
                        (*ENDIF*) 
                        IF  bDumpParent
                        THEN
                            BEGIN
                            bDumpParent := false;
                            g01opmsg (sp3p_knldiag, sp3m_error, csp3_b50_3_invalid_structure,
                                  csp3_n_btree, 'Parent data pageNo      ', nd_id);
                            b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1)
                            END;
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            b51next_branch (np_ptr, recIndex, bWasLastRecord);
                            IF  (NOT bWasLastRecord) AND bWithExtendedCheck
                            THEN
                                bd50_CheckMaxChildKeyAgainstNextSeparator(
                                      curr_trans^, nptr, checkKey, recIndex );
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                    UNTIL
                        bWasLastRecord OR (trError_gg00 <> e_ok)
                    (*ENDREPEAT*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            IF  (e_ok = trError_gg00) AND bWithExtendedCheck
            THEN
                BEGIN (* store max key to check him against next separator key *)
                IF  nd_record_cnt = 0
                THEN
                    checkKey.keyLen_gg00 := 0
                ELSE
                    BEGIN
                    recIndex := nd_record_cnt - 1;
                    pRec     := @nd_body [nd_pointer_list [MAX_POINTERINDEX_BD00 - recIndex]];
                    g10mv ('VBD50 ',   6,    
                          pRec^.recKeyLen_gg00, sizeof (checkKey.keyVal_gg00),
                          @pRec^.recKey_gg00.keyVal_gg00, 1, @checkKey.keyVal_gg00, 1,
                          pRec^.recKeyLen_gg00, trError_gg00);
                    checkKey.keyLen_gg00 := pRec^.recKeyLen_gg00;
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        numPages := succ (numPages);
        IF  bUpdateConverter
        THEN
            b10use_pno (curr_trans^, nptr.np_ptr^.nd_id);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50_CheckLong (
            VAR fileId          : tgg00_FileId;
            VAR t               : tgg00_TransContext;
            nptr                : tbd_nodeptr;
            longColCnt          : tsp00_Int2;
            newLongColCnt       : tsp00_Int2;
            bCheckLongExistence : boolean);
 
VAR
      pRec         : tgg00_RecPtr;
      RecPos       : tsp00_Int4;
      LongPos      : tsp00_Int4;
      AuxLongNo    : tsp00_Int4;
      RecIndex     : tsp00_Int4;
      LongId       : tgg00_FileId;
      ShcolFileId  : tgg00_FileId;
      ShcolCurrent : tbd_current_tree;
      Key          : tgg00_Lkey;
      bCheckShort  : boolean; (* check short column file *)
      bCheckLong   : boolean; (* check long long *)
 
BEGIN
LongId               := b01niltree_id;
LongId.fileType_gg00 := [ftsByteStr_egg00, ftsConcurrent_egg00];
LongId.fileTfn_gg00  := tfnColumn_egg00;
IF  (newLongColCnt < longColCnt)
THEN
    BEGIN
    ShcolFileId                           := fileId;
    ShcolFileId.fileTfn_gg00              := tfnShortScol_egg00;
    ShcolFileId.fileRoot_gg00             := NIL_PAGE_NO_GG00;
    ShcolFileId.fileVersion_gg00.ci2_gg00 := cgg_dummy_file_version
    END;
(*ENDIF*) 
WITH nptr^, t DO
    BEGIN
    RecIndex := FIRST_REC_INDEX_BD00;
    WHILE (trError_gg00 = e_ok) AND (RecIndex <= nd_record_cnt - 1) DO
        BEGIN
        RecPos  := nd_pointer_list[MAX_POINTERINDEX_BD00 - RecIndex];
        pRec    := @nd_body [RecPos];
        LongPos := RecPos + cgg_rec_key_offset + pRec^.recKeyLen_gg00;
&       ifdef trace
        t01p2int4 (bd_byte, 'loop        ', 1
              ,             'old long pos', LongPos);
&       endif
        AuxLongNo := 1;
        WHILE (trError_gg00 =  e_ok) AND (AuxLongNo  <= longColCnt) DO
            BEGIN
&           ifdef trace
            t01p2int4 (bd_byte, 'loop        ', 2
                  ,             'old long nr ', AuxLongNo);
&           endif
            IF  nd_body [LongPos] <> csp_undef_byte
            THEN
                BEGIN
                bCheckShort := bCheckLongExistence AND (newLongColCnt < longColCnt);
                bCheckLong  := false;
                IF  bCheckShort
                THEN
                    BEGIN
                    bd30GetTree (t, ShcolFileId, ShcolCurrent, m_select,
                          NOT LOCK_TREE_EXCL_BD00, NOT SYNC_EXCL_LOCK_BD00);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        ShcolFileId.fileRoot_gg00 := ShcolCurrent.curr_tree_id.fileRoot_gg00;
                        Key.keyLen_gg00           := sizeof (tgg00_Surrogate);
                        g10mv ('VBD50 ',   7,    
                              sizeof (tbd_node), sizeof (Key.keyVal_gg00),
                              @nptr^, LongPos + 1, @Key.keyVal_gg00, 1, Key.keyLen_gg00,
                              trError_gg00);
                        IF  trError_gg00 = e_move_error
                        THEN
                            trError_gg00 := e_data_page_corrupted
                        ELSE
                            bd30ExistRecord (Key, ShcolCurrent);
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  ((trError_gg00 = e_ok) AND NOT bCheckLongExistence) OR
                        (trError_gg00 = e_key_not_found)
                    THEN
                        bCheckLong := true;
                    (*ENDIF*) 
                    bd30ReleaseTree (ShcolCurrent)
                    END
                ELSE
                    BEGIN
                    bCheckLong := true
                    END;
                (*ENDIF*) 
                IF  bCheckLong
                THEN
                    BEGIN
                    trError_gg00         := e_ok;
                    LongId.fileRoot_gg00 := NIL_PAGE_NO_GG00;
                    g10mv ('VBD50 ',   8,    
                          sizeof (tbd_node), sizeof (LongId.fileName_gg00),
                          @nptr^, LongPos + 1, @LongId.fileName_gg00, 3,
                          sizeof (tgg00_Surrogate), trError_gg00);
                    IF  trError_gg00 = e_move_error
                    THEN
                        trError_gg00 := e_data_page_corrupted
                    ELSE
                        b01b_check_bytestr (t, LongId)
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  trError_gg00 = e_file_not_found
                THEN
                    BEGIN
                    (* PTS 1108994 TS 2001-01-22 *)
                    IF  bCheckLongExistence
                    THEN
                        BEGIN
                        (* Long column not found! Neither in short column *)
                        (* file nor in separate blob file.                *)
                        trError_gg00 := e_long_column_missing;
                        END
                    ELSE
                        trError_gg00 := e_ok;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  (trError_gg00 = e_data_page_corrupted) OR
                    (trError_gg00 = e_long_column_missing) OR
                    (trError_gg00 = e_no_converter_entry ) OR
                    (trError_gg00 = e_bad_datapage       ) OR
                    (trError_gg00 = e_page_in_wrong_tree )
                THEN
                    BEGIN
                    g01opmsg (sp3p_knldiag, sp3m_error, bd50c1LongColumnNotFound_csp03,
                          csp3_n_btree, 'Dump base table page    ', nd_id);
                    g01opmsg (sp3p_knldiag, sp3m_error, bd50c1LongColumnNotFound_csp03,
                          csp3_n_btree, 'Blob read error (recPos)', RecPos);
                    b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, nptr, 1)
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            LongPos   := LongPos + cgg_col_fd_size;
            AuxLongNo := succ (AuxLongNo)
            END;
        (*ENDWHILE*) 
        RecIndex := succ (RecIndex)
        END
    (*ENDWHILE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50_CountRecords (
            VAR current     : tbd_current_tree;
            VAR startKey    : tgg00_Lkey;
            VAR stopKey     : tgg00_Lkey;
            startIndexPage  : tsp00_PageNo;
            startLeafPage   : tsp00_PageNo;
            stopLeafPage    : tsp00_PageNo;
            VAR recordCount : tsp00_Int4;
            VAR pageCount   : tsp00_Int4);
 
VAR
      start_result     : tbd_searchresult;
      stop_result      : tbd_searchresult;
      start_maxindex   : tsp00_Int4;
      start_index      : tsp00_Int4;
      stop_index       : tsp00_Int4;
      leafCount        : tsp00_Int4;
      index            : tsp00_Int4;
      currLeafPage     : tsp00_PageNo;
      nextIndexPage    : tsp00_PageNo;
      nptr             : tbd_node_ptrs;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    recordCount   := 0;
    nextIndexPage := NIL_PAGE_NO_GG00;
    IF  currRootNptrs_bd00.np_ptr^.nd_level > FIRST_INDEX_LEVEL_BD00
    THEN
        BEGIN
        (* *)
        (* startLeafPage and stopLeafPage could be outdated,  *)
        (* because of possible subtree exclusive locks.       *)
        (* startIndexPage is still valid, because of the root *)
        (* share lock.                                        *)
        (* *)
        bd30GetSubTree (current, startIndexPage);
        IF  trError_gg00 = e_ok
        THEN
            WITH currIndexNptrs_bd00 DO
                BEGIN
                bd51SearchBranch (current, @startKey.keyVal_gg00,
                      startKey.keyLen_gg00, np_ptr, index);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    stopLeafPage  := NIL_PAGE_NO_GG00;
                    startLeafPage := bd52SubtreePno (np_ptr, index)
                    END
                (*ENDIF*) 
                END
            (*ENDWITH*) 
        (*ENDIF*) 
        END;
&   ifdef TRACE
    (*ENDIF*) 
    t01p2int4 (bd_index, 'start leaf: ', startLeafPage, 'stop leaf:  ', stopLeafPage);
&   endif
    IF  trError_gg00 = e_ok
    THEN
        IF  startLeafPage = curr_tree_id.fileRoot_gg00
        THEN
            nptr := currRootNptrs_bd00
        ELSE
            bd13GetNode (current, startLeafPage, plmLock_ebd00, nr_for_read, nptr);
        (*ENDIF*) 
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        start_maxindex := nptr.np_ptr^.nd_record_cnt - 1;
        currLeafPage   := nptr.np_ptr^.nd_id;
        (* *)
        b31search_entry (current, startKey.keyVal_gg00, startKey.keyLen_gg00,
              nptr.np_ptr, start_index, start_result);
        (* *)
        IF  (trError_gg00 = e_ok) AND (start_result <> nonefound)
        THEN
            BEGIN
            leafCount := 1;
            REPEAT
                IF  nptr.np_ptr^.nd_right = NIL_PAGE_NO_GG00
                THEN
                    stopLeafPage := currLeafPage
                ELSE
                    IF  stopLeafPage = NIL_PAGE_NO_GG00
                    THEN
                        BEGIN
                        b31search_entry (current, stopKey.keyVal_gg00, stopKey.keyLen_gg00,
                              nptr.np_ptr, stop_index, stop_result);
                        IF  stop_result <> lastfound
                        THEN
                            stopLeafPage := currLeafPage
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                (*ENDIF*) 
                IF  (trError_gg00 = e_ok) AND (currLeafPage <> stopLeafPage)
                THEN
                    BEGIN
                    IF  currLeafPage <> startLeafPage
                    THEN
                        recordCount := recordCount + nptr.np_ptr^.nd_record_cnt - 1;
                    (*ENDIF*) 
                    currLeafPage := nptr.np_ptr^.nd_right;
                    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_normal);
                    IF  nextIndexPage <> NIL_PAGE_NO_GG00
                    THEN
                        BEGIN
                        bd30ReleaseSubTree (current);
                        bd30GetSubTree (current, nextIndexPage);
                        nextIndexPage := NIL_PAGE_NO_GG00
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        bd13GetNode (current, currLeafPage, plmLock_ebd00, nr_for_read, nptr);
                        leafCount := succ (leafCount)
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            UNTIL
                (trError_gg00 <> e_ok                     ) OR
                (currLeafPage =  stopLeafPage             ) OR
                (leafCount    >  c_upb_pages_to_count_recs);
            (*ENDREPEAT*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  currLeafPage = stopLeafPage
                THEN
                    BEGIN
                    b31search_entry (current, stopKey.keyVal_gg00, stopKey.keyLen_gg00,
                          nptr.np_ptr, stop_index, stop_result);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        IF  startLeafPage = stopLeafPage
                        THEN
                            recordCount := stop_index - start_index + 1
                        ELSE
                            recordCount := recordCount +
                                  (start_maxindex - start_index + 1) +
                                  (stop_index +1);
                        (*ENDIF*) 
                        IF  start_result = lastfound
                        THEN
                            recordCount := recordCount - 1;
                        (*ENDIF*) 
                        IF  stop_result = nextfound
                        THEN
                            recordCount := recordCount - 1;
                        (*ENDIF*) 
                        IF  recordCount < 0
                        THEN
                            recordCount := 0;
                        (*ENDIF*) 
                        pageCount := leafCount;
&                       ifdef TRACE
                        t01p2int4 (bd_index, 'start leaf: ',startLeafPage
                              ,              'stop leaf:  ',stopLeafPage);
                        t01p2int4 (bd_index, 'curr leaf:  ',currLeafPage
                              ,              'rec count:  ',recordCount);
&                       endif
                        END
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    (* c_upb_pages_to_count_recs exceeded *)
                    (* should not happen                  *)
                    recordCount := -1;
                    IF  pageCount <= c_upb_pages_to_count_recs
                    THEN
                        pageCount := c_upb_pages_to_count_recs +1;
&                   ifdef TRACE
                    (*ENDIF*) 
                    t01p2int4 (bd_index, 'curr leaf:  ', currLeafPage
                          ,              'rec count:  ', recordCount);
&                   endif
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50_CreateTreeIndex (
            VAR current   : tbd_current_tree;
            leaftMostLeaf : tsp00_PageNo);
 
VAR
      freeLeftMostLeaf   : boolean;
      bIsNoLogSet        : boolean;
      fileVersion        : tgg91_FileVersion;
      nextLeafPage       : tsp00_PageNo;
      freePageVersion    : tsp00_Int4;
      nptr               : tbd_node_ptrs;
      lnptr              : tbd_node_ptrs;
      indexorderlist     : tbd00_OrderList;
      sepKey             : tgg00_Lkey;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    lnptr         := nptr;
    bIsNoLogSet   := hsNoLog_egg00 IN fileHandling_gg00;
    IF  NOT bIsNoLogSet
    THEN
        fileHandling_gg00 := fileHandling_gg00 + [hsNoLog_egg00];
    (*ENDIF*) 
    freeLeftMostLeaf := false;
    lnptr            := currRootNptrs_bd00;
    IF  fileRoot_gg00 = leaftMostLeaf
    THEN
        nextLeafPage := NIL_PAGE_NO_GG00
    ELSE
        BEGIN
        bd13GetNode (current, leaftMostLeaf, plmLock_ebd00, nr_for_update, nptr);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            (* copy leftmost leaf page into root *)
            fileVersion      := lnptr.np_ptr^.nd_file_version;
            freeLeftMostLeaf := true;
            freePageVersion  := nptr.np_ptr^.nd_conv_version;
            nextLeafPage     := nptr.np_ptr^.nd_right;
            g10mv ('VBD50 ',   9,    
                  sizeof (nptr.np_ptr^), sizeof (lnptr.np_ptr^),
                  @nptr.np_ptr^, 1, @lnptr.np_ptr^, 1, sizeof (tbd_node), trError_gg00);
            lnptr.np_ptr^.nd_id           := fileRoot_gg00;
            lnptr.np_ptr^.nd_file_version := fileVersion
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        IF  nextLeafPage = NIL_PAGE_NO_GG00
        THEN
            b13w_release_node (lnptr, current)
        ELSE
            REPEAT
                bd13GetNode (current, nextLeafPage, plmLock_ebd00, nr_for_read, nptr);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    indexorderlist.olstCount_bd00 := 0;
                    curr_lvl_1_pno                := NIL_PAGE_NO_GG00;
                    sepKey.keyLen_gg00            := 0;
                    nextLeafPage                  := nptr.np_ptr^.nd_right;
                    bd53NewLeafIndex (lnptr.np_ptr, nptr.np_ptr, sepKey, curr_trans);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        b54add_index (@sepKey.keyVal_gg00, sepKey.keyLen_gg00,
                              nptr.np_ptr^.nd_id, LEAF_LEVEL_BD00, indexorderlist);
                        b13r_release_node (lnptr, current, lru_normal);
                        lnptr         := nptr;
                        nptr.np_ptr   := NIL;
                        nptr.np_cbptr := NIL;
                        b54execute_indexorder (indexorderlist, current)
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
            UNTIL
                (trError_gg00 <> e_ok) OR (nextLeafPage = NIL_PAGE_NO_GG00);
            (*ENDREPEAT*) 
        (*ENDIF*) 
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND freeLeftMostLeaf
    THEN
        BEGIN
        bd13FreePageNo (leaftMostLeaf, freePageVersion, current);
        nptr.np_ptr   := NIL;
        nptr.np_cbptr := NIL
        END;
    (*ENDIF*) 
    IF  lnptr.np_ptr <> NIL
    THEN
        b13r_release_node (lnptr, current, lru_normal);
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    IF  NOT bIsNoLogSet
    THEN
        fileHandling_gg00 := fileHandling_gg00 - [hsNoLog_egg00]
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50_DropLong (
            VAR trans     : tgg00_TransContext;
            nptr          : tbd_nodeptr;
            numberOfLongs : integer);
 
VAR
      pRec        : tgg00_RecPtr;
      recPos      : tsp00_Int4;
      longPos     : tsp00_Int4;
      auxLongNo   : tsp00_Int4;
      recIndex    : tsp00_Int4;
      longFileId  : tgg00_FileId;
 
BEGIN
longFileId               := b01niltree_id;
longFileId.fileType_gg00 := [ftsByteStr_egg00, ftsConcurrent_egg00];
longFileId.fileTfn_gg00  := tfnColumn_egg00;
WITH trans, nptr^ DO
    BEGIN
    recIndex := FIRST_REC_INDEX_BD00;
    WHILE (trError_gg00 = e_ok) AND (recIndex <= nd_record_cnt - 1) DO
        BEGIN
        recPos  := nd_pointer_list[MAX_POINTERINDEX_BD00 - recIndex];
        pRec    := @nd_body [recPos];
        longPos := recPos + cgg_rec_key_offset + pRec^.recKeyLen_gg00;
&       ifdef trace
        t01p2int4 (bd_byte, 'loop        ', 1
              ,             'old long pos', longPos);
&       endif
        auxLongNo := 1;
        WHILE (trError_gg00 = e_ok) AND (auxLongNo <= numberOfLongs) DO
            BEGIN
&           ifdef trace
            t01p2int4 (bd_byte, 'loop        ', 2
                  ,             'old long nr ', auxLongNo);
&           endif
            IF  nd_body [longPos] <> csp_undef_byte
            THEN
                BEGIN
                longFileId.fileRoot_gg00 := NIL_PAGE_NO_GG00;
                g10mv ('VBD50 ',  10,    
                      sizeof (tbd_node), sizeof (longFileId.fileName_gg00),
                      @nptr^, longPos + 1, @longFileId.fileName_gg00, 3,
                      sizeof (tgg00_Surrogate), 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, nptr, 1)
                    END
                ELSE
                    b01ldestroy_long_file (trans, longFileId);
                (*ENDIF*) 
                IF  (trError_gg00 = e_bad_datapage)
                    OR
                    (trError_gg00 = e_file_not_found)
                THEN
                    trError_gg00 := e_ok
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            longPos   := longPos + cgg_col_fd_size;
            auxLongNo := auxLongNo + 1
            END;
        (*ENDWHILE*) 
        recIndex := recIndex + 1
        END
    (*ENDWHILE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50_DropTreeIndex (
            VAR current : tbd_current_tree;
            subRoot     : tsp00_PageNo);
 
VAR
      bLast    : boolean;
      auxError : tgg00_BasisError;
      recIndex : tsp00_Int4;
      nptr     : tbd_node_ptrs;
 
BEGIN
nptr.np_ptr   := NIL;
nptr.np_cbptr := NIL;
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    IF  subRoot = fileRoot_gg00
    THEN
        nptr := currRootNptrs_bd00
    ELSE
        bd13GetNode (current, subRoot, plmLock_ebd00, nr_for_update, nptr);
    (*ENDIF*) 
    IF  trError_gg00 <> e_ok
    THEN
        BEGIN
        IF  ((trError_gg00 = e_bad_datapage      ) OR
            ( trError_gg00 = e_page_in_wrong_tree) OR
            ( trError_gg00 = e_invalid_root      ) OR
            ( trError_gg00 = e_illegal_page_no)  )
        THEN
            trError_gg00 := e_ok
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  nptr.np_ptr^.nd_level > LEAF_LEVEL_BD00
        THEN
            BEGIN
            IF  nptr.np_ptr^.nd_level > FIRST_INDEX_LEVEL_BD00
            THEN
                BEGIN
                recIndex := FIRST_REC_INDEX_BD00;
                bLast    := false;
                auxError := e_ok;
                REPEAT
                    subRoot := bd52SubtreePno (nptr.np_ptr, recIndex);
                    bd50_DropTreeIndex (current, subRoot);
                    IF  trError_gg00 = e_bad_datapage
                    THEN
                        BEGIN
                        auxError     := trError_gg00;
                        trError_gg00 := e_ok
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        b51next_branch (nptr.np_ptr, recIndex, bLast)
                    (*ENDIF*) 
                UNTIL
                    bLast OR (trError_gg00 <> e_ok);
                (*ENDREPEAT*) 
                IF  trError_gg00 = e_ok
                THEN
                    trError_gg00 := auxError
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  (trError_gg00 = e_ok) OR (trError_gg00 = e_bad_datapage)
            THEN
                BEGIN
                auxError     := trError_gg00;
                trError_gg00 := e_ok;
                IF  nptr.np_ptr^.nd_id <> fileRoot_gg00
                THEN
                    b13free_node (nptr, current)
                ELSE
                    WITH nptr.np_ptr^ DO
                        BEGIN
                        nd_sorted     := false;
                        nd_bottom     := BODY_BEG_BD00;
                        nd_record_cnt := 0;
                        nd_level      := LEAF_LEVEL_BD00;
                        nd_right      := NIL_PAGE_NO_GG00;
                        b13w_release_node (nptr, current)
                        END;
                    (*ENDWITH*) 
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    trError_gg00 := auxError
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        ELSE
            IF  nptr.np_ptr <> NIL
            THEN
                b13r_release_node (nptr, current, lru_normal)
            (*ENDIF*) 
        (*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
      bd50_GetLeftSubTree (
            VAR current     : tbd_current_tree;
            nptr            : tbd_nodeptr;
            recIndex        : tsp00_Int4;
            leftNeighbor    : tsp00_PageNo;
            VAR leftSubRoot : tsp00_PageNo);
 
VAR
      nnptr : tbd_node_ptrs;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    trError_gg00   := e_ok;
    nnptr.np_ptr   := NIL;
    nnptr.np_cbptr := NIL;
    IF  recIndex <> FIRST_REC_INDEX_BD00
    THEN
        BEGIN
        recIndex    := recIndex - 1;
        leftSubRoot := bd52SubtreePno (nptr, recIndex)
        END
    ELSE
        BEGIN
        IF  (leftNeighbor = NIL_PAGE_NO_GG00)
            OR
            (
            (nptr^.nd_level = FIRST_INDEX_LEVEL_BD00                    ) AND
            (ftsConcurrent_egg00 IN curr_tree_id.fileType_gg00          ) AND
            (NOT bd20IsPageExclusiveLocked (currRootNptrs_bd00.np_cbptr))
            )
        THEN
            leftSubRoot := NIL_PAGE_NO_GG00
        ELSE
            BEGIN
            bd13GetNode (current, leftNeighbor, plmLock_ebd00, nr_for_read, nnptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  nnptr.np_ptr^.nd_level = FIRST_INDEX_LEVEL_BD00
                THEN
                    current.curr_lvl_1_pno := NIL_PAGE_NO_GG00;
                (*ENDIF*) 
                recIndex    := nnptr.np_ptr^.nd_record_cnt - 1;
                leftSubRoot := bd52SubtreePno (nnptr.np_ptr, recIndex)
                END;
            (*ENDIF*) 
            IF  nnptr.np_ptr <> NIL
            THEN
                b13r_release_node (nnptr, current, lru_normal)
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50_GetRightSubTree (
            VAR current      : tbd_current_tree;
            nptr             : tbd_nodeptr;
            VAR recIndex     : tsp00_Int4;
            rightNeighbor    : tsp00_PageNo;
            VAR rightSubRoot : tsp00_PageNo);
 
VAR
      bLast  : boolean;
      nnptr  : tbd_node_ptrs;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    trError_gg00   := e_ok;
    nnptr.np_ptr   := NIL;
    nnptr.np_cbptr := NIL;
    b51next_branch (nptr, recIndex, bLast);
    IF  NOT bLast
    THEN
        rightSubRoot := bd52SubtreePno (nptr, recIndex)
    ELSE
        IF  (rightNeighbor = NIL_PAGE_NO_GG00)
            OR
            (
            (nptr^.nd_level = FIRST_INDEX_LEVEL_BD00                    ) AND
            (ftsConcurrent_egg00 IN curr_tree_id.fileType_gg00          ) AND
            (NOT bd20IsPageExclusiveLocked (currRootNptrs_bd00.np_cbptr))
            )
        THEN
            rightSubRoot := NIL_PAGE_NO_GG00
        ELSE
            BEGIN
            bd13GetNode (current, rightNeighbor, plmLock_ebd00, nr_for_read, nnptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                recIndex     := FIRST_REC_INDEX_BD00;
                rightSubRoot := bd52SubtreePno (nnptr.np_ptr, recIndex)
                END;
            (*ENDIF*) 
            IF  nnptr.np_ptr <> NIL
            THEN
                b13r_release_node (nnptr, current, lru_normal)
            (*ENDIF*) 
            END
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd50_RecordPositionValid (
            VAR trans   : tgg00_TransContext;
            VAR fileId  : tgg00_FileId;
            nptr        : tbd_nodeptr;
            recPos      : tsp00_Int4) : boolean;
 
BEGIN
IF  (recPos < BODY_BEG_BD00) OR (recPos > nptr^.nd_bottom)
THEN
    BEGIN
    trans.trError_gg00 := e_data_page_corrupted;
    b06dump_bad_page (trans.trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
          nptr^.nd_id, nptr, 1);
    g01opmsg (sp3p_knldiag, sp3m_error, bd50c5IllegalEntryPos_csp03,
          csp3_n_btree, 'Illegal entry pos       ', recPos);
    b06write_filename_and_root (fileId)
    END;
(*ENDIF*) 
bd50_RecordPositionValid := (trans.trError_gg00 = e_ok);
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50_TruncLeafPages (
            VAR current            : tbd_current_tree;
            leaftMostLeaf          : tsp00_PageNo;
            longColCnt             : integer;
            VAR truncRecKey        : tgg00_Lkey;
            VAR bReCreateTreeIndex : boolean);
 
VAR
      compResult   : tsp00_LcompResult;
      pRec         : tgg00_RecPtr;
      recPos       : tsp00_Int4;
      nptr         : tbd_node_ptrs;
      nextLeafPage : tsp00_PageNo;
 
BEGIN
bReCreateTreeIndex := true;
nextLeafPage       := leaftMostLeaf;
nptr.np_ptr        := NIL;
nptr.np_cbptr      := NIL;
WITH current, curr_trans^ DO
    BEGIN
    IF  truncRecKey.keyLen_gg00 = 0
    THEN
        bReCreateTreeIndex := false
    ELSE
        REPEAT
            IF  nextLeafPage = curr_tree_id.fileRoot_gg00
            THEN
                nptr := currRootNptrs_bd00
            ELSE
                bd13GetNode (current, nextLeafPage, plmLock_ebd00, nr_for_update, nptr);
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  nptr.np_ptr^.nd_bottom > BODY_BEG_BD00
                THEN
                    BEGIN
                    recPos  := nptr.np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 -
                          (nptr.np_ptr^.nd_record_cnt - 1)];
                    pRec := @nptr.np_ptr^.nd_body [recPos];
                    s30cmp (truncRecKey.keyVal_gg00, 1, truncRecKey.keyLen_gg00,
                          pRec^.recKey_gg00.keyVal_gg00,
                          1, pRec^.recKeyLen_gg00, compResult);
                    IF  compResult = l_greater
                    THEN
                        BEGIN
                        nextLeafPage := nptr.np_ptr^.nd_right;
                        b13r_release_node (nptr, current, lru_normal)
                        END
                    ELSE
                        BEGIN
                        IF  compResult = l_equal
                        THEN
                            BEGIN
                            nextLeafPage          := nptr.np_ptr^.nd_right;
                            nptr.np_ptr^.nd_right := NIL_PAGE_NO_GG00;
                            b13w_release_node (nptr, current)
                            END
                        ELSE
                            BEGIN
                            IF  nextLeafPage = leaftMostLeaf
                            THEN
                                bReCreateTreeIndex := false
                            ELSE
                                IF  truncRecKey.keyVal_gg00 [1] = csp_undef_byte
                                THEN
                                    trError_gg00 := e_invalid;
                                (*ENDIF*) 
                            (*ENDIF*) 
                            b13r_release_node (nptr, current, lru_normal)
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    IF  nextLeafPage = leaftMostLeaf
                    THEN
                        bReCreateTreeIndex := false
                    ELSE
                        trError_gg00 := e_invalid_leaves_structure;
                    (*ENDIF*) 
                    compResult := l_less;
                    b13r_release_node (nptr, current, lru_normal);
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
        UNTIL
            (trError_gg00 <> e_ok            ) OR
            (compResult   <> l_greater       ) OR
            (nextLeafPage =  NIL_PAGE_NO_GG00);
        (*ENDREPEAT*) 
    (*ENDIF*) 
    IF  nextLeafPage = curr_tree_id.fileRoot_gg00 (* root_is_leaf *)
    THEN
        BEGIN
        nextLeafPage := NIL_PAGE_NO_GG00;
        IF  truncRecKey.keyLen_gg00 = 0
        THEN
            BEGIN
            bd13GetNode (current, curr_tree_id.fileRoot_gg00, plmLock_ebd00,
                  nr_for_update, nptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  longColCnt > 0
                THEN
                    BEGIN
                    bd50_DropLong (curr_trans^, nptr.np_ptr, longColCnt);
                    IF  (trError_gg00 = e_bad_datapage      ) OR
                        (trError_gg00 = e_page_in_wrong_tree) OR
                        (trError_gg00 = e_invalid_root      ) OR
                        (trError_gg00 = e_illegal_page_no   )
                    THEN
                        trError_gg00 := e_ok
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                WITH nptr.np_ptr^ DO
                    BEGIN
                    nd_sorted     := false;
                    nd_bottom     := BODY_BEG_BD00;
                    nd_record_cnt := 0;
                    nd_level      := LEAF_LEVEL_BD00;
                    nd_right      := NIL_PAGE_NO_GG00;
                    b13w_release_node (nptr, current)
                    END
                (*ENDWITH*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (* *)
    (* delete all subsequent leaf pages *)
    (* *)
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND (nextLeafPage <> NIL_PAGE_NO_GG00)
    THEN
        BEGIN
        REPEAT
            bd13GetNode (current, nextLeafPage, plmLock_ebd00, nr_for_update, nptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                nextLeafPage := nptr.np_ptr^.nd_right;
                IF  longColCnt > 0
                THEN
                    BEGIN
                    bd50_DropLong (curr_trans^, nptr.np_ptr, longColCnt);
                    IF  (trError_gg00 = e_bad_datapage      ) OR
                        (trError_gg00 = e_page_in_wrong_tree) OR
                        (trError_gg00 = e_invalid_root      ) OR
                        (trError_gg00 = e_illegal_page_no   )
                    THEN
                        trError_gg00 := e_ok
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    b13free_node (nptr, current);
                (*ENDIF*) 
                END
            (*ENDIF*) 
        UNTIL
            (trError_gg00 <> e_ok) OR (nextLeafPage = NIL_PAGE_NO_GG00);
        (*ENDREPEAT*) 
        IF  (trError_gg00 = e_bad_datapage      ) OR
            (trError_gg00 = e_page_in_wrong_tree) OR
            (trError_gg00 = e_invalid_root      ) OR
            (trError_gg00 = e_illegal_page_no   )
        THEN
            trError_gg00 := e_ok
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 <> e_ok
    THEN
        IF  nptr.np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal)
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50_WriteVtraceForDeleteSaveness (
            VAR Trans     : tgg00_TransContext;
            pageNo        : tsp00_PageNo;
            recIndex      : tsp00_Int4;
            maximumKeyLen : tsp00_Int4;
            maxSepLen     : tsp00_Int4;
            usedSpace     : tsp00_Int4);
 
VAR
      len        : tsp00_Int4;
      traceLine  : tsp00_Line;
 
BEGIN
len := 0;
g17sname_to_line ('*** Save Del', len, traceLine);
len             := len + 1;
traceLine [len] := ' ';
(* *)
g17sname_to_line ('Index Pno:  ', len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
g17trimint4_to_line (pageNo, len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
(* *)
g17sname_to_line ('Rec Index:  ', len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
g17trimint4_to_line (recIndex, len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
(* *)
(* b120InsertTrace (Trans, gg, gg_opmsg, len, @traceLine); *)
(* *)
(*len := 0;*)
g17sname_to_line ('Max Key:    ', len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
g17trimint4_to_line (maximumKeyLen, len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
(* *)
g17sname_to_line ('Max Sep:    ', len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
g17trimint4_to_line (maxSepLen, len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
(* *)
g17sname_to_line ('Used Space: ', len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
g17trimint4_to_line (usedSpace, len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
(* *)
b120InsertTrace (Trans, gg, gg_opmsg, len, @traceLine);
(* *)
Trans.trError_gg00 := e_ok;
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50_WriteVtraceForInsertSaveness (
            VAR Trans     : tgg00_TransContext;
            pageNo        : tsp00_PageNo;
            recIndex      : tsp00_Int4;
            maxSepLen     : tsp00_Int4;
            bottom        : tsp00_Int4;
            recCount      : tsp00_Int4);
 
VAR
      len        : tsp00_Int4;
      traceLine  : tsp00_Line;
 
BEGIN
(* *)
len := 0;
g17sname_to_line ('*** Save Ins', len, traceLine);
len             := len + 1;
traceLine [len] := ' ';
(* *)
g17sname_to_line ('Index Pno:  ', len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
g17trimint4_to_line (pageNo, len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
(* *)
g17sname_to_line ('Rec Index:  ', len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
g17trimint4_to_line (recIndex, len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
(* *)
(* b120InsertTrace (Trans, gg, gg_opmsg, len, @traceLine); *)
(* *)
(* len := 0; *)
g17sname_to_line ('Max Sep:    ', len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
g17trimint4_to_line (maxSepLen, len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
(* *)
g17sname_to_line ('Bottom:     ', len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
g17trimint4_to_line (bottom, len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
(* *)
g17sname_to_line ('Rec Count:  ', len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
g17trimint4_to_line (recCount, len, traceLine);
len            := len + 1;
traceLine[len] := ' ';
(* *)
b120InsertTrace (Trans, gg, gg_opmsg, len, @traceLine);
(* *)
Trans.trError_gg00 := e_ok;
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50_CheckEntriesOnPage(
            VAR trans          : tgg00_TransContext;
            VAR fileId         : tgg00_FileId;
            VAR pNodes         : tbd_node_ptrs;
            VAR checkKey       : tgg00_Lkey;
            VAR bDumpParent    : boolean;
            bWithExtendedCheck : boolean);
 
VAR
      compResult : tsp00_LcompResult;
      recPos     : tsp00_Int4;
      pRec       : tgg00_RecPtr;
 
BEGIN
bd13CheckNode (trans.trTaskId_gg00, trans.trError_gg00, pNodes, fileId, bWithExtendedCheck);
IF  (trans.trError_gg00 = e_ok) AND bWithExtendedCheck AND (checkKey.keyLen_gg00 > 0)
THEN
    WITH pNodes, np_ptr^ DO
        BEGIN (* recPos and recLength were checked before *)
        recPos := nd_pointer_list [MAX_POINTERINDEX_BD00 - FIRST_REC_INDEX_BD00];
        pRec   := @nd_body [recPos];
        (* *)
        s30cmp (checkKey.keyVal_gg00, 1,
              checkKey.keyLen_gg00, pRec^.recKey_gg00.keyVal_gg00, 1,
              pRec^.recKey_gg00.keyLen_gg00, compResult);
        IF  compResult = l_greater
        THEN
            WITH pNodes, np_ptr^ DO
                BEGIN
                trans.trError_gg00 := e_illegal_key; (* invalid key order *)
                g01opmsg (sp3p_knldiag, sp3m_error, bd50c4IllegalEntryPos_csp03,
                      csp3_n_btree, 'Wrong key order sep/page', recPos);
                g01opmsg (sp3p_knldiag, sp3m_error, bd50c4IllegalEntryPos_csp03,
                      csp3_n_btree, 'Corrupted data page     ', nd_id);
                (* *)
                b06dump_bad_page (trans.trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1);
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
(*ENDIF*) 
bDumpParent := (trans.trError_gg00 <> e_ok)
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50_CheckMaxChildKeyAgainstNextSeparator(
            VAR trans       : tgg00_TransContext;
            VAR pNodes      : tbd_node_ptrs;
            VAR checkKey    : tgg00_Lkey;
            recIndex        : tsp00_Int4);
 
VAR
      compResult : tsp00_LcompResult;
      recPos     : tsp00_Int4;
      pRec       : tgg00_RecPtr;
 
BEGIN
IF  checkKey.keyLen_gg00 > 0
THEN  (* check if highest key of last child is smaller than current sep key *)
    WITH pNodes, np_ptr^ DO
        BEGIN
        recPos := nd_pointer_list [MAX_POINTERINDEX_BD00 - recIndex];
        pRec   := @nd_body [recPos];
        s30cmp (checkKey.keyVal_gg00, 1,
              checkKey.keyLen_gg00, pRec^.recKey_gg00.keyVal_gg00, 1,
              pRec^.recKey_gg00.keyLen_gg00, compResult);
        IF  compResult <> l_less
        THEN
            BEGIN
            trans.trError_gg00 := e_illegal_key; (* invalid key order *)
            g01opmsg (sp3p_knldiag, sp3m_error, bd50c4IllegalEntryPos_csp03,
                  csp3_n_btree, 'Wrong key order page/sep', recPos);
            g01opmsg (sp3p_knldiag, sp3m_error, bd50c4IllegalEntryPos_csp03,
                  csp3_n_btree, 'Corrupted data page     ', nd_id);
            (* *)
            b06dump_bad_page (trans.trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1);
            END
        (*ENDIF*) 
        END
    (*ENDWITH*) 
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
