.ad 8
.bm 8
.fm 4
.bt $Copyright by SAP AG, 2003$$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
 
 
    ========== licence begin  GPL
    Copyright (C) 2000 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
.nf
.sp
Module  : indexhandling
=========
.sp
Purpose : operations on a B* tree index
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        PROCEDURE
              b50bfind_branchnode (
                    VAR sepkey  : tsp00_Key;
                    KeyLen      : tsp00_Int4;
                    lno         : tsp00_Int2;
                    node_req    : tbd_node_request;
                    VAR nptr    : tbd_node_ptrs;
                    VAR neighbs : tbd_neighbors;
                    VAR found   : boolean;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b50calculate_pagecount (
                    VAR current           : tbd_current_tree;
                    VAR is_tree_requested : boolean;
                    VAR start_sep         : tgg00_Lkey;
                    VAR stop_sep          : tgg00_Lkey;
                    VAR page_count        : tsp00_Int4);
 
        PROCEDURE
              b50change_treeroot (
                    subroot     : tsp00_PageNo;
                    new_root    : tsp00_PageNo;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b50check_subtree (
                    root                 : tsp00_PageNo;
                    right                : tsp00_PageNo;
                    long_col_cnt         : tsp00_Int2;
                    new_long_col_cnt     : tsp00_Int2;
                    VAR dump_parent      : boolean;
                    VAR bad_long         : boolean;
                    VAR current          : tbd_current_tree;
                    check_long_existence : boolean);
 
        PROCEDURE
              b50cross_subtree_boundary (
                    VAR current : tbd_current_tree;
                    source_leaf : tsp00_PageNo;
                    dest_leaf   : tsp00_PageNo);
 
        PROCEDURE
              b50eval_pagecount (
                    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);
 
        PROCEDURE
              b50find_leaf (
                    VAR sepkey         : tsp00_Key (* ptocSynonym tsp00_KeyPtr *);
                    KeyLen             : tsp00_Int4;
                    lock_type          : tbd_treelock;
                    node_req           : tbd_node_request;
                    VAR subtree_info   : tbd_subtree_info;
                    VAR left_estimate  : tsp00_Int4;
                    VAR rightestimate  : tsp00_Int4;
                    VAR index_pno      : tsp00_PageNo;
                    VAR nptr           : tbd_node_ptrs;
                    VAR neighbs        : tbd_neighbors;
                    VAR current        : tbd_current_tree);
 
        PROCEDURE
              b50first_leaf (
                    VAR firstleaf : tsp00_PageNo;
                    lock_type     : tbd_treelock;
                    VAR single    : boolean;
                    VAR current   : tbd_current_tree);
 
        PROCEDURE
              b50get_left_subtree (
                    VAR nptr         : tbd_node_ptrs;
                    VAR index        : integer;
                    left_neighbor    : tsp00_PageNo;
                    VAR left_subroot : tsp00_PageNo;
                    VAR current      : tbd_current_tree);
 
        PROCEDURE
              b50position_leaf (
                    leafpos           : tsp00_Int4;
                    leafnodes         : tsp00_Int4;
                    VAR left_estimate : tsp00_Int4;
                    VAR rightestimate : tsp00_Int4;
                    VAR nptr          : tbd_node_ptrs;
                    VAR current       : tbd_current_tree);
 
        PROCEDURE
              b50release_subtree (
                    subroot        : tsp00_PageNo;
                    stringcol_cnt  : integer;
                    varcol_cnt_off : integer;
                    only_empty     : boolean;
                    VAR current    : tbd_current_tree);
 
        PROCEDURE
              b50reorg_treeindex (
                    VAR rk         : tgg00_Lkey;
                    stringcol_cnt  : integer;
                    varcol_cnt_off : integer;
                    VAR current    : tbd_current_tree);
 
        PROCEDURE
              b50verify_subtree (root : tsp00_PageNo;
                    right           : tsp00_PageNo;
                    conv_update     : boolean;
                    VAR dump_parent : boolean;
                    VAR current     : tbd_current_tree;
                    VAR NumPages    : tsp00_Int4);
 
        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;
                    nptr         : tbd_nodeptr;
                    VAR recIndex : tsp00_Int4;
                    VAR leaf     : tsp00_PageNo);
 
        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 temp_current : tbd_current_tree);
 
        PROCEDURE
              bd50FindLeaf (
                    VAR sepKey  : tsp00_Key;
                    keyLen      : tsp00_Int4;
                    VAR nptrs   : tbd_node_ptrs;
                    VAR neighbs : tbd_neighbors;
                    VAR current : tbd_current_tree);
 
        FUNCTION
              bd50IndexNodeIsSaveForDelete (
                    VAR current : tbd_current_tree;
                    recIndex    : tsp00_Int4) : boolean;
 
        FUNCTION
              bd50IndexNodeIsSaveForInsert (
                    VAR current : tbd_current_tree;
                    recIndex    : tsp00_Int4) : boolean;
 
.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
              bd13GetNode (VAR Current : tbd_current_tree;
                    Pno          : tsp00_PageNo;
                    PageLockMode : tbd00_PageLockMode;
                    NodeReq      : tbd_node_request;
                    VAR Nptrs    : tbd_node_ptrs);
 
        PROCEDURE
              b13free_node (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b13pfree_pno (pno : tsp00_PageNo;
                    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
              treehandling : VBD30;
 
        PROCEDURE
              b30cinit_current (VAR t : tgg00_TransContext;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b30current (VAR t : tgg00_TransContext;
                    VAR file_id : tgg00_FileId;
                    m_type      : tgg00_MessType;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b30exists_rec (VAR rk  : tgg00_Lkey;
                    VAR current      : tbd_current_tree);
 
        PROCEDURE
              b30tadd_temp_primary (
                    bCountDuplicates : boolean;
                    VAR Rec          : tgg00_Rec;
                    VAR current      : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              leafhandling : VBD31;
 
        PROCEDURE
              b31next_search (release_frame : boolean;
                    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
              concurrency : VBD75;
 
        PROCEDURE
              b75ilread_lock_index (VAR current : tbd_current_tree;
                    indexnode      : tsp00_PageNo;
                    suspend_reason : tsp00_Int2);
 
        PROCEDURE
              b75iuiread_unlocklock_index (VAR current : tbd_current_tree;
                    src_index      : tsp00_PageNo;
                    dest_index     : tsp00_PageNo;
                    suspend_reason : tsp00_Int2);
 
        PROCEDURE
              b75iuread_unlock_index (VAR current : tbd_current_tree;
                    indexnode       : tsp00_PageNo);
 
        PROCEDURE
              b75llwrite_lock_leaf (VAR current : tbd_current_tree;
                    leaf           : tsp00_PageNo;
                    suspend_reason : tsp00_Int2);
 
        PROCEDURE
              b75llread_lock_leaf (VAR current : tbd_current_tree;
                    leaf           : tsp00_PageNo;
                    suspend_reason : tsp00_Int2);
 
        PROCEDURE
              b75reset_lock (VAR current : tbd_current_tree;
                    leaf : tsp00_PageNo);
 
        PROCEDURE
              b75lulread_unlocklock_leaf (
                    VAR current    : tbd_current_tree;
                    src_leaf       : tsp00_PageNo;
                    src_index      : tsp00_PageNo;
                    dest_leaf      : tsp00_PageNo;
                    dest_index     : tsp00_PageNo;
                    suspend_reason : tsp00_Int2);
 
        PROCEDURE
              b75luread_unlock_leaf (VAR current : tbd_current_tree;
                    leaf : tsp00_PageNo);
 
        PROCEDURE
              b75tlread_lock_tree (VAR current : tbd_current_tree;
                    suspend_reason : tsp00_Int2);
 
        FUNCTION
              b75tree_request (pid : tsp00_TaskId;
                    root : tsp00_PageNo) : boolean;
 
        PROCEDURE
              b75turead_unlock_tree (VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              BD_Wrapper : VBD999;
 
        PROCEDURE
              bd999CheckSpace(
                    VAR Trans         : tgg00_TransContext;
                    NumPagesRequestes : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01glob : tgg_kernel_globals;
 
        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    : tsp_int4;
                    msg_label : tsp_c8;
                    msg_text  : tsp_c24;
                    msg_value : tsp_int4);
 
      ------------------------------ 
 
        FROM
              GG_cpp_auxiliary_functions : VGG06;
 
        FUNCTION
              gg06PnoGet (VAR Cint4 : tgg90_Cint4): tsp00_Int4;
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG10;
 
        PROCEDURE
              g10mv1  (mod_id : tsp_c6;
                    mod_intern_num : tsp_int4;
                    source_upb     : tsp_int4;
                    destin_upb     : tsp_int4;
                    VAR source     : tbd_node;
                    source_pos     : tsp_int4;
                    VAR destin     : tgg00_Filename;
                    destin_pos     : tsp_int4;
                    length         : tsp_int4;
                    VAR e          : tgg_basis_error);
 
        PROCEDURE
              g10mv2  (mod_id : tsp_c6;
                    mod_intern_num : tsp_int4;
                    source_upb     : tsp_int4;
                    destin_upb     : tsp_int4;
                    VAR source     : tbd_node;
                    source_pos     : tsp_int4;
                    VAR destin     : tsp00_Key;
                    destin_pos     : tsp_int4;
                    length         : tsp_int4;
                    VAR e          : tgg_basis_error);
 
        PROCEDURE
              g10mv3  (mod_id : tsp_c6;
                    mod_intern_num : tsp_int4;
                    source_upb     : tsp_int4;
                    destin_upb     : tsp_int4;
                    VAR source     : tsp00_Key;
                    source_pos     : tsp_int4;
                    VAR destin     : tsp00_Key;
                    destin_pos     : tsp_int4;
                    length         : tsp_int4;
                    VAR e          : tgg_basis_error);
 
        PROCEDURE
              g10mv4  (mod_id      : tsp_c6;
                    mod_intern_num : tsp_int4;
                    source_upb     : tsp_int4;      destin_upb : tsp_int4;
                    VAR source     : tsp00_Key;     source_pos : tsp_int4;
                    VAR destin     : tsp_moveobj;   destin_pos : tsp_int4;
                    length         : tsp_int4;
                    VAR e          : tgg_basis_error);
 
      ------------------------------ 
 
        FROM
              KB_index_handling : VKB33;
 
        PROCEDURE
              k33mult_inv_key (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 move_err  : tgg00_BasisError);
 
      ------------------------------ 
 
        FROM
              RTE-Extension-10 : VSP10;
 
        PROCEDURE
              s10mv2 (size1   : tsp_int4;
                    size2    : tsp_int4;
                    VAR src  : tbd_node;
                    srcind   : tsp_int4;
                    VAR dest : tbd_node;
                    destind  : tsp_int4;
                    cnt      : tsp_int4);
 
      ------------------------------ 
 
        FROM
              RTE-Extension-30 : VSP30;
 
        PROCEDURE
              s30cmp (VAR buf1  : tsp00_Key;
                    fieldpos1    : tsp_int4;
                    fieldlength1 : tsp_int4;
                    VAR buf2     : tsp00_Key;
                    fieldpos2    : tsp_int4;
                    fieldlength2 : tsp_int4;
                    VAR l_result : tsp_lcomp_result);
&       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
              t01msgcheck (msg      : tsp00_C30;
                    check_condition : boolean;
                    bad_int         : 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);
 
        FUNCTION
              t01trace (debug : tgg00_Debug) : boolean;
&       endif
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
        PROCEDURE
              b06dump_bad_page;
 
              tbd_univ_ptr tbd_nodeptr
 
        PROCEDURE
              g10mv1;
 
              tsp_moveobj tbd_node
              tsp_moveobj tgg00_Filename
 
        PROCEDURE
              g10mv2;
 
              tsp_moveobj tbd_node
              tsp_moveobj tsp00_Key
 
        PROCEDURE
              g10mv3;
 
              tsp_moveobj tsp00_Key
              tsp_moveobj tsp00_Key
 
        PROCEDURE
              g10mv4;
 
              tsp_moveobj tsp00_Key
 
        PROCEDURE
              s10mv2;
 
              tsp_moveobj tbd_node
 
        PROCEDURE
              s30cmp;
 
              tsp_moveobj tsp00_Key
              tsp_moveobj tsp00_Key
&             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:
 
   b50eval_pagecount
      (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
   b50find_leaf(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;If the current tree is already locked,
.br;lock_type = w_lock_leaf calls B75LLWRITE_LOCK_LEAF and
.br;lock_type = r_lock_leaf calls B75LLREAD_LOCK_LEAF,
.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
   b50first_leaf(firstleaf,lock_type,single,current)
.sp
Firstleaf supplies the page number of the leaf that is responsible for
the lowest key (dependent on key type). If this leaf is the only node of
the tree, 'single' is set to TRUE; otherwise it is set to
FALSE.
.br;If the current tree is already locked,
.br;lock_type = w_lock_leaf calls B75LLWRITE_LOCK_LEAF and
.br;lock_type = r_lock_leaf calls B75LLREAD_LOCK_LEAF,
.br;which works correctly only, if there is a tree lock on the current
tree (r_lock_tree)
.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
   b50position_leaf(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;lock_type = w_lock_leaf calls B75LLWRITE_LOCK_LEAF and
.br;lock_type = r_lock_leaf calls B75LLREAD_LOCK_LEAF,
.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
   b50release_subtree(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
      c_count_duplicates        = true;
      c_upb_pages_to_count_recs = 3;
 
 
(*------------------------------*) 
 
PROCEDURE
      b50bfind_branchnode (
            VAR sepkey  : tsp00_Key;
            KeyLen      : tsp00_Int4;
            lno         : tsp00_Int2;
            node_req    : tbd_node_request;
            VAR nptr    : tbd_node_ptrs;
            VAR neighbs : tbd_neighbors;
            VAR found   : boolean;
            VAR current : tbd_current_tree);
 
VAR
      last           : boolean;
      node_release   : boolean;
      this_lno       : tsp00_Int2;
      subroot_index  : integer;
      index          : integer;
      subroot        : tsp00_PageNo;
      next           : tsp00_PageNo;
      right          : tsp00_PageNo;
      right_neighbor : tsp00_PageNo;
      left           : tsp00_PageNo;
      left_neighbor  : tsp00_PageNo;
 
BEGIN
&ifdef TRACE
t01msgcheck ('b50bf_0: illegal node_request ',
      ((node_req <> nr_return_if_leaf) AND
      (node_req <> nr_ret_if_leaf_or_first_index)), lno);
t01msgcheck ('b50bf_1: leaflevel not allowed',
      lno <> LEAF_LEVEL_BD00, lno);
&endif
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    this_lno       := LEAF_LEVEL_BD00;
    subroot        := fileRoot_gg00;
    left           := NIL_PAGE_NO_GG00;
    left_neighbor  := left;
    right          := NIL_PAGE_NO_GG00;
    right_neighbor := right;
    WITH neighbs DO
        BEGIN
        ln := NIL_PAGE_NO_GG00;
        rn := NIL_PAGE_NO_GG00
        END;
    (*ENDWITH*) 
    node_release := false;
    REPEAT
        IF  node_release
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  (ftsDynamic_egg00 IN fileType_gg00)
            AND
            (curr_lockstate = r_lock_tree)
            AND
            g01glob.bd_subtree
        THEN
            BEGIN
            (* node_req = nr_for_read *)
            IF  subroot = fileRoot_gg00
            THEN
                BEGIN
                bd13GetNode (current, subroot, plmNoLock_ebd00,
                      nr_ret_if_leaf_or_first_index, nptr);
                IF  (trError_gg00 = e_root_is_first_index)
                    OR
                    (trError_gg00 = e_root_is_leaf)
                THEN
                    BEGIN
                    trError_gg00 := e_ok;
                    b75ilread_lock_index (current, fileRoot_gg00, 123);
                    bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00,
                          nr_for_read, nptr)
                    END
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                (* J.P. 16.12.96 *)
                IF  (this_lno = SECOND_INDEX_LEVEL_BD00)
                THEN
                    b75ilread_lock_index (current, subroot, 124);
                (*ENDIF*) 
                bd13GetNode (current, subroot, plmNoLock_ebd00,
                      nr_for_read, nptr)
                END
            (*ENDIF*) 
            END
        ELSE
            IF  node_req = nr_for_update
            THEN
                BEGIN
                IF  subroot = fileRoot_gg00
                THEN
                    BEGIN
                    IF  (lno > FIRST_INDEX_LEVEL_BD00)
                    THEN
                        (* If the tree consists of more than two   *)
                        (* levels (leaf and firstindex level) then *)
                        (* we have got a exclusive BD-lock on it.  *)
                        (* Therefore nr_for_update will generate   *)
                        (* no trouble with parallel nr_for_read on *)
                        (* nodes of the B*tree index.              *)
                        bd13GetNode (current, subroot, plmNoLock_ebd00,
                              nr_for_update, nptr)
                    ELSE
                        BEGIN
                        bd13GetNode (current, subroot, plmNoLock_ebd00,
                              nr_ret_if_leaf_or_first_index, nptr);
                        IF  (trError_gg00 = e_root_is_first_index)
                            OR
                            (trError_gg00 = e_root_is_leaf)
                        THEN
                            BEGIN
                            trError_gg00 := e_ok;
                            bd13GetNode (current, subroot, plmNoLock_ebd00,
                                  nr_for_update, nptr)
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    IF  (this_lno = succ (lno))
                    THEN
                        bd13GetNode (current, subroot, plmNoLock_ebd00,
                              nr_for_update, nptr)
                    ELSE
                        bd13GetNode (current, subroot, plmNoLock_ebd00,
                              nr_for_read, nptr)
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            ELSE
                bd13GetNode (current, subroot, plmNoLock_ebd00,
                      node_req, nptr);
            (*ENDIF*) 
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            node_release := true;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            this_lno := nptr.np_ptr^.nd_level;
&           ifdef TRACE
            IF  node_req = nr_for_read
            THEN
                t01msgcheck ('b50bf_2: leaflevel not allowed',
                      this_lno <> LEAF_LEVEL_BD00, this_lno);
&           endif
            (*ENDIF*) 
            IF  ftsPerm_egg00 IN fileType_gg00
            THEN
                BEGIN
                IF  nptr.np_ptr^.nd_id <> fileRoot_gg00
                THEN
                    BEGIN
                    next := nptr.np_ptr^.nd_right;
                    IF  (next <> right_neighbor)
                        AND (this_lno > LEAF_LEVEL_BD00)
                    THEN
                        BEGIN
                        (* PTS 1107109 TS 2000-07-18 *)
                        g01opmsg (sp3p_knldiag, sp3m_error,
                              csp3_b50_2_invalid_structure, csp3_n_btree,
                              'invalid index structure ', right_neighbor);
                        b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                              nptr.np_ptr^.nd_id, nptr.np_ptr, 1);
                        trError_gg00 := e_invalid_index_structure;
                        (* PTS 1107109 *)
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  this_lno >= succ(lno)
                THEN
                    BEGIN
                    bd51SearchBranch (current, @sepkey, KeyLen, nptr.np_ptr, index );
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        subroot_index := index;
                        subroot       := bd52SubtreePno (nptr.np_ptr, index);
                        b51next_branch (nptr.np_ptr, index, last);
                        IF  last
                        THEN
                            bd50get_right_subtree (current, nptr, index,
                                  right, right_neighbor)
                        ELSE
                            right_neighbor := bd52SubtreePno (nptr.np_ptr, index);
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            right := right_neighbor;
                            b50get_left_subtree (nptr, subroot_index,
                                  left, left_neighbor, current);
                            IF  trError_gg00 = e_ok
                            THEN
                                left := left_neighbor;
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
    UNTIL
        (this_lno <= lno) OR (trError_gg00 <> e_ok);
    (*ENDREPEAT*) 
    IF  trError_gg00 = e_ok
    THEN
        WITH neighbs DO
            BEGIN
            ln     := left;
            rn     := right;
&           ifdef TRACE
            IF  t01trace (bd_index)
            THEN
                BEGIN
                t01int4 (bd_index, 'left neighbo', left);
                t01int4 (bd_index, 'right neighb', right);
                END;
&           endif
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
    (*ENDIF*) 
    found := (this_lno = lno)
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b50calculate_pagecount (
            VAR current           : tbd_current_tree;
            VAR is_tree_requested : boolean;
            VAR start_sep         : tgg00_Lkey;
            VAR stop_sep          : tgg00_Lkey;
            VAR page_count        : tsp00_Int4);
 
VAR
      node_release     : boolean;
      use_subtree_lock : boolean;
      l_result         : tsp00_LcompResult;
      level            : tsp00_Int2;
      io_cnt           : integer;
      rec_pos          : tsp00_Int2;
      pRec             : tgg00_RecPtr;
      start_index      : integer;
      stop_index       : integer;
      next             : tsp00_PageNo;
      old_next         : tsp00_PageNo;
      subroot          : tsp00_PageNo;
      start_pno        : tsp00_PageNo;
      nptr             : tbd_node_ptrs;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    io_cnt           := 0;
    level            := LEAF_LEVEL_BD00;
    subroot          := fileRoot_gg00;
    node_release     := false;
    nptr.np_ptr      := NIL;
    nptr.np_cbptr    := NIL;
    use_subtree_lock :=
          (curr_lockstate <> no_bd_lock)
          AND
          (ftsDynamic_egg00 IN fileType_gg00)
          AND
          g01glob.bd_subtree;
    REPEAT
        IF  node_release
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  (level = SECOND_INDEX_LEVEL_BD00) AND use_subtree_lock
        THEN
            BEGIN
            b75ilread_lock_index (current, subroot, 24);
            bd13GetNode (current, subroot, plmNoLock_ebd00,
                  nr_for_read, nptr)
            END
        ELSE
            IF  subroot <> fileRoot_gg00
            THEN
                bd13GetNode (current, subroot, plmNoLock_ebd00,
                      nr_for_read, nptr)
            ELSE
                BEGIN
                IF  use_subtree_lock
                THEN
                    bd13GetNode (current, subroot, plmNoLock_ebd00,
                          nr_ret_if_leaf_or_first_index, nptr)
                ELSE
                    bd13GetNode (current, subroot, plmNoLock_ebd00,
                          nr_return_if_leaf, nptr);
                (*ENDIF*) 
                IF  trError_gg00 = e_root_is_leaf
                THEN
                    BEGIN
                    trError_gg00 := e_no_next_record;
                    page_count   := 1
                    END
                ELSE
                    IF  trError_gg00 = e_root_is_first_index
                    THEN
                        BEGIN
                        trError_gg00 := e_ok;
                        b75ilread_lock_index (current, subroot, 24);
                        bd13GetNode (current, subroot, plmNoLock_ebd00,
                              nr_for_read, nptr)
                        END
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            node_release := true;
            level        := nptr.np_ptr^.nd_level;
            bd51SearchBranch (current, @start_sep.keyVal_gg00, start_sep.keyLen_gg00, nptr.np_ptr, start_index);
            IF  level > FIRST_INDEX_LEVEL_BD00
            THEN
                subroot := bd52SubtreePno (nptr.np_ptr, start_index)
            ELSE
                start_pno := nptr.np_ptr^.nd_id
            (*ENDIF*) 
            END
        (*ENDIF*) 
    UNTIL
        (level = FIRST_INDEX_LEVEL_BD00) OR (trError_gg00 <> e_ok);
    (*ENDREPEAT*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        (* *)
        (* level = 1 *)
        (* *)
        old_next := NIL_PAGE_NO_GG00;
        next     := start_pno;
        REPEAT
            IF  next <> start_pno
            THEN
                BEGIN
                IF  curr_lockstate = r_lock_index
                THEN
                    b75iuiread_unlocklock_index (current, old_next, next, 7);
                (*ENDIF*) 
                bd13GetNode (current, next, plmNoLock_ebd00, nr_for_read, nptr)
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                WITH nptr.np_ptr^ DO
                    BEGIN
&                   ifdef TRACE
                    t01int4 (bd_index, 'page  id    ', nd_id);
                    t01int4 (bd_index, 'recs in page', nd_record_cnt);
&                   endif
                    rec_pos := nd_pointer_list [MAX_POINTERINDEX_BD00 - (nd_record_cnt - 1)];
                    IF  (rec_pos < BODY_BEG_BD00) OR (rec_pos > nd_bottom)
                    THEN
                        BEGIN
                        trError_gg00 := e_illegal_entrypos;
                        b06dump_bad_page (trTaskId_gg00, 'd',
                              FILE_EXT_COR_BD00, nd_id, nptr.np_ptr, 1);
                        g01opmsg (sp3p_knldiag, sp3m_error,
                              bd50c8IllegalEntryPos_csp03, csp3_n_btree,
                              'Illegal entry pos       ', rec_pos);
                        b06write_filename_and_root (curr_tree_id)
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        pRec := @nd_body [rec_pos];
                        s30cmp (
                              pRec^.recKey_gg00.keyVal_gg00, 1,
                              pRec^.recKey_gg00.keyLen_gg00,
                              stop_sep.keyVal_gg00, 1,
                              stop_sep.keyLen_gg00, l_result);
                        CASE l_result OF
                            l_less :
                                BEGIN
                                (* trError_gg00 = e_ok  *)
                                END;
                            l_greater :
                                BEGIN
                                trError_gg00 := e_no_next_record;
                                bd51SearchBranch (current, @stop_sep.keyVal_gg00, stop_sep.keyLen_gg00, nptr.np_ptr,
                                      stop_index);
                                END;
                            l_equal :
                                BEGIN
                                trError_gg00 := e_no_next_record;
                                stop_index   := nd_record_cnt - 1
                                END;
                            OTHERWISE:
                                ;
                            END;
                        (*ENDCASE*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            (* *)
                            (* increment page count and read next page. *)
                            (* *)
                            IF  next = start_pno
                            THEN
                                page_count := page_count + (nd_record_cnt - start_index)
                            ELSE
                                page_count := page_count + nd_record_cnt
                            (*ENDIF*) 
                            END
                        ELSE
                            IF  trError_gg00 = e_no_next_record
                            THEN
                                BEGIN
                                (* *)
                                (* increment page count and stop reading *)
                                (* pages.                                *)
                                (* *)
                                IF  next = start_pno
                                THEN
                                    page_count := stop_index - start_index + 1
                                ELSE
                                    page_count := page_count + stop_index + 1
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDWITH*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    old_next := next;
                    next     := nptr.np_ptr^.nd_right;
                    IF  next = NIL_PAGE_NO_GG00
                    THEN
                        trError_gg00 := e_no_next_record
                    ELSE
                        BEGIN
                        io_cnt := succ (io_cnt);
                        IF  io_cnt = MAX_NODE_SCAN_BD00
                        THEN
                            BEGIN
                            IF  trRteCommPtr_gg00^.to_cancel
                            THEN
                                trError_gg00 := e_cancelled
                            ELSE
                                IF  NOT b75tree_request (trTaskId_gg00, fileRoot_gg00)
                                THEN
                                    io_cnt := 0
                                ELSE
                                    BEGIN
                                    is_tree_requested := true;
                                    g01key_assign (pRec^.recKey_gg00, start_sep, 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,
                                              nptr.np_ptr^.nd_id, nptr.np_ptr, 1)
                                        END
                                    (*ENDIF*) 
                                    END
                                (*ENDIF*) 
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  nptr.np_ptr <> NIL
            THEN
                b13r_release_node (nptr, current, lru_normal);
&           ifdef trace
            (*ENDIF*) 
            t01int4 (bd_index, 'pagecout    ', page_count);
&           endif
        UNTIL
            (trError_gg00 <> e_ok) OR is_tree_requested
            OR
            (next = NIL_PAGE_NO_GG00)
        (*ENDREPEAT*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_no_next_record
    THEN
        trError_gg00 := e_ok;
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    IF  curr_lockstate =  r_lock_index
    THEN
        b75iuread_unlock_index (current, curr_lvl_1_locked)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b50change_treeroot (subroot : tsp00_PageNo;
            new_root    : tsp00_PageNo;
            VAR current : tbd_current_tree);
 
VAR
      last            : boolean;
      index           : integer;
      next_subroot    : tsp00_PageNo;
      aux_source_ptr  : tbd_univ_ptr;
      aux_target_ptr  : tbd_univ_ptr;
      source_nptr     : tbd_node_ptrs;
      target_nptr     : tbd_node_ptrs;
      aux_full_header : tbd_node_header;
 
BEGIN
source_nptr.np_ptr   := NIL;
source_nptr.np_cbptr := NIL;
target_nptr          := source_nptr;
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    bd13GetNode (current, subroot, plmNoLock_ebd00,
          nr_for_update, source_nptr);
    IF  (trError_gg00 = e_ok) AND (subroot = fileRoot_gg00)
    THEN
        BEGIN
        fileRoot_gg00 := new_root;
        bd13GetNode (current, new_root, plmNoLock_ebd00,
              nr_for_update, target_nptr);
        fileRoot_gg00 := subroot;
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            aux_full_header         := target_nptr.np_ptr^.nd_full_header;
            aux_source_ptr.nodeaddr := source_nptr.np_ptr;
            aux_target_ptr.nodeaddr := target_nptr.np_ptr;
            aux_target_ptr.bufaddr^ := aux_source_ptr.bufaddr^;
            (* *)
            WITH target_nptr.np_ptr^ DO
                BEGIN
                nd_root     := new_root;
                nd_id       := new_root;
                nd_checksum := nd_write_cnt;
                nd_trailer  := nd_header
                END;
            (*ENDWITH*) 
            (* *)
            WITH source_nptr.np_ptr^ DO
                BEGIN
                nd_full_header := aux_full_header;
                nd_root        := subroot;
                nd_id          := subroot;
                nd_checksum    := nd_write_cnt;
                nd_trailer     := nd_header
                END;
            (*ENDWITH*) 
            (* *)
            b13w_release_node (source_nptr, current);
            (* *)
            source_nptr          := target_nptr;
            target_nptr.np_ptr   := NIL;
            target_nptr.np_cbptr := NIL
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        WITH source_nptr.np_ptr^ DO
            IF  nd_level = LEAF_LEVEL_BD00
            THEN
                BEGIN
                nd_root := new_root;
                b13w_release_node (source_nptr, current)
                END
            ELSE
                (*  lno > leaflevel *)
                BEGIN
                index := FIRST_REC_INDEX_BD00;
                last  := false;
                REPEAT
                    next_subroot := bd52SubtreePno (source_nptr.np_ptr, index);
                    b50change_treeroot(next_subroot, new_root, current);
                    IF  trError_gg00 = e_ok
                    THEN
                        b51next_branch (source_nptr.np_ptr, index, last)
                    (*ENDIF*) 
                UNTIL
                    last OR (trError_gg00 <> e_ok);
                (*ENDREPEAT*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    nd_root := new_root;
                    b13w_release_node (source_nptr, current)
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDWITH*) 
    (*ENDIF*) 
    IF  trError_gg00 <> e_ok
    THEN
        BEGIN
        IF  source_nptr.np_ptr <> NIL
        THEN
            b13r_release_node (source_nptr, current, lru_normal);
        (*ENDIF*) 
        IF  target_nptr.np_ptr <> NIL
        THEN
            b13r_release_node (target_nptr, current, lru_normal)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(* PTS 1109905 E.Z. *)
(*------------------------------*) 
 
PROCEDURE
      b50check_subtree (
            root                 : tsp00_PageNo;
            right                : tsp00_PageNo;
            long_col_cnt         : tsp00_Int2;
            new_long_col_cnt     : tsp00_Int2;
            VAR dump_parent      : boolean;
            VAR bad_long         : boolean;
            VAR current          : tbd_current_tree;
            check_long_existence : boolean);
 
VAR
      last          : boolean;
      index         : integer;
      lno           : integer;
      right_index   : integer;
      nptr          : tbd_node_ptrs;
      right_subroot : tsp00_PageNo;
      subroot       : tsp00_PageNo;
 
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
        bd13GetNode (current, root, plmNoLock_ebd00,
              nr_for_read, nptr);
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        lno := nptr.np_ptr^.nd_level;
        IF  lno = LEAF_LEVEL_BD00
        THEN
            BEGIN
            IF  right <> nptr.np_ptr^.nd_right
            THEN
                BEGIN
                trError_gg00 := e_invalid_leaves_structure;
                dump_parent  := true;
                g01opmsg (sp3p_knldiag, sp3m_error,
                      csp3_b50_1_invalid_structure, csp3_n_btree,
                      'invalid leaves structure', nptr.np_ptr^.nd_id);
                b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                      nptr.np_ptr^.nd_id, nptr.np_ptr, 1)
                END
            ELSE
                BEGIN
                bd50_CheckEntry (nptr, dump_parent, current);
                IF  (trError_gg00 = e_ok) AND (long_col_cnt > 0)
                THEN
                    BEGIN
                    (* PTS 1109905 E.Z. *)
                    bd50l_check_long (curr_tree_id, curr_trans^,
                          nptr.np_ptr, long_col_cnt, new_long_col_cnt,
                          check_long_existence);
                    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
                        bad_long     := true;
                        trError_gg00 := e_ok;
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        ELSE (*  lno > leaflevel *)
            IF  right <> nptr.np_ptr^.nd_right
            THEN
                BEGIN
                trError_gg00 := e_invalid_index_structure;
                dump_parent    := true;
                g01opmsg (sp3p_knldiag, sp3m_error,
                      csp3_b50_2_invalid_structure, csp3_n_btree,
                      'invalid index structure ', nptr.np_ptr^.nd_id);
                b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                      nptr.np_ptr^.nd_id, nptr.np_ptr, 1)
                END
            ELSE
                BEGIN
                index := FIRST_REC_INDEX_BD00;
                last  := false;
                REPEAT
                    subroot     := bd52SubtreePno (nptr.np_ptr, index);
                    right_index := index;
                    bd50get_right_subtree (current, nptr, right_index,
                          right, right_subroot);
                    IF  trError_gg00 = e_ok
                    THEN
                        (* PTS 1109905 E.Z. *)
                        b50check_subtree (subroot, right_subroot,
                              long_col_cnt, new_long_col_cnt,
                              dump_parent, bad_long,
                              current, check_long_existence);
                    (*ENDIF*) 
                    IF  dump_parent
                    THEN
                        BEGIN
                        (* trError_gg00 = e_invalid_index_structure  OR *)
                        (* trError_gg00 = e_invalid_leaves_structure OR *)
                        (* trError_gg00 = e_illegal_entrypos            *)
                        dump_parent := false;
                        g01opmsg (sp3p_knldiag, sp3m_error,
                              csp3_b50_3_invalid_structure, csp3_n_btree,
                              'parent node is          ', nptr.np_ptr^.nd_id);
                        b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                              nptr.np_ptr^.nd_id, nptr.np_ptr, 1)
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        b51next_branch (nptr.np_ptr, index, last)
                    (*ENDIF*) 
                UNTIL
                    last OR (trError_gg00 <> e_ok)
                (*ENDREPEAT*) 
                END
            (*ENDIF*) 
        (*ENDIF*) 
        END
    ELSE (* e_ok <> trError_gg00 *)
        IF  (root = curr_tree_id.fileRoot_gg00) AND
            (
            (trError_gg00 = e_invalid_root      ) OR
            (trError_gg00 = e_page_in_wrong_tree)
            )
        THEN
            trError_gg00 := e_ok;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b50cross_subtree_boundary (VAR current : tbd_current_tree;
            source_leaf : tsp00_PageNo;
            dest_leaf   : tsp00_PageNo);
 
VAR
      new_index_pno : tsp00_PageNo;
      nptr          : tbd_node_ptrs;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
&   ifdef TRACE
    t01msgcheck ('b50cr: Only for dynamic trees!',
          (ftsDynamic_egg00 IN curr_tree_id.fileType_gg00), 0);
    IF  t01trace (bd_index)
    THEN
        BEGIN
        t01int4   (bd_index, 'curr_lvl1_lo', curr_lvl_1_locked);
        t01p2int4 (bd_index, 'curr_left_bo', curr_left_bound
              ,              'curr_right_b', curr_right_bound);
        t01int4   (bd_index, 'right_neighb', dest_leaf);
        END;
&   endif
    (*ENDIF*) 
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    bd13GetNode (current, curr_lvl_1_locked, plmNoLock_ebd00,
          nr_for_read, nptr);
    IF  (trError_gg00 = e_ok)
    THEN
        BEGIN
        new_index_pno := nptr.np_ptr^.nd_right;
        b13r_release_node (nptr, current, lru_normal);
        b75reset_lock (current, source_leaf);
        b75ilread_lock_index (current, new_index_pno, 125);
        bd13GetNode (current, new_index_pno, plmNoLock_ebd00,
              nr_for_read, nptr);
        IF  (trError_gg00 = e_ok)
        THEN
            BEGIN
            curr_left_bound  := bd52SubtreePno (nptr.np_ptr, FIRST_REC_INDEX_BD00);
            curr_right_bound := bd52SubtreePno (nptr.np_ptr, nptr.np_ptr^.nd_record_cnt - 1);
&           ifdef TRACE
            t01msgcheck ('b50cr: dest_leaf <> left_bound',
                  (dest_leaf = curr_left_bound), curr_left_bound);
&           endif
            END;
        (*ENDIF*) 
        IF  (nptr.np_ptr <> NIL)
        THEN
            b13r_release_node (nptr, current, lru_normal)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b50eval_pagecount (
            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
      node_release     : boolean;
      use_subtree_lock : boolean;
      found            : boolean;
      this_lno         : tsp00_Int2;
      sep_level        : tsp00_Int2;
      middle_lno       : tsp00_Int2;  (* PTS 1113904 2002-01-30 *)
      subroot          : tsp00_PageNo;
      stop_pno         : tsp00_PageNo;
      start_pno        : 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;
      start_leaf       : tsp00_PageNo;
      stop_leaf        : tsp00_PageNo;
      sum_indices      : integer;
      all_page_cnt_real: tsp00_Longreal;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    middle_lno        := MAX_LEVEL_BD00; (* PTS 1113904 2002-01-30 *)
    all_page_cnt      := 0;
    all_page_cnt_real := 0.0;
    record_cnt        := -1;
    subroot           := fileRoot_gg00;
    node_release      := false;
    start_leaf        := subroot;
    start_pno         := subroot;
    stop_leaf         := subroot;
    FOR path := 1 TO 3 DO
        BEGIN
        FOR this_lno := 1 TO c_maxlevel_arr_ix DO
            BEGIN
            coverings  [this_lno, path] := MAX_INT4_SP00;
            indices    [this_lno, path] := MAX_INT4_SP00;
            maxindices [this_lno, path] := MAX_INT4_SP00;
            pnos       [this_lno, path] := NIL_PAGE_NO_GG00;
            avg_amount [this_lno, path] := 0
            END;
        (*ENDFOR*) 
        left_page_cnt  [path] := 0;
        END;
    (*ENDFOR*) 
    nptr.np_ptr      := NIL;
    nptr.np_cbptr    := NIL;
    use_subtree_lock :=
          (ftsDynamic_egg00 IN fileType_gg00)
          AND
          (curr_lockstate <> no_bd_lock)
          AND
          g01glob.bd_subtree;
    REPEAT
        IF  node_release
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  subroot <> fileRoot_gg00
        THEN
            bd13GetNode (current, subroot, plmNoLock_ebd00, nr_for_read, nptr)
        ELSE
            BEGIN
            IF  use_subtree_lock
            THEN
                bd13GetNode (current, subroot, plmNoLock_ebd00, nr_ret_if_leaf_or_first_index, nptr)
            ELSE
                bd13GetNode (current, subroot, plmNoLock_ebd00, nr_return_if_leaf, nptr);
            (*ENDIF*) 
            IF  trError_gg00 = e_root_is_leaf
            THEN
                BEGIN
                trError_gg00 := e_no_next_record;
                all_page_cnt := 1;
                page_count   := 1
                END
            ELSE
                BEGIN
                IF  trError_gg00 = e_root_is_first_index
                THEN
                    BEGIN
                    trError_gg00 := e_ok;
                    b75ilread_lock_index(current, subroot, 126);
                    bd13GetNode (current, subroot, plmNoLock_ebd00, nr_for_read, nptr)
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            node_release := true;
            this_lno     := nptr.np_ptr^.nd_level;
            bd51SearchBranch (current, @start_key.keyVal_gg00, start_key.keyLen_gg00, nptr.np_ptr,
                  indices [this_lno,1]);
            indices    [this_lno, 2] := indices [this_lno, 1];
            pnos       [this_lno, 1] := nptr.np_ptr^.nd_id;
            pnos       [this_lno, 2] := pnos    [this_lno, 1];
            coverings  [this_lno, 1] := nptr.np_ptr^.nd_bottom - BODY_BEG_BD00
                  +                           nptr.np_ptr^.nd_record_cnt*POINTERSIZE_BD00;
            coverings  [this_lno, 2] := coverings  [this_lno, 1];
            maxindices [this_lno, 1] := nptr.np_ptr^.nd_record_cnt - 1;
            maxindices [this_lno, 2] := maxindices [this_lno, 1];
            IF  this_lno > FIRST_INDEX_LEVEL_BD00
            THEN
                BEGIN
                subroot := bd52SubtreePno (nptr.np_ptr, indices  [this_lno,1]);
                IF  (this_lno = SECOND_INDEX_LEVEL_BD00) AND use_subtree_lock
                THEN
                    b75ilread_lock_index(current, subroot, 127)
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                all_page_cnt     := maxindices [this_lno, 1] + 1;
                start_pno        := nptr.np_ptr^.nd_id;
                IF  count_records
                THEN
                    start_leaf := bd52SubtreePno (nptr.np_ptr, indices  [this_lno,1]);
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END
        (*ENDIF*) 
    UNTIL
        (this_lno = FIRST_INDEX_LEVEL_BD00) OR (trError_gg00 <> e_ok);
    (*ENDREPEAT*) 
    IF  nptr.np_ptr <> NIL
    THEN
        BEGIN
        node_release := false;
        b13r_release_node (nptr, current, lru_normal)
        END;
    (*ENDIF*) 
    IF  curr_lockstate = r_lock_index
    THEN
        b75reset_lock (current, NIL_PAGE_NO_GG00);
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        subroot       := fileRoot_gg00;
        middl_subroot := NIL_PAGE_NO_GG00;
        REPEAT
            IF  node_release
            THEN
                b13r_release_node (nptr, current, lru_normal);
            (*ENDIF*) 
            IF  (subroot <> fileRoot_gg00) OR NOT use_subtree_lock
            THEN
                bd13GetNode (current, subroot, plmNoLock_ebd00, nr_for_read, nptr)
            ELSE
                BEGIN
                bd13GetNode (current, subroot, plmNoLock_ebd00,
                      nr_ret_if_leaf_or_first_index, nptr);
                (* *)
                (* e_root_is_leaf is impossible; see path1 *)
                (* *)
                IF  trError_gg00 = e_root_is_first_index
                THEN
                    BEGIN
                    trError_gg00 := e_ok;
                    b75ilread_lock_index (current, subroot, 128);
                    bd13GetNode (current, subroot, plmNoLock_ebd00, nr_for_read, nptr)
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                node_release := true;
                this_lno     := nptr.np_ptr^.nd_level;
                bd51SearchBranch (current, @stop_key.keyVal_gg00, stop_key.keyLen_gg00, nptr.np_ptr,
                      indices [this_lno,3]);
                pnos       [this_lno, 3] := nptr.np_ptr^.nd_id;
                coverings  [this_lno, 3] := nptr.np_ptr^.nd_bottom - BODY_BEG_BD00
                      +                           nptr.np_ptr^.nd_record_cnt*POINTERSIZE_BD00;
                maxindices [this_lno, 3] := nptr.np_ptr^.nd_record_cnt - 1;
                IF  (
                    (indices  [this_lno,1] <> indices  [this_lno,3])
                    OR (this_lno = 1)
                    )
                    AND (middl_subroot = NIL_PAGE_NO_GG00)
                THEN
                    BEGIN
                    (* the node where the pathes separate, PTS 1104630 Alexander Kley *)
                    sum_indices := (indices  [this_lno,1] + indices  [this_lno,3]);
                    indices  [this_lno,2] := sum_indices DIV 2;
                    IF  this_lno > FIRST_INDEX_LEVEL_BD00
                    THEN
                        BEGIN
                        middl_subroot := bd52SubtreePno (nptr.np_ptr, indices  [this_lno,2]);
                        middle_lno    := this_lno -1 (* PTS 1113904 2002-01-30 *)
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  this_lno > FIRST_INDEX_LEVEL_BD00
                THEN
                    BEGIN
                    subroot := bd52SubtreePno (nptr.np_ptr, indices  [this_lno,3]);
                    IF  (this_lno = SECOND_INDEX_LEVEL_BD00) AND use_subtree_lock
                    THEN
                        b75ilread_lock_index (current, subroot, 129)
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    IF  start_pno <> nptr.np_ptr^.nd_id
                    THEN
                        all_page_cnt := all_page_cnt + maxindices [this_lno,3] + 1;
                    (*ENDIF*) 
                    stop_pno := nptr.np_ptr^.nd_id;
                    IF  count_records
                    THEN
                        stop_leaf := bd52SubtreePno (nptr.np_ptr, indices  [this_lno,3]);
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
        UNTIL
            (this_lno = FIRST_INDEX_LEVEL_BD00) OR (trError_gg00 <> e_ok)
        (*ENDREPEAT*) 
        END;
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        BEGIN
        node_release := false;
        b13r_release_node (nptr, current, lru_normal)
        END;
    (*ENDIF*) 
    IF  curr_lockstate = r_lock_index
    THEN
        b75reset_lock (current, NIL_PAGE_NO_GG00);
    (*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 *)
        (* *)
        (* PTS 1113904 2002-01-30 *)
        IF  (middle_lno = FIRST_INDEX_LEVEL_BD00) AND use_subtree_lock
        THEN
            b75ilread_lock_index (current, middl_subroot, 131);
        (*ENDIF*) 
        REPEAT
            IF  node_release
            THEN
                b13r_release_node (nptr, current, lru_normal);
            (*ENDIF*) 
            bd13GetNode (current, middl_subroot, plmNoLock_ebd00, nr_for_read, nptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                node_release := true;
                this_lno     := nptr.np_ptr^.nd_level;
                pnos       [this_lno, 2] := nptr.np_ptr^.nd_id;
                coverings  [this_lno, 2] := nptr.np_ptr^.nd_bottom - BODY_BEG_BD00
                      +                           nptr.np_ptr^.nd_record_cnt*POINTERSIZE_BD00;
                maxindices [this_lno, 2] := nptr.np_ptr^.nd_record_cnt - 1;
                (* PTS 1104630 Alexander Kley *)
                IF  sum_indices = 2*indices  [succ(this_lno), 2]
                THEN
                    BEGIN
                    sum_indices          := maxindices [this_lno, 2];
                    indices [this_lno,2] := sum_indices DIV 2
                    END
                ELSE
                    BEGIN
                    (* once we took the leaf with smaller keys *)
                    sum_indices          := maxindices [this_lno, 2] * 2;
                    indices [this_lno,2] := maxindices [this_lno, 2]
                    END;
                (*ENDIF*) 
                (* END PTS 1104630 Alexander Kley *)
                IF  this_lno > FIRST_INDEX_LEVEL_BD00
                THEN
                    BEGIN
                    middl_subroot := bd52SubtreePno (nptr.np_ptr, indices  [this_lno, 2]);
                    IF  (this_lno = SECOND_INDEX_LEVEL_BD00) AND use_subtree_lock
                    THEN
                        b75ilread_lock_index (current, middl_subroot, 130)
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
        UNTIL
            (this_lno = FIRST_INDEX_LEVEL_BD00) OR (trError_gg00 <> e_ok);
        (*ENDREPEAT*) 
        END;
    (* after all estimation with accumulated average *)
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        BEGIN
        node_release := false;
        b13r_release_node (nptr, current, lru_normal)
        END;
    (*ENDIF*) 
    IF  curr_lockstate = r_lock_index
    THEN
        b75reset_lock (current, NIL_PAGE_NO_GG00);
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        FOR this_lno := MAX_LEVEL_BD00 DOWNTO 1 DO
            BEGIN
            FOR  path := 1 TO 3 DO
                BEGIN
                IF  indices [this_lno, path] <> MAX_INT4_SP00
                THEN
                    BEGIN
                    IF  MAX_LEVEL_BD00 = this_lno
                    THEN
                        avg_amount [this_lno, path] := maxindices [this_lno, path] + 1
                    ELSE
                        IF  MAX_INT4_SP00  = indices  [succ(this_lno), path]
                        THEN
                            avg_amount [this_lno, path] := maxindices [this_lno, path] + 1
                        ELSE
                            IF  (pnos [succ(this_lno), path] = fileRoot_gg00)
                                AND
                                (avg_amount [succ(this_lno), path] <= 6)
                                AND
                                (pnos [this_lno, 1] <> pnos [this_lno, 2])
                                AND
                                (pnos [this_lno, 2] <> pnos [this_lno, 3])
                            THEN
                                avg_amount [this_lno, path] := maxindices [this_lno, path] + 1
                            ELSE
                                (* hsNoTreeBalance_egg00 IN curr_tree_id.fileHandling_gg00*)
                                IF  ftsDynamic_egg00 IN curr_tree_id.fileType_gg00
                                THEN
                                    avg_amount [this_lno, path] :=
                                          ((FULLCOVERING_BD00 * 50 / 100)
                                          * (maxindices [this_lno, path] + 1))
                                          /coverings [this_lno, path]
                                ELSE
                                    avg_amount [this_lno, path] :=
                                          ((FULLCOVERING_BD00 * 80 / 100)
                                          * (maxindices [this_lno, path] + 1))
                                          /coverings [this_lno, path]
                                (*ENDIF*) 
                            (*ENDIF*) 
                        (*ENDIF*) 
                    (*ENDIF*) 
                    END;
&               ifdef TRACE
                (*ENDIF*) 
                t01p2int4 (bd_index, 'level:      ', this_lno
                      ,              'path:       ', path);
                t01int4   (bd_index, 'pno         ', pnos [this_lno, path]);
                t01p2int4 (bd_index, 'covering    ', coverings [this_lno, path]
                      ,              'maxindex    ', maxindices [this_lno, path]);
                t01int4   (bd_index, 'index       ', indices [this_lno, path]);
                t01real   (bd_index, 'avg_amount_1', avg_amount [this_lno, path]
                      , 7)
&                     endif
                END;
            (*ENDFOR*) 
            (* PTS 1104630 Alexander Kley *)
            (* IF  (pnos [succ(this_lno), path] = was changed into  : Alexander Kley 98\9\8 *)
            IF  (pnos [succ(this_lno), 3] =
                curr_tree_id.fileRoot_gg00)
                AND
                (avg_amount [succ(this_lno), 3] <= 3)
                AND
                (pnos [this_lno, 1] =  pnos [this_lno, 2])
            THEN
                IF  pnos [this_lno, 1] <> pnos [this_lno, 3]
                THEN
                    avg_amount [this_lno, 1] := (maxindices [this_lno, 1] +
                          maxindices [this_lno, 3] + 2) / 2.0
                ELSE
                    avg_amount [this_lno, 1] :=
                          ((FULLCOVERING_BD00 * 75 / 100)
                          * (maxindices [this_lno, 1] + 1))
                          /coverings [this_lno, 1]
                (*ENDIF*) 
            ELSE
                avg_amount [this_lno, 1] := (avg_amount [this_lno, 1]
                      +                      avg_amount [this_lno, 2]
                      +                      avg_amount [this_lno, 3]) / 3.0;
            (*ENDIF*) 
&           ifdef TRACE
            t01int4 (bd_index, 'level:      ', this_lno);
            t01real (bd_index, 'avg_amount_2', avg_amount [this_lno, 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 this_lno := sep_level DOWNTO 1 DO
            BEGIN
            left_page_cnt  [1] := left_page_cnt [1]  * avg_amount [this_lno, 1] + indices [this_lno, 1];
            IF  (left_page_cnt [3] = 0)
            THEN
                left_page_cnt [3] := indices [this_lno, 3]
            ELSE
                IF  (pnos[this_lno,1] <> pnos[this_lno,2])
                THEN
                    left_page_cnt [3] := (left_page_cnt [3] - 2) *  avg_amount [this_lno, 1] +
                          maxindices [this_lno,1] + 1 +
                          maxindices [this_lno,2] + 1 +
                          indices [this_lno, 3]
                ELSE
                    left_page_cnt [3] := (left_page_cnt [3] - 1) *  avg_amount [this_lno, 1] +
                          maxindices [this_lno,1] + 1 +
                          indices [this_lno, 3];
                (*ENDIF*) 
            (*ENDIF*) 
&           ifdef TRACE
            t01int4 (bd_index, '----- Level ', this_lno);
            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 this_lno := MAX_LEVEL_BD00 DOWNTO 1 DO
            BEGIN
            IF  (pnos[this_lno,1] <> NIL_PAGE_NO_GG00)
            THEN
                IF  (all_page_cnt_real < 1)
                THEN
                    all_page_cnt_real := maxindices [this_lno,1] + 1
                ELSE
                    IF  (pnos[this_lno,1] <> pnos[this_lno,2])
                    THEN
                        all_page_cnt_real := (all_page_cnt_real - 3) * avg_amount [this_lno, 1] +
                              maxindices [this_lno,1] + 1 +
                              maxindices [this_lno,2] + 1 +
                              maxindices [this_lno,3] + 1
                    ELSE
                        IF  (pnos[this_lno,1] <> pnos[this_lno,3])
                        THEN
                            all_page_cnt_real := (all_page_cnt_real - 2) * avg_amount [this_lno, 1] +
                                  maxindices [this_lno,1] + 1 +
                                  maxindices [this_lno,3] + 1
                        ELSE
                            all_page_cnt_real := (all_page_cnt_real - 1) * avg_amount [this_lno, 1] +
                                  maxindices [this_lno,1] + 1;
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
&           ifdef TRACE
            (*ENDIF*) 
            t01int4 (bd_index, '----- Level ', this_lno);
            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) (* PTS 1000771 *)
    THEN
        bd50count_records (current, start_key, stop_key, start_pno,
              start_leaf, stop_leaf, record_cnt, page_count);
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b50find_leaf (
            VAR sepkey        : tsp00_Key;
            KeyLen            : tsp00_Int4;
            lock_type         : tbd_treelock;
            node_req          : tbd_node_request;
            VAR subtree_info  : tbd_subtree_info;
            VAR left_estimate : tsp00_Int4;
            VAR rightestimate : tsp00_Int4;
            VAR index_pno     : tsp00_PageNo;
            VAR nptr          : tbd_node_ptrs;
            VAR neighbs       : tbd_neighbors;
            VAR current       : tbd_current_tree);
 
VAR
      found          : boolean;
      last           : boolean;
      node_release   : boolean;
      aux_release    : boolean;
      aux_err        : tgg00_BasisError;
      aux_request    : tbd_node_request;
      pRec           : tgg00_RecPtr;
      lno            : tsp00_Int2;
      amount         : integer;
      avg_amount     : integer;
      index          : integer;
      subroot_index  : integer;
      rec_pos        : tsp00_Int4;
      subroot        : tsp00_PageNo;
      left_subroot   : tsp00_PageNo;
      right_subroot  : tsp00_PageNo;
      left_neighbor  : tsp00_PageNo;
      right_neighbor : tsp00_PageNo;
      next           : tsp00_PageNo;
 
BEGIN
&ifdef TRACE
t01msgcheck ('b50find: illegal node_request ',
      ((node_req <> nr_return_if_leaf) AND
      ( node_req <> nr_ret_if_leaf_or_first_index)), LEAF_LEVEL_BD00);
t01int4 (bd_index, 'root        ', current.curr_tree_id.fileRoot_gg00);
&endif
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    subroot        := fileRoot_gg00;
    right_subroot  := NIL_PAGE_NO_GG00;
    right_neighbor := right_subroot;
    left_subroot   := NIL_PAGE_NO_GG00;
    left_neighbor  := left_subroot;
    WITH neighbs DO
        BEGIN
        ln := NIL_PAGE_NO_GG00;
        rn := NIL_PAGE_NO_GG00
        END;
    (*ENDWITH*) 
    found            := false;
    node_release     := false;
    lno              := LEAF_LEVEL_BD00;
    curr_lvl_1_pno   := NIL_PAGE_NO_GG00;
    curr_lvl_1_left  := NIL_PAGE_NO_GG00;
    curr_left_bound  := NIL_PAGE_NO_GG00;
    curr_right_bound := NIL_PAGE_NO_GG00;
    left_estimate    := 0;
    rightestimate    := 0;
    WITH subtree_info DO
        BEGIN
        sti_index_overflow  := false;
        sti_index_underflow := false;
        sti_boundary        := false
        END;
    (*ENDWITH*) 
    REPEAT
        IF  node_release
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  (lno = SECOND_INDEX_LEVEL_BD00)
            AND
            (ftsDynamic_egg00 IN curr_tree_id.fileType_gg00)
            AND
            g01glob.bd_subtree
        THEN
            BEGIN
            IF  (curr_lockstate <> no_bd_lock)
                AND
                ((lock_type = w_lock_leaf) OR
                ( lock_type = r_lock_leaf)  )
            THEN
                b75ilread_lock_index (current, subroot, 133);
            (*ENDIF*) 
            bd13GetNode (current, subroot, plmNoLock_ebd00,
                  nr_for_read, nptr);
            IF  trError_gg00 = e_ok
            THEN
                node_release := true
            (*ENDIF*) 
            END
        ELSE
            IF  lno = FIRST_INDEX_LEVEL_BD00
            THEN
                BEGIN
                IF  (curr_lockstate <> no_bd_lock)
                    AND
                    ((lock_type = w_lock_leaf) OR
                    ( lock_type = r_lock_leaf)  )
                THEN
                    BEGIN
                    IF  lock_type = w_lock_leaf
                    THEN
                        b75llwrite_lock_leaf (current, subroot, 134)
                    ELSE
                        IF  lock_type = r_lock_leaf
                        THEN
                            b75llread_lock_leaf (current, subroot, 135)
                        (*ENDIF*) 
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                bd13GetNode (current, subroot, plmNoLock_ebd00,
                      node_req, nptr);
                IF  trError_gg00 = e_ok
                THEN
                    node_release := true
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                IF  subroot = fileRoot_gg00
                THEN
                    BEGIN
                    IF  (curr_lockstate <> no_bd_lock) AND
                        (
                        (lock_type = w_lock_leaf ) OR
                        (lock_type = r_lock_leaf ) OR
                        (lock_type = w_lock_index)
                        )
                    THEN
                        BEGIN
                        IF  (ftsDynamic_egg00 IN fileType_gg00) AND g01glob.bd_subtree
                        THEN
                            bd13GetNode (current, subroot, plmNoLock_ebd00,
                                  nr_ret_if_leaf_or_first_index, nptr)
                        ELSE
                            bd13GetNode (current, subroot, plmNoLock_ebd00,
                                  nr_return_if_leaf, nptr)
                        (*ENDIF*) 
                        END
                    ELSE
                        bd13GetNode (current, subroot, plmNoLock_ebd00,
                              node_req, nptr);
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        node_release := true;
                    (*ENDIF*) 
                    IF  (trError_gg00 = e_root_is_leaf)
                        OR
                        (trError_gg00 = e_root_is_first_index)
                    THEN
                        BEGIN
                        aux_err      := trError_gg00;
                        trError_gg00 := e_ok;
                        IF  (ftsDynamic_egg00 IN fileType_gg00) AND g01glob.bd_subtree
                            AND
                            ((lock_type = w_lock_leaf) OR
                            ( lock_type = r_lock_leaf)  )
                        THEN
                            b75ilread_lock_index (current, subroot, 136);
                        (*ENDIF*) 
                        IF  aux_err = e_root_is_leaf
                        THEN
                            BEGIN
                            subtree_info.sti_boundary := true;(* PTS 1000436 *)
                            aux_release               := false;
                            aux_request               := node_req;
                            IF  lock_type = w_lock_leaf
                            THEN
                                b75llwrite_lock_leaf (current,subroot, 137)
                            ELSE
                                IF  lock_type = r_lock_leaf
                                THEN
                                    b75llread_lock_leaf (current,subroot, 138)
                                (*ENDIF*) 
                            (*ENDIF*) 
                            END
                        ELSE (* e_root_is_first_index *)
                            BEGIN
                            aux_release := true;
                            aux_request := nr_for_read
                            END;
                        (*ENDIF*) 
                        bd13GetNode (current, subroot, plmNoLock_ebd00,
                              aux_request, nptr);
                        IF  trError_gg00 = e_ok
                        THEN
                            node_release := aux_release
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                ELSE (* subroot <> fileRoot_gg00 *)
                    BEGIN
                    bd13GetNode (current, subroot, plmNoLock_ebd00,
                          nr_for_read, nptr);
                    IF  trError_gg00 = e_ok
                    THEN
                        node_release := true
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  nptr.np_ptr^.nd_level = LEAF_LEVEL_BD00
            THEN
                BEGIN
                node_release := false;
                found        := true;
                IF  (ftsPerm_egg00 IN fileType_gg00)
                    AND
                    (nptr.np_ptr^.nd_right <> right_neighbor)
                THEN
                    BEGIN
                    IF  NOT
                        ((nptr.np_ptr^.nd_id = curr_right_bound)
                        AND
                        (ftsDynamic_egg00 IN curr_tree_id.fileType_gg00))
                    THEN
                        BEGIN
                        (* PTS 1107109 TS 2000-07-18 *)
                        g01opmsg (sp3p_knldiag, sp3m_error,
                              csp3_b50_2_invalid_structure, csp3_n_btree,
                              'invalid index structure ', right_neighbor);
                        b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                              nptr.np_ptr^.nd_id, nptr.np_ptr, 1);
                        trError_gg00 := e_invalid_leaves_structure;
                        (* PTS 1107109 *)
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                lno  := nptr.np_ptr^.nd_level;
                next := nptr.np_ptr^.nd_right;
                IF  (ftsPerm_egg00 IN fileType_gg00) AND (next <> right_neighbor)
                THEN
                    BEGIN
                    (* PTS 1107109 TS 2000-07-18 *)
                    g01opmsg (sp3p_knldiag, sp3m_error,
                          csp3_b50_2_invalid_structure, csp3_n_btree,
                          'invalid index structure ', right_neighbor);
                    b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                          nptr.np_ptr^.nd_id, nptr.np_ptr, 1);
                    trError_gg00 := e_invalid_index_structure;
                    (* PTS 1107109 *)
                    END;
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    bd51SearchBranch (current, @sepkey, KeyLen, nptr.np_ptr, index );
                    subroot_index := index;
                    WITH nptr.np_ptr^ DO
                        BEGIN
                        (* average amount of records *)
                        (* in pages of this index level *)
                        WITH nptr.np_ptr^ DO
                            IF  ftsDynamic_egg00 IN curr_tree_id.fileType_gg00
                            THEN
                                avg_amount := ((FULLCOVERING_BD00*50 DIV 100)*
                                      nd_record_cnt*POINTERSIZE_BD00) DIV
                                      (POINTERSIZE_BD00*
                                      (nd_bottom - BODY_BEG_BD00 + nd_record_cnt*POINTERSIZE_BD00))
                            ELSE
                                avg_amount := ((FULLCOVERING_BD00*80 DIV 100)*
                                      nd_record_cnt*POINTERSIZE_BD00) DIV
                                      (POINTERSIZE_BD00*
                                      (nd_bottom - BODY_BEG_BD00 + nd_record_cnt*POINTERSIZE_BD00));
                            (*ENDIF*) 
                        (*ENDWITH*) 
                        rightestimate := rightestimate*avg_amount + (nd_record_cnt - 1) - index;
                        left_estimate := left_estimate*avg_amount + index;
                        rec_pos       := nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
                        pRec          := @nd_body [rec_pos];
                        END;
                    (*ENDWITH*) 
                    IF  (rec_pos < BODY_BEG_BD00) OR (rec_pos > nptr.np_ptr^.nd_bottom)
                    THEN
                        BEGIN
                        trError_gg00 := e_data_page_corrupted;
                        b06dump_bad_page (trTaskId_gg00, 'd',
                              FILE_EXT_COR_BD00, nptr.np_ptr^.nd_id,
                              nptr.np_ptr, 1);
                        g01opmsg (sp3p_knldiag, sp3m_error,
                              bd50c5IllegalEntryPos_csp03, csp3_n_btree,
                              'Illegal entry pos       ', rec_pos);
                        b06write_filename_and_root (curr_tree_id)
                        END
                    ELSE
                        BEGIN
                        subroot := gg06PnoGet (pRec^.recPno_gg00);
                        IF  ftsPerm_egg00 IN fileType_gg00
                        THEN
                            BEGIN
                            b51next_branch (nptr.np_ptr, index, last);
                            IF  last
                            THEN
                                bd50get_right_subtree (current, nptr, index,
                                      right_neighbor, right_subroot)
                            ELSE (*  NOT last *)
                                BEGIN
                                WITH nptr.np_ptr^ DO
                                    BEGIN
                                    rec_pos := nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
                                    pRec    := @nd_body [rec_pos]
                                    END;
                                (*ENDWITH*) 
                                IF  (rec_pos < BODY_BEG_BD00) OR (rec_pos > nptr.np_ptr^.nd_bottom)
                                THEN
                                    BEGIN
                                    trError_gg00 := e_data_page_corrupted;
                                    b06dump_bad_page (trTaskId_gg00, 'd',
                                          FILE_EXT_COR_BD00,
                                          nptr.np_ptr^.nd_id,  nptr.np_ptr, 1);
                                    g01opmsg (sp3p_knldiag, sp3m_error,
                                          bd50c6IllegalEntryPos_csp03, csp3_n_btree,
                                          'Illegal entry pos       ', rec_pos);
                                    b06write_filename_and_root (curr_tree_id)
                                    END
                                ELSE
                                    BEGIN
                                    amount        := 3 * pRec^.recLen_gg00;
                                    right_subroot := gg06PnoGet (pRec^.recPno_gg00);
                                    IF  (nptr.np_ptr^.nd_level = FIRST_INDEX_LEVEL_BD00)
                                        AND
                                        (nptr.np_ptr^.nd_bottom + amount < MAX_BOTTOM_BD00)
                                    THEN
                                        BEGIN
                                        curr_lvl_1_pno  := nptr.np_ptr^.nd_id;
                                        curr_lvl_1_left := left_neighbor
                                        END
                                    (*ENDIF*) 
                                    END
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  (trError_gg00 = e_ok)
                        AND
                        (lno = FIRST_INDEX_LEVEL_BD00)
                        AND
                        ((ftsDynamic_egg00 IN fileType_gg00)          OR
                        ( curr_action      = m_create_index_parallel) OR
                        ( curr_action      = m_create_index)           )
                    THEN
                        BEGIN
                        (* DANGER: Use curr_lvl_1_locked only in    *)
                        (* context with dynamic trees, because      *)
                        (* curr_lvl_1_locked is responsible (!)     *)
                        (* for BD-LOCKS!!!!!!!                      *)
                        (* curr_lvl_1_locked := nptr.np_ptr^.nd_id  *)
                        (* IS WRONG!                                *)
                        index_pno := nptr.np_ptr^.nd_id;
                        bd50determine_subtree_info (nptr, subroot,
                              subroot_index, nptr.np_ptr^.nd_record_cnt - 1, current,
                              subtree_info)
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        right_neighbor := right_subroot;
                        b50get_left_subtree (nptr,
                              subroot_index, left_neighbor,
                              left_subroot, current);
                        IF  trError_gg00 = e_ok
                        THEN
                            left_neighbor := left_subroot
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
    UNTIL
        found OR (trError_gg00 <> e_ok);
    (*ENDREPEAT*) 
    IF  found
    THEN
        WITH neighbs DO
            BEGIN
            ln := left_neighbor;
            rn := right_neighbor;
&           ifdef TRACE
            t01p2int4 (bd_index, 'leaf        ', nptr.np_ptr^.nd_id
                  ,              'right       ', rn);
            t01int4   (bd_index, 'left        ', ln);
            IF  curr_lvl_1_pno <> NIL_PAGE_NO_GG00
            THEN
                BEGIN
                t01p2int4 (bd_index, 'lvl_1_pno   ', curr_lvl_1_pno
                      ,              'lvl_1_left  ', curr_lvl_1_left);
                END;
            (*ENDIF*) 
            IF  curr_lvl_1_locked <> NIL_PAGE_NO_GG00
            THEN
                BEGIN
                t01int4   (bd_index, 'lvl_1_locked', curr_lvl_1_locked);
                t01p2int4 (bd_index, 'curr_left_bo', curr_left_bound
                      ,              'curr_right_b', curr_right_bound)
                END
&           endif
            (*ENDIF*) 
            END
        (*ENDWITH*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b50first_leaf (
            VAR firstleaf : tsp00_PageNo;
            lock_type   : tbd_treelock;
            VAR single  : boolean;
            VAR current : tbd_current_tree);
 
VAR
      aux_err  : tgg00_BasisError;
      found    : boolean;
      lno      : tsp00_Int2;
      index    : integer;
      nptr     : tbd_node_ptrs;
 
BEGIN
nptr.np_ptr   := NIL;
nptr.np_cbptr := NIL;
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    trError_gg00     := e_ok;
    single           := false;
    found            := false;
    lno              := LEAF_LEVEL_BD00;
    firstleaf        := fileRoot_gg00;
    curr_left_bound  := NIL_PAGE_NO_GG00;
    curr_right_bound := NIL_PAGE_NO_GG00;
&   ifdef TRACE
    t01int4 (bd_index, 'root        ', fileRoot_gg00);
&   endif
    IF  firstleaf <> NIL_PAGE_NO_GG00
    THEN
        REPEAT
            IF  firstleaf = fileRoot_gg00
            THEN
                BEGIN
                IF  (curr_lockstate <> no_bd_lock)
                    AND
                    ((lock_type = w_lock_leaf) OR
                    ( lock_type = r_lock_leaf))
                THEN
                    BEGIN
                    IF  (ftsDynamic_egg00 IN curr_tree_id.fileType_gg00) AND
                        g01glob.bd_subtree
                    THEN
                        bd13GetNode (current, firstleaf, plmNoLock_ebd00,
                              nr_ret_if_leaf_or_first_index, nptr)
                    ELSE
                        bd13GetNode (current, firstleaf, plmNoLock_ebd00,
                              nr_return_if_leaf, nptr)
                    (*ENDIF*) 
                    END
                ELSE
                    bd13GetNode (current, firstleaf, plmNoLock_ebd00,
                          nr_for_read, nptr);
                (*ENDIF*) 
                IF  (trError_gg00 = e_root_is_leaf)
                    OR
                    (trError_gg00 = e_root_is_first_index)
                THEN
                    BEGIN
&                   ifdef TRACE
                    t01msgcheck ('b50firs: nptr <> NIL          ',
                          nptr.np_ptr = NIL, 0);
&                   endif
                    aux_err      := trError_gg00;
                    trError_gg00 := e_ok;
                    IF  (ftsDynamic_egg00 IN curr_tree_id.fileType_gg00) AND
                        g01glob.bd_subtree
                    THEN
                        b75ilread_lock_index (current, firstleaf, 139);
                    (*ENDIF*) 
                    IF  aux_err = e_root_is_leaf
                    THEN
                        BEGIN
                        IF  lock_type = w_lock_leaf
                        THEN
                            b75llwrite_lock_leaf (current, firstleaf, 140)
                        ELSE
                            b75llread_lock_leaf (current, firstleaf, 141)
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    bd13GetNode (current, firstleaf, plmNoLock_ebd00,
                          nr_for_read, nptr)
                    END
                (*ENDIF*) 
                END
            ELSE
                bd13GetNode (current, firstleaf, plmNoLock_ebd00,
                      nr_for_read, nptr);
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                lno := nptr.np_ptr^.nd_level;
&               ifdef TRACE
                t01int4 (bd_index, 'level       ', lno);
&               endif
                IF  lno = LEAF_LEVEL_BD00
                THEN
                    BEGIN
                    found  := true;
                    single := (nptr.np_ptr^.nd_right = NIL_PAGE_NO_GG00)
                    END
                ELSE
                    BEGIN
                    index     := FIRST_REC_INDEX_BD00;
                    firstleaf := bd52SubtreePno (nptr.np_ptr, index);
                    IF  (lno = SECOND_INDEX_LEVEL_BD00)                  AND
                        (ftsDynamic_egg00 IN curr_tree_id.fileType_gg00) AND
                        g01glob.bd_subtree
                    THEN
                        BEGIN
                        IF  (curr_lockstate <> no_bd_lock)
                            AND
                            ((lock_type = w_lock_leaf) OR
                            (lock_type = r_lock_leaf))
                        THEN
                            b75ilread_lock_index (current, firstleaf, 142);
                        (*ENDIF*) 
                        END
                    ELSE
                        IF  lno = FIRST_INDEX_LEVEL_BD00
                        THEN
                            BEGIN
                            IF  (curr_lockstate <> no_bd_lock)
                                AND
                                ((lock_type = w_lock_leaf) OR
                                (lock_type = r_lock_leaf))
                            THEN
                                BEGIN
                                IF  lock_type = w_lock_leaf
                                THEN
                                    b75llwrite_lock_leaf (current,
                                          firstleaf, 143)
                                ELSE
                                    IF  lock_type = r_lock_leaf
                                    THEN
                                        b75llread_lock_leaf (current,
                                              firstleaf, 144)
                                    (*ENDIF*) 
                                (*ENDIF*) 
                                END;
                            (*ENDIF*) 
                            WITH nptr, np_ptr^ DO
                                BEGIN
                                IF  NOT (bd_write_acc IN fileBdUse_gg00)
                                THEN
                                    curr_lvl_1_pno  := nd_id;
                                (*ENDIF*) 
                                curr_left_bound  := bd52SubtreePno (np_ptr, FIRST_REC_INDEX_BD00);
                                curr_right_bound := bd52SubtreePno (np_ptr, nd_record_cnt - 1);
&                               ifdef TRACE
                                IF  t01trace (bd_index)
                                THEN
                                    BEGIN
                                    t01int4   (bd_index, 'curr_lvl1_lo',
                                          curr_lvl_1_locked);
                                    t01p2int4 (bd_index, 'curr_left_bo',
                                          curr_left_bound,
                                          'curr_right_b',
                                          curr_right_bound)
                                    END;
&                               endif
                                (*ENDIF*) 
                                END;
                            (*ENDWITH*) 
                            found := true
                            END
                        (*ENDIF*) 
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                b13r_release_node (nptr, current, lru_normal);
            (*ENDIF*) 
        UNTIL
            found OR (trError_gg00 <> e_ok)
        (*ENDREPEAT*) 
    (*ENDIF*) 
    END;
(*ENDWITH*) 
IF  nptr.np_ptr <> NIL
THEN
    b13r_release_node (nptr, current, lru_normal)
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b50get_left_subtree (
            VAR nptr         : tbd_node_ptrs;
            VAR index        : integer;
            left_neighbor    : tsp00_PageNo;
            VAR left_subroot : tsp00_PageNo;
            VAR current      : tbd_current_tree);
 
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  index = FIRST_REC_INDEX_BD00
    THEN
        BEGIN
        IF  (left_neighbor = NIL_PAGE_NO_GG00)
            OR
            ((nptr.np_ptr^.nd_level = FIRST_INDEX_LEVEL_BD00)   AND
            (ftsDynamic_egg00 IN curr_tree_id.fileType_gg00) AND
            ((curr_lockstate <> w_lock_tree) AND
            (curr_lockstate  <> d_lock_tree) AND
            (curr_lockstate  <> s_lock_tree) AND
            (curr_lockstate  <> no_bd_lock))
            AND
            g01glob.bd_subtree)
        THEN
            left_subroot := NIL_PAGE_NO_GG00
        ELSE
            BEGIN
            bd13GetNode (current, left_neighbor, plmNoLock_ebd00,
                  nr_for_read, nnptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  nnptr.np_ptr^.nd_level = succ(LEAF_LEVEL_BD00)
                THEN
                    current.curr_lvl_1_pno := NIL_PAGE_NO_GG00;
                (*ENDIF*) 
                index        := nnptr.np_ptr^.nd_record_cnt - 1;
                left_subroot := bd52SubtreePno (nnptr.np_ptr, index)
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    ELSE (*  not first *)
        BEGIN
        index        := index - 1;
        left_subroot := bd52SubtreePno (nptr.np_ptr, index)
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
IF  nnptr.np_ptr <> NIL
THEN
    b13r_release_node (nnptr, current, lru_normal)
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b50position_leaf (
            leafpos           : tsp00_Int4;
            leafnodes         : tsp00_Int4;
            VAR left_estimate : tsp00_Int4;
            VAR rightestimate : tsp00_Int4;
            VAR nptr          : tbd_node_ptrs;
            VAR current       : tbd_current_tree);
 
VAR
      found        : boolean;
      node_release : boolean;
      aux_err      : tgg00_BasisError;
      pRec         : tgg00_RecPtr;
      lno          : tsp00_Int2;
      index        : integer;
      amount       : integer;
      pos          : integer;
      subroot      : tsp00_PageNo;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    subroot          := fileRoot_gg00;
    found            := false;
    node_release     := false;
    lno              := LEAF_LEVEL_BD00;
    curr_lvl_1_pno   := NIL_PAGE_NO_GG00;
    curr_lvl_1_left  := NIL_PAGE_NO_GG00;
    curr_left_bound  := NIL_PAGE_NO_GG00;
    curr_right_bound := NIL_PAGE_NO_GG00;
    left_estimate    := 0;
    rightestimate    := 0;
    REPEAT
        IF  node_release
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  (lno = SECOND_INDEX_LEVEL_BD00)
            AND
            (ftsDynamic_egg00 IN curr_tree_id.fileType_gg00)
            AND
            g01glob.bd_subtree
        THEN
            BEGIN
            IF  (curr_lockstate <> no_bd_lock)
            THEN
                b75ilread_lock_index (current, subroot, 145);
            (*ENDIF*) 
            bd13GetNode (current, subroot, plmNoLock_ebd00,
                  nr_for_read, nptr);
            IF  trError_gg00 = e_ok
            THEN
                node_release := true
            (*ENDIF*) 
            END
        ELSE
            IF  lno = FIRST_INDEX_LEVEL_BD00
            THEN
                BEGIN
                IF  curr_lockstate <> no_bd_lock
                THEN
                    b75llread_lock_leaf (current, subroot, 146);
                (*ENDIF*) 
                bd13GetNode (current, subroot, plmNoLock_ebd00,
                      nr_for_read, nptr);
                IF  trError_gg00 = e_ok
                THEN
                    node_release := true
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                IF  subroot = fileRoot_gg00
                THEN
                    BEGIN
                    IF  curr_lockstate <> no_bd_lock
                    THEN
                        BEGIN
                        IF  (ftsDynamic_egg00 IN fileType_gg00)
                            AND
                            g01glob.bd_subtree
                        THEN
                            bd13GetNode (current, subroot, plmNoLock_ebd00,
                                  nr_ret_if_leaf_or_first_index, nptr)
                        ELSE
                            bd13GetNode (current, subroot, plmNoLock_ebd00,
                                  nr_return_if_leaf, nptr)
                        (*ENDIF*) 
                        END
                    ELSE
                        bd13GetNode (current, subroot, plmNoLock_ebd00,
                              nr_for_read, nptr);
                    (*ENDIF*) 
                    IF  (trError_gg00 = e_root_is_leaf)
                        OR
                        (trError_gg00 = e_root_is_first_index)
                    THEN
                        BEGIN
&                       ifdef TRACE
                        t01msgcheck ('b50posi: nptr <> NIL          ',
                              nptr.np_ptr = NIL, 0);
&                       endif
                        aux_err      := trError_gg00;
                        trError_gg00 := e_ok;
                        IF  (ftsDynamic_egg00 IN fileType_gg00)
                            AND
                            g01glob.bd_subtree
                        THEN
                            b75ilread_lock_index (current, subroot, 147);
                        (*ENDIF*) 
                        IF  aux_err = e_root_is_leaf
                        THEN
                            b75llread_lock_leaf (current, subroot, 148);
                        (*ENDIF*) 
                        bd13GetNode (current, subroot, plmNoLock_ebd00,
                              nr_for_read, nptr);
                        IF  (aux_err = e_root_is_first_index)
                        THEN
                            node_release := true;
                        (*ENDIF*) 
                        END
                    ELSE
                        IF  trError_gg00 = e_ok
                        THEN
                            node_release := true;
                        (*ENDIF*) 
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    bd13GetNode (current, subroot, plmNoLock_ebd00,
                          nr_for_read, nptr);
                    IF  trError_gg00 = e_ok
                    THEN
                        node_release := true
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  nptr.np_ptr^.nd_level = LEAF_LEVEL_BD00
            THEN
                BEGIN
                node_release := false;
                found        := true;
                END
            ELSE
                BEGIN
                lno := nptr.np_ptr^.nd_level;
                IF  leafnodes < 1
                THEN
                    leafnodes := 1;
                (*ENDIF*) 
                IF  leafpos <  0
                THEN
                    leafpos := 0;
                (*ENDIF*) 
                IF  leafnodes < leafpos
                THEN
                    leafpos := leafnodes;
                (*ENDIF*) 
                amount   := nptr.np_ptr^.nd_record_cnt;
                index    := ((amount -1) * leafpos) DIV leafnodes;
&               ifdef TRACE
                t01msgcheck ('b50position_: index > maxindex',
                      index <= nptr.np_ptr^.nd_record_cnt - 1, index);
&               endif
                pos           := amount DIV 2;
                leafpos       := leafpos - (index*leafnodes+pos) DIV amount;
                leafnodes     := (leafnodes + pos) DIV amount;
                rightestimate := rightestimate * amount + (nptr.np_ptr^.nd_record_cnt - 1) - index;
                left_estimate := left_estimate * amount + index;
                pos           :=  nptr.np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
                pRec          := @nptr.np_ptr^.nd_body [pos];
                IF  (pos < BODY_BEG_BD00) OR (pos > nptr.np_ptr^.nd_bottom)
                THEN
                    BEGIN
                    trError_gg00 := e_data_page_corrupted;
                    b06dump_bad_page (trTaskId_gg00, 'd',
                          FILE_EXT_COR_BD00, nptr.np_ptr^.nd_id, nptr.np_ptr, 1);
                    g01opmsg (sp3p_knldiag, sp3m_error,
                          bd50c7IllegalEntryPos_csp03, csp3_n_btree,
                          'Illegal entry pos       ', pos);
                    b06write_filename_and_root (curr_tree_id)
                    END
                ELSE
                    BEGIN
                    subroot := gg06PnoGet (pRec^.recPno_gg00);
                    IF  (lno = FIRST_INDEX_LEVEL_BD00)
                        AND
                        (ftsDynamic_egg00 IN fileType_gg00)
                        AND
                        g01glob.bd_subtree
                    THEN
                        BEGIN
                        curr_left_bound  := bd52SubtreePno (nptr.np_ptr, FIRST_REC_INDEX_BD00);
                        curr_right_bound := bd52SubtreePno (nptr.np_ptr, nptr.np_ptr^.nd_record_cnt - 1)
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
    UNTIL
        found OR (trError_gg00 <> e_ok);
    (*ENDREPEAT*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b50release_subtree (
            subroot        : tsp00_PageNo;
            stringcol_cnt  : integer;
            varcol_cnt_off : integer;
            only_empty     : boolean;
            VAR current    : tbd_current_tree);
 
VAR
      last         : boolean;
      aux_error    : tgg00_BasisError;
      lno          : tsp00_Int2;
      index        : integer;
      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
    (* PTS 1001034 Torsten Strahl 1998-05-12 *)
    bd13GetNode (current, subroot, plmNoLock_ebd00,
          nr_for_read, nptr);
    (* PTS 1001034 *)
    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
        lno := nptr.np_ptr^.nd_level;
        IF  lno = LEAF_LEVEL_BD00
        THEN
            BEGIN
            IF  stringcol_cnt > 0
            THEN
                bd50drop_long (curr_trans^, nptr.np_ptr,
                      stringcol_cnt, varcol_cnt_off);
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  only_empty AND (subroot = fileRoot_gg00)
                THEN
                    BEGIN
                    b13r_release_node (nptr, current, lru_normal);
                    bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00,
                          nr_for_update, nptr);
                    IF  trError_gg00 = e_ok
                    THEN
                        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*) 
                    END
                ELSE
                    b13free_node (nptr, current)
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        ELSE
            (*  lno > 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
                    (stringcol_cnt = 0                ) AND
                    (lno = FIRST_INDEX_LEVEL_BD00)
                THEN
                    b13pfree_pno (next_subroot, current)
                ELSE
                    b50release_subtree (next_subroot, stringcol_cnt,
                          varcol_cnt_off, only_empty, 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  only_empty AND (nptr.np_ptr^.nd_id = fileRoot_gg00)
                THEN
                    BEGIN
                    b13r_release_node (nptr, current, lru_normal);
                    bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00,
                          nr_for_update, nptr);
                    IF  trError_gg00 = e_ok
                    THEN
                        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*) 
                    END
                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
      b50reorg_treeindex (
            VAR rk         : tgg00_Lkey;
            stringcol_cnt  : integer;
            varcol_cnt_off : integer;
            VAR current    : tbd_current_tree);
 
VAR
      single            : boolean;
      create_tree_index : boolean;
      firstleaf         : tsp00_PageNo;
 
BEGIN
single            := false;
create_tree_index := true;
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    b50first_leaf (firstleaf, w_lock_tree, single, current);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  NOT single
        THEN
            bd50trelease_treeindex (current, fileRoot_gg00);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            bd50trunc_tree (current, firstleaf, stringcol_cnt,
                  varcol_cnt_off, rk, create_tree_index);
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND create_tree_index
        THEN
            bd50establish_treeindex (firstleaf, current);
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b50verify_subtree (root : tsp00_PageNo;
            right           : tsp00_PageNo;
            conv_update     : boolean;
            VAR dump_parent : boolean;
            VAR current     : tbd_current_tree;
            VAR NumPages    : tsp00_Int4);
 
VAR
      last          : boolean;
      index         : integer;
      lno           : integer;
      right_index   : integer;
      nptr          : tbd_node_ptrs;
      right_subroot : tsp00_PageNo;
      subroot       : tsp00_PageNo;
 
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
        bd13GetNode (current, root, plmNoLock_ebd00,
              nr_for_read, nptr);
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        lno := nptr.np_ptr^.nd_level;
        IF  lno = LEAF_LEVEL_BD00
        THEN
            BEGIN
            IF  right <> nptr.np_ptr^.nd_right
            THEN
                BEGIN
                trError_gg00 := e_invalid_leaves_structure;
                dump_parent    := true;
                g01opmsg (sp3p_knldiag, sp3m_error,
                      csp3_b50_1_invalid_structure, csp3_n_btree,
                      'invalid leaves structure', nptr.np_ptr^.nd_id);
                b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                      nptr.np_ptr^.nd_id, nptr.np_ptr, 1)
                END
            ELSE
                bd50_CheckEntry (nptr, dump_parent, current);
            (*ENDIF*) 
            END
        ELSE (*  lno > leaflevel *)
            IF  right <> nptr.np_ptr^.nd_right
            THEN
                BEGIN
                trError_gg00 := e_invalid_index_structure;
                dump_parent  := true;
                g01opmsg (sp3p_knldiag, sp3m_error,
                      csp3_b50_2_invalid_structure, csp3_n_btree,
                      'invalid index structure ', nptr.np_ptr^.nd_id);
                b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                      nptr.np_ptr^.nd_id, nptr.np_ptr, 1);
                END
            ELSE
                BEGIN
                index := FIRST_REC_INDEX_BD00;
                last  := false;
                REPEAT
                    subroot     := bd52SubtreePno (nptr.np_ptr, index);
                    right_index := index;
                    bd50get_right_subtree (current, nptr, right_index,
                          right, right_subroot);
                    IF  trError_gg00 = e_ok
                    THEN
                        b50verify_subtree (subroot, right_subroot,
                              conv_update, dump_parent, current, NumPages);
                    (*ENDIF*) 
                    IF  dump_parent
                    THEN
                        BEGIN
                        (* trError_gg00 = e_invalid_index_structure OR *)
                        (* trError_gg00 = e_invalid_leaves_structure   *)
                        dump_parent := false;
                        g01opmsg (sp3p_knldiag, sp3m_error,
                              csp3_b50_3_invalid_structure, csp3_n_btree,
                              'parent node is          ', nptr.np_ptr^.nd_id);
                        b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                              nptr.np_ptr^.nd_id, nptr.np_ptr, 1)
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        b51next_branch (nptr.np_ptr, index, last)
                    (*ENDIF*) 
                UNTIL
                    last OR (trError_gg00 <> e_ok)
                (*ENDREPEAT*) 
                END
            (*ENDIF*) 
        (*ENDIF*) 
        END
    ELSE (* trError_gg00 <> e_ok *)
        IF  (root = curr_tree_id.fileRoot_gg00) AND
            (NOT conv_update                  ) AND
            (
            (trError_gg00 = e_invalid_root      ) OR
            (trError_gg00 = e_page_in_wrong_tree)
            )
        THEN
            trError_gg00 := e_ok;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        NumPages := succ (NumPages);
        IF  conv_update
        THEN
            b10use_pno (curr_trans^, root);
        (*ENDIF*) 
        END;
    (*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);
 
CONST
      c_max_scan_index_nodes = 1;
 
VAR
      incl_first_read_index  : boolean;
      no_more_subtree        : boolean;
      use_subtree_lock       : boolean;
      result                 : tbd_searchresult;
      index                  : integer;
      pos                    : integer;
      scaned_nodes           : integer;
      sub_info               : tbd_subtree_info;
      dummy                  : tsp00_Int4;
      index_pno              : tsp00_PageNo;
      old_right_bound        : tsp00_PageNo;
      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;
    IF  (ftsConcurrent_egg00 IN fileType_gg00 ) AND (curr_lockstate = no_bd_lock)
    THEN
        b75tlread_lock_tree (PrimCurrent, 195);
    (*ENDIF*) 
    sub_info.sti_is_del_op := false;
    index_pno              := NIL_PAGE_NO_GG00;
    old_right_bound        := NIL_PAGE_NO_GG00;
    scaned_nodes           := 0;
    NumLeavesToScan        := 0;
    AvgRecordsPerLeaf      := 0;
    incl_first_read_index  := true;
    use_subtree_lock       := ((ftsDynamic_egg00 IN fileType_gg00) AND
          (curr_lockstate <> no_bd_lock) AND g01glob.bd_subtree);
    (* *)
    IF  trError_gg00 = e_ok
    THEN
        b50find_leaf (StopPrimKey, StopPrimKeyLen, r_lock_leaf, nr_for_read,
              sub_info, dummy, dummy, index_pno, nptrs, neighbors, PrimCurrent);
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        b31search_entry (PrimCurrent, StopPrimKey, StopPrimKeyLen,
              nptrs.np_ptr, index, result);
        IF  trError_gg00 = e_ok
        THEN
            CASE result OF
                lastfound, thisfound:
                    BEGIN
                    IF  nptrs.np_ptr^.nd_id = curr_right_bound
                    THEN
                        old_right_bound := nptrs.np_ptr^.nd_id;
                    (* *)
                    (*ENDIF*) 
                    b31next_search (RELEASE_FRAME_BD00, nptrs, index, PrimCurrent);
                    IF  ((old_right_bound <> NIL_PAGE_NO_GG00  ) AND
                        (old_right_bound  <> nptrs.np_ptr^.nd_id))
                    THEN
                        incl_first_read_index := false
                    (*ENDIF*) 
                    END;
                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  (pos < BODY_BEG_BD00) OR (pos > nd_bottom)
                THEN
                    BEGIN
                    trError_gg00 := e_illegal_entrypos;
                    b06dump_bad_page (trTaskId_gg00, 'd',
                          FILE_EXT_COR_BD00, nd_id, np_ptr, 1);
                    g01opmsg (sp3p_knldiag, sp3m_error,
                          csp03_b50_2_illegal_entrypos, csp3_n_btree,
                          'Illegal entry pos       ', pos);
                    b06write_filename_and_root (curr_tree_id)
                    END;
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    pRec            := @nd_body [pos];
                    StartPrimKeyLen := pRec^.recKey_gg00.keyLen_gg00;
                    g10mv3 ('VBD50 ',   1,    
                          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);
        (* *)
        (* concurrent AND dynamic     -> lockstate = r_lock_leaf *)
        (* concurrent AND not dynamic -> lockstate = r_lock_leaf *)
        (* *)
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            REPEAT
                bd13GetNode (PrimCurrent, index_pno, plmNoLock_ebd00,
                      nr_for_read, nptrs);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    index_pno       := nptrs.np_ptr^.nd_right;
                    no_more_subtree := (index_pno = NIL_PAGE_NO_GG00);
                    IF  incl_first_read_index
                    THEN
                        BEGIN
                        scaned_nodes    := succ (scaned_nodes);
                        NumLeavesToScan := NumLeavesToScan + nptrs.np_ptr^.nd_record_cnt
                        END
                    ELSE
                        incl_first_read_index := true;
                    (*ENDIF*) 
                    IF  (scaned_nodes = c_max_scan_index_nodes) OR
                        (no_more_subtree                      )
                    THEN
                        BEGIN
                        curr_left_bound  := bd52SubtreePno (nptrs.np_ptr, FIRST_REC_INDEX_BD00);
                        curr_right_bound := bd52SubtreePno (nptrs.np_ptr, nptrs.np_ptr^.nd_record_cnt - 1);
                        END
                    ELSE
                        BEGIN
                        b13r_release_node (nptrs, PrimCurrent, lru_normal);
                        IF  use_subtree_lock
                        THEN
                            BEGIN
                            b75reset_lock (PrimCurrent, curr_node_locked);
                            b75ilread_lock_index (PrimCurrent, index_pno, 78)
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            UNTIL
                (trError_gg00 <> e_ok                  ) OR
                (scaned_nodes >= c_max_scan_index_nodes) OR
                (no_more_subtree                       );
            (*ENDREPEAT*) 
            IF  nptrs.np_ptr <> NIL
            THEN
                b13r_release_node (nptrs, PrimCurrent, lru_normal);
            (* *)
            (* conrurrent AND dynamic     -> lockstate = r_lock_index *)
            (* conrurrent AND not dynamic -> lockstate = r_lock_leaf  *)
            (* *)
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (curr_lockstate <> no_bd_lock)
        THEN
            BEGIN
            CASE curr_lockstate OF
                r_lock_index :
                    b75llread_lock_leaf (PrimCurrent, curr_right_bound, 196);
                r_lock_leaf  :
                    b75lulread_unlocklock_leaf (PrimCurrent,
                          curr_node_locked, curr_lvl_1_locked,
                          curr_right_bound, curr_lvl_1_locked, 196);
                OTHERWISE
                    ;
                END
            (*ENDCASE*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
&           ifdef TRACE
            t01int4 (bd_idx_create, 'Stop Leaf   ', curr_right_bound);
&           endif
            bd13GetNode (PrimCurrent, curr_right_bound, plmNoLock_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  (pos < BODY_BEG_BD00) OR (pos > nd_bottom)
                    THEN
                        BEGIN
                        trError_gg00 := e_illegal_entrypos;
                        b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1);
                        g01opmsg (sp3p_knldiag, sp3m_error,
                              csp03_b50_3_illegal_entrypos, csp3_n_btree,
                              'Illegal entry pos       ', pos);
                        b06write_filename_and_root (curr_tree_id)
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        pRec           := @nd_body [pos];
                        StopPrimKeyLen := pRec^.recKey_gg00.keyLen_gg00;
                        g10mv3 ('VBD50 ',   2,    
                              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*) 
    CASE  curr_lockstate  OF
        r_lock_leaf :
            b75luread_unlock_leaf (PrimCurrent, curr_node_locked);
        r_lock_index :
            b75iuread_unlock_index (PrimCurrent, curr_lvl_1_locked);
        r_lock_tree :
            b75turead_unlock_tree (PrimCurrent);
        OTHERWISE
            ;
        END
    (*ENDCASE*) 
    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;
            nptr         : tbd_nodeptr;
            VAR recIndex : tsp00_Int4;
            VAR leaf     : tsp00_PageNo);
 
VAR
      recPosition : tsp00_Int4;
      pRec        : tgg00_RecPtr;
 
BEGIN
bd51SearchBranch (current, pSepKey, keyLen, nptr, recIndex);
WITH current, curr_trans^ DO
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        recPosition := nptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - recIndex];
        IF  (recPosition < BODY_BEG_BD00) OR (recPosition > nptr^.nd_bottom)
        THEN
            BEGIN
            trError_gg00 := e_data_page_corrupted;
            b06dump_bad_page (trTaskId_gg00, 'd',
                  FILE_EXT_COR_BD00, nptr^.nd_id, nptr, 1);
            g01opmsg (sp3p_knldiag, sp3m_error,bd50c10IllegalEntryPos_csp03,
                  csp3_n_btree, 'Illegal entry pos       ', recPosition);
            b06write_filename_and_root (curr_tree_id)
            END
        ELSE
            BEGIN
            pRec := @nptr^.nd_body[ recPosition ];
            leaf := gg06PnoGet (pRec^.recPno_gg00);
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
(*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 temp_current : tbd_current_tree);
 
CONST
      c_init_inv_tree  = true; (* k33mult_inv_key *)
      c_next_check_cnt = 50;
 
VAR
      single           : boolean;
      index            : integer;
      rec_pos          : integer;
      CheckSpaceCount  : tsp00_Int4;
      Next             : tsp00_PageNo;
      nptr             : tbd_node_ptrs;
      pRec             : tgg00_RecPtr;
      Key              : tgg00_Lkey;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    nptr.np_ptr     := NIL;
    nptr.np_cbptr   := NIL;
    CheckSpaceCount := 0;
    Next            := NIL_PAGE_NO_GG00;
    b50first_leaf (Next, r_lock_leaf, single, current);
    WHILE (trError_gg00 = e_ok) AND (Next <> NIL_PAGE_NO_GG00) DO
        BEGIN
        IF  trRteCommPtr_gg00^.to_cancel
        THEN
            trError_gg00 := e_cancelled
        ELSE
            IF  nptr.np_ptr = NIL
            THEN
                BEGIN
                bd13GetNode (current, Next, plmNoLock_ebd00, nr_for_read, nptr);
                index := FIRST_REC_INDEX_BD00
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            WHILE (trError_gg00 = e_ok) AND (index < nptr.np_ptr^.nd_record_cnt) DO
                BEGIN
                WITH nptr, np_ptr^, m.mb_qual^, m.mb_data^ DO
                    BEGIN
                    rec_pos := nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
                    pRec    := @nd_body [rec_pos];
                    k33mult_inv_key( curr_tree_id, curr_tree_id, NOT c_init_inv_tree,
                          m.mb_st, pRec, mcol_pos, mcol_pos + mcol_cnt - 1, Key, trError_gg00);
                    IF  (Key.keyLen_gg00 > 0) AND (trError_gg00 = e_ok)
                    THEN
                        BEGIN
                        mbp_reclen := Key.keyLen_gg00 +  cgg_rec_key_offset;
                        mbp_keylen := Key.keyLen_gg00;
                        g10mv4 ('VBD50 ',   3,    
                              sizeof (Key.keyVal_gg00), m.mb_data_size,
                              Key.keyVal_gg00, 1,
                              mbp_buf, 1 + cgg_rec_key_offset,
                              Key.keyLen_gg00, trError_gg00);
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            IF  CheckSpaceCount = c_next_check_cnt
                            THEN
                                BEGIN
                                bd999CheckSpace (curr_trans^, 1);
                                CheckSpaceCount := 0
                                END;
                            (*ENDIF*) 
                            IF  trError_gg00 = e_ok
                            THEN
                                BEGIN
                                b30tadd_temp_primary (NOT c_count_duplicates,
                                      mbp_rec, temp_current);
                                IF  trError_gg00 = e_duplicate_key
                                THEN
                                    trError_gg00 := e_ok
                                ELSE
                                    CheckSpaceCount := CheckSpaceCount + 1
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    index := index + 1
                    END
                (*ENDWITH*) 
                END;
            (*ENDWHILE*) 
            Next := nptr.np_ptr^.nd_right;
            b13r_release_node (nptr, current, lru_mid);
            IF  (curr_lockstate = r_lock_leaf) AND (Next <> NIL_PAGE_NO_GG00)
            THEN
                BEGIN
                IF  (ftsDynamic_egg00 IN curr_tree_id.fileType_gg00) AND
                    (curr_right_bound = curr_node_locked           ) AND
                    g01glob.bd_subtree
                THEN
                    BEGIN
                    b50cross_subtree_boundary (current, curr_node_locked, Next);
                    IF  trError_gg00 = e_ok
                    THEN
                        b75llread_lock_leaf(current, Next, 190)
                    (*ENDIF*) 
                    END
                ELSE
                    b75lulread_unlocklock_leaf (current, curr_node_locked, curr_lvl_1_locked,
                          Next, curr_lvl_1_locked, 112)
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    IF  curr_lockstate = r_lock_leaf
    THEN
        b75luread_unlock_leaf (current, curr_node_locked)
    ELSE
        IF  curr_lockstate = r_lock_index
        THEN
            b75iuread_unlock_index (current, curr_lvl_1_locked)
        (*ENDIF*) 
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50FindLeaf (
            VAR sepKey  : tsp00_Key;
            keyLen      : tsp00_Int4;
            VAR nptrs   : tbd_node_ptrs;
            VAR neighbs : tbd_neighbors;
            VAR current : tbd_current_tree);
 
VAR
      bConcurrent     : boolean;
      bFound          : boolean;
      bForUpdate      : boolean;
      bWasLastRecord  : 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
    bConcurrent      := ftsConcurrent_egg00 IN fileType_gg00;
    bForUpdate       := bd_write_acc IN fileBdUse_gg00;
    bFound           := false;
    (* *)
    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;
    curr_left_bound  := NIL_PAGE_NO_GG00;
    curr_right_bound := 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*) 
            IF  (level = FIRST_INDEX_LEVEL_BD00) AND bForUpdate
            THEN
                bd13GetNode (current, subRoot, plmLock_ebd00, nr_for_update, nptrs)
            ELSE
                BEGIN
                bd13GetNode (current, subRoot, plmLock_ebd00, nr_for_read, nptrs);
                IF  (level = SECOND_INDEX_LEVEL_BD00) AND bConcurrent
                THEN
                    currIndexNptrs_bd00 := nptrs
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            WITH nptrs, np_ptr^ DO
                BEGIN
                level := nd_level;
                IF  ((ftsPerm_egg00 IN fileType_gg00) AND (nd_right <> rightNeighbor))
                    AND
                    (((level = LEAF_LEVEL_BD00) AND (nd_id <> curr_right_bound))
                    OR
                    (level <> LEAF_LEVEL_BD00))
                THEN
                    BEGIN
                    g01opmsg (sp3p_knldiag, sp3m_error, csp3_b50_2_invalid_structure,
                          csp3_n_btree, 'invalid index 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  ftsPerm_egg00 IN fileType_gg00
                            THEN
                                BEGIN
                                b51next_branch (np_ptr, recIndex, bWasLastRecord);
                                IF  bWasLastRecord
                                THEN
                                    bd50get_right_subtree (current, nptrs, 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
                                        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; (* TODO was ist das ??*)
                                            curr_lvl_1_left := leftNeighbor
                                            END
                                        (*ENDIF*) 
                                        END
                                    (*ENDIF*) 
                                    END;
                                (*ENDIF*) 
                                IF  trError_gg00 = e_ok
                                THEN
                                    BEGIN
                                    b50get_left_subtree (nptrs, subRootRecIndex, leftNeighbor,
                                          leftSubRoot, current);
                                    IF  trError_gg00 = e_ok
                                    THEN
                                        BEGIN
                                        rightNeighbor := rightSubRoot;
                                        leftNeighbor  := leftSubRoot;
                                        IF  level = FIRST_INDEX_LEVEL_BD00
                                        THEN
                                            BEGIN
                                            curr_left_bound  := bd52SubtreePno (np_ptr, FIRST_REC_INDEX_BD00);
                                            curr_right_bound := bd52SubtreePno (np_ptr, nd_record_cnt - 1)
                                            END
                                        (*ENDIF*) 
                                        END
                                    (*ENDIF*) 
                                    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
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd50IndexNodeIsSaveForDelete (
            VAR current : tbd_current_tree;
            recIndex    : tsp00_Int4) : boolean;
 
VAR
      bIsSave     : boolean;
      level       : tsp00_Int2;
      length      : tsp00_Int4;
      maxRecIndex : tsp00_Int4;
      recPosition : tsp00_Int4;
      usedSpace   : tsp00_Int4;
      pRec        : tgg00_RecPtr;
      nptrs       : tbd_node_ptrs;
 
BEGIN
WITH current DO
    BEGIN
    level := currRootNptrs_bd00.np_ptr^.nd_level;
    IF  LEAF_LEVEL_BD00 = level
    THEN
        bIsSave := false
    ELSE
        BEGIN
        IF  FIRST_INDEX_LEVEL_BD00 = level
        THEN
            nptrs := currRootNptrs_bd00
        ELSE
            nptrs := currIndexNptrs_bd00;
        (*ENDIF*) 
        WITH nptrs, np_ptr^ DO
            BEGIN
            maxRecIndex := nd_record_cnt - 1;
            IF  (recIndex = maxRecIndex) OR (recIndex = FIRST_REC_INDEX_BD00)
            THEN
                bIsSave := false
            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 ];
                    length    := pRec^.recLen_gg00 + POINTERSIZE_BD00;
                    usedSpace := nd_bottom - BODY_BEG_BD00 + nd_record_cnt * POINTERSIZE_BD00;
                    bIsSave   := (nd_id = curr_tree_id.fileRoot_gg00) OR
                          ((usedSpace - length) > QUATER_COVERING_BD00)
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDWITH*) 
        END;
    (*ENDIF*) 
    bd50IndexNodeIsSaveForDelete := bIsSave
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd50IndexNodeIsSaveForInsert (
            VAR current : tbd_current_tree;
            recIndex    : tsp00_Int4) : boolean;
 
VAR
      bIsSave     : boolean;
      level       : tsp00_Int2;
      length      : tsp00_Int4;
      maxRecIndex : tsp00_Int4;
      recPosition : tsp00_Int4;
      pRec        : tgg00_RecPtr;
      nptrs       : tbd_node_ptrs;
 
BEGIN
WITH current DO
    BEGIN
    level := currRootNptrs_bd00.np_ptr^.nd_level;
    IF  LEAF_LEVEL_BD00 = level
    THEN
        bIsSave := false
    ELSE
        BEGIN
        IF  FIRST_INDEX_LEVEL_BD00 = level
        THEN
            nptrs := currRootNptrs_bd00
        ELSE
            nptrs := currIndexNptrs_bd00;
        (*ENDIF*) 
        WITH nptrs, np_ptr^ DO
            BEGIN
            maxRecIndex := nd_record_cnt - 1;
            IF  recIndex = maxRecIndex
            THEN
                bIsSave := false
            ELSE
                BEGIN
                recPosition := nd_pointer_list [MAX_POINTERINDEX_BD00 - maxRecIndex];
                IF  bd50_RecordPositionValid( curr_trans^, curr_tree_id,
                    nptrs.np_ptr, recPosition)
                THEN
                    BEGIN
                    pRec    := @nd_body[ recPosition ];
                    length  := pRec^.recLen_gg00 + POINTERSIZE_BD00 + 2; (* alignment *)
                    bIsSave := (nd_bottom + 2 * length) <
                          (MAX_BOTTOM_BD00 - ((nd_record_cnt+1)*POINTERSIZE_BD00));
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDWITH*) 
        END;
    (*ENDIF*) 
    bd50IndexNodeIsSaveForInsert := bIsSave
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50count_records (
            VAR current     : tbd_current_tree;
            VAR start_key   : tgg00_Lkey;
            VAR stop_key    : tgg00_Lkey;
            start_index_pno : tsp00_PageNo;
            start_leaf      : tsp00_PageNo;
            stop_leaf       : tsp00_PageNo;
            VAR record_cnt  : tsp00_Int4;
            VAR page_cnt    : tsp00_Int4);
 
VAR
      use_subtree_lock : boolean;
      start_result     : tbd_searchresult;
      stop_result      : tbd_searchresult;
      start_maxindex   : integer;
      start_index      : integer;
      stop_index       : integer;
      leaf_cnt         : integer;
      index            : integer;
      curr_leaf        : tsp00_PageNo;
      nptr             : tbd_node_ptrs;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    record_cnt    := 0;
    use_subtree_lock :=
          (ftsDynamic_egg00 IN curr_tree_id.fileType_gg00)
          AND
          g01glob.bd_subtree;
    IF  curr_lockstate <> no_bd_lock
    THEN
        BEGIN
        IF  use_subtree_lock
        THEN
            BEGIN
            b75ilread_lock_index (current, start_index_pno, 187);
            bd13GetNode (current, start_index_pno, plmNoLock_ebd00, nr_return_if_leaf, nptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                stop_leaf := NIL_PAGE_NO_GG00;
                bd51SearchBranch (current, @start_key.keyVal_gg00, start_key.keyLen_gg00, nptr.np_ptr, index);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    start_leaf       := bd52SubtreePno (nptr.np_ptr, index);
                    curr_left_bound  := bd52SubtreePno (nptr.np_ptr, FIRST_REC_INDEX_BD00);
                    curr_right_bound := bd52SubtreePno (nptr.np_ptr, nptr.np_ptr^.nd_record_cnt - 1);
                    b13r_release_node (nptr, current, lru_normal)
                    END
                (*ENDIF*) 
                END
            ELSE
                IF  trError_gg00 = e_root_is_leaf
                THEN
                    trError_gg00 := e_ok;
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b75llread_lock_leaf (current, start_leaf, 183)
        (*ENDIF*) 
        END;
&   ifdef TRACE
    (*ENDIF*) 
    t01p2int4 (bd_index, 'start leaf: ', start_leaf
          ,              'stop_leaf:  ', stop_leaf);
&   endif
    IF  trError_gg00 = e_ok
    THEN
        bd13GetNode (current, start_leaf, plmNoLock_ebd00,
              nr_for_read, nptr);
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        start_maxindex := nptr.np_ptr^.nd_record_cnt - 1;
        curr_leaf      := nptr.np_ptr^.nd_id;
        b31search_entry (current, start_key.keyVal_gg00, start_key.keyLen_gg00,
              nptr.np_ptr, start_index, start_result);
        IF  (start_result <> nonefound) OR (trError_gg00 <> e_ok)
        THEN
            BEGIN
            leaf_cnt := 1;
            REPEAT
                IF  stop_leaf = NIL_PAGE_NO_GG00
                THEN
                    BEGIN
                    b31search_entry (current, stop_key.keyVal_gg00, stop_key.keyLen_gg00,
                          nptr.np_ptr, stop_index, stop_result);
                    IF  (stop_result <> lastfound)
                        AND
                        (nptr.np_ptr^.nd_right <> NIL_PAGE_NO_GG00)
                        AND
                        (trError_gg00 = e_ok)
                    THEN
                        stop_leaf := curr_leaf
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  (start_leaf <> stop_leaf) AND (trError_gg00 = e_ok)
                THEN
                    BEGIN
                    IF  (curr_leaf <> start_leaf) AND
                        (curr_leaf <> stop_leaf )
                    THEN
                        record_cnt := record_cnt + nptr.np_ptr^.nd_record_cnt - 1;
                    (*ENDIF*) 
                    IF  curr_leaf <> stop_leaf
                    THEN
                        BEGIN
                        curr_leaf := nptr.np_ptr^.nd_right;
                        b13r_release_node (nptr, current, lru_normal);
                        IF  curr_lockstate = r_lock_leaf
                        THEN
                            BEGIN
                            IF  use_subtree_lock AND
                                (curr_right_bound = curr_node_locked)
                            THEN
                                BEGIN
                                b50cross_subtree_boundary (current,
                                      curr_node_locked, curr_leaf);
                                IF  trError_gg00 = e_ok
                                THEN
                                    b75llread_lock_leaf (current,
                                          curr_leaf, 194)
                                (*ENDIF*) 
                                END
                            ELSE
                                b75lulread_unlocklock_leaf (current,
                                      curr_node_locked, curr_lvl_1_locked,
                                      curr_leaf, curr_lvl_1_locked, 184)
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            bd13GetNode (current, curr_leaf, plmNoLock_ebd00,
                                  nr_for_read, nptr);
                            leaf_cnt := succ (leaf_cnt)
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            UNTIL
                (trError_gg00 <> e_ok                     ) OR
                (curr_leaf    =  stop_leaf                ) OR
                (leaf_cnt     >  c_upb_pages_to_count_recs);
            (*ENDREPEAT*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  curr_leaf = stop_leaf
                THEN
                    BEGIN
                    b31search_entry (current, stop_key.keyVal_gg00, stop_key.keyLen_gg00,
                          nptr.np_ptr, stop_index, stop_result);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        IF  start_leaf = stop_leaf
                        THEN
                            record_cnt := stop_index - start_index + 1
                        ELSE
                            record_cnt := record_cnt +
                                  (start_maxindex - start_index + 1) +
                                  (stop_index +1);
                        (*ENDIF*) 
                        IF  start_result = lastfound
                        THEN
                            record_cnt := record_cnt - 1;
                        (*ENDIF*) 
                        IF  stop_result = nextfound
                        THEN
                            record_cnt := record_cnt - 1;
                        (*ENDIF*) 
                        IF  record_cnt < 0
                        THEN
                            record_cnt := 0;
                        (*ENDIF*) 
                        page_cnt := leaf_cnt;
&                       ifdef TRACE
                        t01p2int4 (bd_index, 'start leaf: ',start_leaf
                              ,              'stop_leaf:  ',stop_leaf);
                        t01p2int4 (bd_index, 'curr leaf:  ',curr_leaf
                              ,              'rec count:  ',record_cnt);
&                       endif
                        END
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    (* c_upb_pages_to_count_recs exceeded *)
                    (* should not happen                  *)
                    record_cnt := -1;
                    IF  page_cnt <= c_upb_pages_to_count_recs
                    THEN
                        page_cnt := c_upb_pages_to_count_recs +1;
&                   ifdef TRACE
                    (*ENDIF*) 
                    t01p2int4 (bd_index, 'curr leaf:  ', curr_leaf
                          ,              'rec count:  ', record_cnt);
&                   endif
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    IF  curr_lockstate = r_lock_leaf
    THEN
        b75luread_unlock_leaf (current, curr_node_locked)
    ELSE
        IF  curr_lockstate = r_lock_index
        THEN
            b75iuread_unlock_index (current, curr_lvl_1_locked)
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50determine_subtree_info (VAR nptrs : tbd_node_ptrs;
            subroot          : tsp00_PageNo;
            RecIndex         : tsp00_Int4;
            MaxRecIndex      : tsp00_Int4;
            VAR current      : tbd_current_tree;
            VAR subtree_info : tbd_subtree_info);
 
VAR
      length : integer;
      pRec   : tgg00_RecPtr;
 
BEGIN
WITH nptrs, np_ptr^, current, curr_tree_id, subtree_info DO
    BEGIN
    curr_left_bound  := bd52SubtreePno (np_ptr, FIRST_REC_INDEX_BD00);
    curr_right_bound := bd52SubtreePno (np_ptr, MaxRecIndex);
    IF  sti_is_del_op
    THEN
        BEGIN
        (* delete *)
        IF  (subroot = curr_left_bound)
            OR
            (subroot = curr_right_bound)
        THEN
            sti_boundary := true;
        (*ENDIF*) 
        pRec   := @nd_body [nd_pointer_list [MAX_POINTERINDEX_BD00 - RecIndex]];
        length := pRec^.recLen_gg00 + POINTERSIZE_BD00;
        sti_index_underflow := (nd_id <> fileRoot_gg00) AND
              ((nd_bottom - BODY_BEG_BD00 + nd_record_cnt*POINTERSIZE_BD00 -
              length) < QUATER_COVERING_BD00)
        END
    ELSE
        BEGIN
        (* insert *)
        IF  (subroot = curr_right_bound)
        THEN
            sti_boundary := true;
        (*ENDIF*) 
        pRec   := @nd_body [nd_pointer_list [MAX_POINTERINDEX_BD00 - MaxRecIndex]];
        length := pRec^.recLen_gg00 + POINTERSIZE_BD00;
        sti_index_overflow :=
              ((nd_bottom + 2 * length) > (MAX_BOTTOM_BD00 - ((nd_record_cnt+1)*POINTERSIZE_BD00)))
        END;
    (*ENDIF*) 
&   ifdef TRACE
    IF  t01trace (bd_index)
    THEN
        BEGIN
        t01int4   (bd_index, 'curr_lvl1_lo', curr_lvl_1_locked);
        t01p2int4 (bd_index, 'curr_left_bo', curr_left_bound
              ,              'curr_right_b', curr_right_bound)
        END;
&   endif
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50drop_long (
            VAR t          : tgg00_TransContext;
            nptr           : tbd_nodeptr;
            long_cnt       : integer;
            varcol_cnt_off : integer);
 
VAR
      pRec            : tgg00_RecPtr;
      rec_pos         : tsp00_Int4;
      long_pos        : tsp00_Int4;
      aux_long_no     : tsp00_Int4;
      aux_varcol_no   : tsp00_Int4;
      curr_varcol_cnt : tsp00_Int4;
      aux_varcol_len  : tsp00_Int4;
      index           : tsp00_Int4;
      long_id         : tgg00_FileId;
 
BEGIN
long_id               := b01niltree_id;
long_id.fileType_gg00 := [ ftsByteStr_egg00, ftsConcurrent_egg00 ];
long_id.fileTfn_gg00  := tfnColumn_egg00;
WITH t, nptr^ DO
    BEGIN
    index    := FIRST_REC_INDEX_BD00;
    WHILE (trError_gg00 = e_ok) AND (index <= nd_record_cnt - 1) DO
        BEGIN
        rec_pos := nd_pointer_list[MAX_POINTERINDEX_BD00 - index];
        pRec    := @nd_body [rec_pos];
        IF  varcol_cnt_off = cgg_nil_varcol_cnt_off
        THEN
            BEGIN
            long_pos := rec_pos + cgg_rec_key_offset + pRec^.recKeyLen_gg00;
&           ifdef trace
            t01p2int4 (bd_byte, 'loop        ', 1
                  ,             'old long pos', long_pos);
&           endif
            aux_long_no := 1;
            WHILE (trError_gg00 = e_ok) AND
                  (aux_long_no <= long_cnt) DO
                BEGIN
&               ifdef trace
                t01p2int4 (bd_byte, 'loop        ', 2
                      ,             'old long nr ', aux_long_no);
&               endif
                IF  nd_body [long_pos] <> csp_undef_byte
                THEN
                    BEGIN
                    long_id.fileRoot_gg00 := NIL_PAGE_NO_GG00;
                    g10mv1 ('VBD50 ',   4,    
                          sizeof (tbd_node), sizeof (long_id.fileName_gg00),
                          nptr^, long_pos + 1, long_id.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 (t, long_id);
                    (*ENDIF*) 
                    IF  (trError_gg00 = e_bad_datapage)
                        OR
                        (trError_gg00 = e_file_not_found)
                    THEN
                        trError_gg00 := e_ok
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                long_pos    := long_pos + cgg_col_fd_size;
                aux_long_no := aux_long_no + 1
                END;
            (*ENDWHILE*) 
            END
        ELSE
            BEGIN
            long_pos := rec_pos + cgg_rec_key_offset +
                  pRec^.recKeyLen_gg00 + varcol_cnt_off;
            curr_varcol_cnt := ord (nd_body [long_pos]);
            long_pos := long_pos + 1;
&           ifdef trace
            t01p2int4 (bd_byte, 'loop        ', 1
                  ,             'long pos    ', long_pos);
&           endif
            aux_long_no   := 1;
            aux_varcol_no := 1;
            WHILE (trError_gg00  =  e_ok           ) AND
                  (aux_varcol_no <= curr_varcol_cnt) AND
                  (aux_long_no   <= long_cnt       ) DO
                BEGIN
&               ifdef trace
                IF  t01trace (bd_byte)
                THEN
                    BEGIN
                    t01p2int4 (bd_byte, 'loop        ', 2
                          ,             'varcol no   ', aux_varcol_no);
                    t01int4   (bd_byte, 'varcol pos  ', long_pos);
                    END;
&               endif
                (*ENDIF*) 
                aux_varcol_len := ord (nd_body [long_pos]);
                long_pos       := long_pos + 1;
                long_pos       := long_pos + aux_varcol_len;
                aux_varcol_no  := aux_varcol_no + 1
                END;
            (*ENDWHILE*) 
            END;
        (*ENDIF*) 
        index := index + 1
        END
    (*ENDWHILE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50establish_treeindex (first_leaf : tsp00_PageNo;
            VAR current : tbd_current_tree);
 
VAR
      free_first_node    : boolean;
      nolog              : boolean;
      root_fileversion   : tgg91_FileVersion;
      next               : tsp00_PageNo;
      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;
    nolog         := hsNoLog_egg00 IN fileHandling_gg00;
    IF  NOT nolog
    THEN
        fileHandling_gg00 := fileHandling_gg00 + [hsNoLog_egg00];
    (*ENDIF*) 
    free_first_node := false;
    bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00,
          nr_for_update, lnptr);
    IF  trError_gg00 = e_ok
    THEN
        IF  fileRoot_gg00 <> first_leaf
        THEN
            BEGIN
            bd13GetNode (current, first_leaf, plmNoLock_ebd00,
                  nr_for_update, nptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                root_fileversion   := lnptr.np_ptr^.nd_file_version;
                free_first_node    := true;
                next               := nptr.np_ptr^.nd_right;
                s10mv2 (sizeof (tbd_node), sizeof (tbd_node),
                      nptr.np_ptr^, 1,
                      lnptr.np_ptr^, 1, sizeof (tbd_node));
                lnptr.np_ptr^.nd_id           := fileRoot_gg00;
                lnptr.np_ptr^.nd_file_version := root_fileversion;
                END
            (*ENDIF*) 
            END
        ELSE
            next := lnptr.np_ptr^.nd_right;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        IF  next <> NIL_PAGE_NO_GG00
        THEN
            REPEAT
                bd13GetNode (current, next, plmNoLock_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;
                    next                          := 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 (next = NIL_PAGE_NO_GG00)
            (*ENDREPEAT*) 
        ELSE
            b13w_release_node (lnptr, current);
        (*ENDIF*) 
    (*ENDIF*) 
    IF  free_first_node AND (trError_gg00 = e_ok)
    THEN
        BEGIN
        b13pfree_pno (first_leaf, 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 nolog
    THEN
        fileHandling_gg00 := fileHandling_gg00 - [hsNoLog_egg00]
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50get_right_subtree (
            VAR current       : tbd_current_tree;
            VAR nptr          : tbd_node_ptrs;
            VAR index         : integer;
            right_neighbor    : tsp00_PageNo;
            VAR right_subroot : tsp00_PageNo);
 
VAR
      last  : 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.np_ptr, index, last);
    IF  last
    THEN
        IF  (right_neighbor = NIL_PAGE_NO_GG00)
            OR
            ((nptr.np_ptr^.nd_level = FIRST_INDEX_LEVEL_BD00)
            AND
            (ftsDynamic_egg00 IN curr_tree_id.fileType_gg00)
            AND
            ((curr_lockstate <> w_lock_tree) AND
            (curr_lockstate  <> d_lock_tree) AND
            (curr_lockstate  <> s_lock_tree) AND
            (curr_lockstate  <> no_bd_lock))
            AND
            g01glob.bd_subtree)
        THEN
            right_subroot := NIL_PAGE_NO_GG00
        ELSE
            BEGIN
            bd13GetNode (current, right_neighbor, plmNoLock_ebd00,
                  nr_for_read, nnptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                index         := FIRST_REC_INDEX_BD00;
                right_subroot := bd52SubtreePno (nnptr.np_ptr, index)
                END;
            (*ENDIF*) 
            IF  nnptr.np_ptr <> NIL
            THEN
                b13r_release_node (nnptr, current, lru_normal)
            (*ENDIF*) 
            END
        (*ENDIF*) 
    ELSE (*  not last *)
        right_subroot := bd52SubtreePno (nptr.np_ptr, index)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(* PTS 1109905 E.Z. everything with newlong *)
(*------------------------------*) 
 
PROCEDURE
      bd50l_check_long (
            VAR FileId           : tgg00_FileId;
            VAR t                : tgg00_TransContext;
            Nptr                 : tbd_nodeptr;
            LongColCnt           : tsp00_Int2;
            NewLongColCnt        : tsp00_Int2;
            check_long_existence : 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;
 
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;
    b30cinit_current (t, ShcolCurrent);
    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
                IF  check_long_existence AND
                    (NewLongColCnt < LongColCnt)
                THEN
                    BEGIN
                    b30current (t, ShcolFileId, m_select, ShcolCurrent);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        Key.keyLen_gg00 := sizeof (tgg00_Surrogate);
                        g10mv2 ('VBD50 ',   5,    
                              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
                            b30exists_rec (Key, ShcolCurrent);
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  ShcolCurrent.curr_lockstate = r_lock_tree
                    THEN
                        b75turead_unlock_tree (ShcolCurrent);
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  ((trError_gg00 = e_ok) AND NOT check_long_existence) OR
                    (trError_gg00 = e_key_not_found)
                THEN
                    BEGIN
                    trError_gg00         := e_ok;
                    LongId.fileRoot_gg00 := NIL_PAGE_NO_GG00;
                    g10mv1 ('VBD50 ',   6,    
                          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  check_long_existence
                    THEN
                        BEGIN
                        (* Long column not found! Neither in short column *)
                        (* file nor in separate blob file.                *)
                        trError_gg00 := e_long_column_missing; (* PTS 1103382 TS 1999-07-16 *)
                        g01opmsg (sp3p_knldiag, sp3m_error,
                              bd50c1LongColumnNotFound_csp03,
                              csp3_n_btree, 'Long column not found   ', RecPos);
                        END
                    ELSE
                        trError_gg00 := e_ok;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  (trError_gg00 = e_data_page_corrupted) OR
                    (trError_gg00 = e_long_column_missing)
                THEN
                    b06dump_bad_page (trTaskId_gg00, 'd',
                          FILE_EXT_COR_BD00, nd_id, Nptr, 1)
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            LongPos   := LongPos + cgg_col_fd_size;
            AuxLongNo := succ (AuxLongNo)
            END;
        (*ENDWHILE*) 
        RecIndex := succ (RecIndex)
        END
    (*ENDWHILE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50trelease_treeindex (
            VAR current : tbd_current_tree;
            subroot     : tsp00_PageNo);
 
VAR
      last        : boolean;
      aux_error   : tgg00_BasisError;
      index       : integer;
      new_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
    bd13GetNode (current, subroot, plmNoLock_ebd00,
          nr_for_update, nptr);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        WITH nptr.np_ptr^ DO
            IF  (subroot <> fileRoot_gg00) OR
                (nd_level > LEAF_LEVEL_BD00)
            THEN
                BEGIN
                IF  nd_level > LEAF_LEVEL_BD00 + 1
                THEN
                    BEGIN
                    index := FIRST_REC_INDEX_BD00;
                    last := false;
                    aux_error := e_ok;
                    REPEAT
                        new_subroot := bd52SubtreePno (nptr.np_ptr, index);
                        bd50trelease_treeindex (current, new_subroot);
                        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*) 
                    END;
                (*ENDIF*) 
                IF  (trError_gg00 = e_ok) OR (trError_gg00 = e_bad_datapage)
                THEN
                    BEGIN
                    aux_error    := trError_gg00;
                    trError_gg00 := e_ok;
                    IF  nptr.np_ptr^.nd_id = fileRoot_gg00
                    THEN
                        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*) 
                    ELSE
                        b13free_node (nptr, current);
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        trError_gg00 := aux_error
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            ELSE
                IF  nptr.np_ptr <> NIL
                THEN
                    b13r_release_node (nptr, current, lru_normal)
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDWITH*) 
        END
    ELSE
        IF  (subroot <> fileRoot_gg00)
            AND
            ((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*) 
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd50trunc_tree (
            VAR current           : tbd_current_tree;
            first_leaf            : tsp00_PageNo;
            stringcol_cnt         : integer;
            varcol_cnt_off        : integer;
            VAR rk                : tgg00_Lkey;
            VAR create_tree_index : boolean);
 
VAR
      l_result : tsp00_LcompResult;
      pRec     : tgg00_RecPtr;
      pos      : integer;
      nptr     : tbd_node_ptrs;
      pno      : tsp00_PageNo;
 
BEGIN
create_tree_index := true;
pno               := first_leaf;
nptr.np_ptr       := NIL;
nptr.np_cbptr     := NIL;
WITH current, curr_trans^ DO
    BEGIN
    IF  rk.len > 0
    THEN
        REPEAT
            bd13GetNode (current, pno, plmNoLock_ebd00,
                  nr_for_update, nptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  nptr.np_ptr^.nd_bottom > BODY_BEG_BD00
                THEN
                    BEGIN
                    pos  := nptr.np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 -
                          (nptr.np_ptr^.nd_record_cnt - 1)];
                    pRec := @nptr.np_ptr^.nd_body [pos];
                    s30cmp (rk.keyVal_gg00, 1, rk.keyLen_gg00,
                          pRec^.recKey_gg00.keyVal_gg00,
                          1, pRec^.recKeyLen_gg00, l_result);
                    IF  l_result = l_greater
                    THEN
                        BEGIN
                        pno := nptr.np_ptr^.nd_right;
                        b13r_release_node (nptr, current, lru_normal);
                        END
                    ELSE
                        BEGIN
                        IF  l_result = l_equal
                        THEN
                            BEGIN
                            pno := nptr.np_ptr^.nd_right;
                            nptr.np_ptr^.nd_right := NIL_PAGE_NO_GG00;
                            b13w_release_node (nptr, current)
                            END
                        ELSE
                            BEGIN
                            IF  pno = first_leaf
                            THEN
                                create_tree_index := false
                            ELSE
                                IF  rk.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  pno = first_leaf
                    THEN
                        create_tree_index := false
                    ELSE
                        trError_gg00 := e_invalid_leaves_structure;
                    (*ENDIF*) 
                    l_result := l_less;
                    b13r_release_node (nptr, current, lru_normal);
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
        UNTIL
            (trError_gg00 <> e_ok            ) OR
            (l_result     <> l_greater       ) OR
            (pno          =  NIL_PAGE_NO_GG00)
        (*ENDREPEAT*) 
    ELSE
        create_tree_index := false;
    (*ENDIF*) 
    IF  pno = curr_tree_id.fileRoot_gg00
    THEN
        BEGIN
        pno := NIL_PAGE_NO_GG00;
        IF  rk.len = 0
        THEN
            BEGIN
            bd13GetNode (current, curr_tree_id.fileRoot_gg00, plmNoLock_ebd00,
                  nr_for_update, nptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  stringcol_cnt > 0
                THEN
                    BEGIN
                    bd50drop_long (curr_trans^, nptr.np_ptr, stringcol_cnt,
                          varcol_cnt_off);
                    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;
                    pno           := nd_right;
                    nd_right      := NIL_PAGE_NO_GG00;
                    b13w_release_node (nptr, current)
                    END
                (*ENDWITH*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND (pno <> NIL_PAGE_NO_GG00)
    THEN
        BEGIN
        REPEAT
            bd13GetNode (current, pno, plmNoLock_ebd00,
                  nr_for_update, nptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                pno := nptr.np_ptr^.nd_right;
                IF  stringcol_cnt > 0
                THEN
                    BEGIN
                    bd50drop_long (curr_trans^, nptr.np_ptr,
                          stringcol_cnt, varcol_cnt_off);
                    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 (pno = 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_CheckEntry (
            VAR Nptr       : tbd_node_ptrs;
            VAR DumpParent : boolean;
            VAR Current    : tbd_current_tree);
 
VAR
      RecIndex : tsp_int4;
      RecPos   : tsp_int4;
 
BEGIN
WITH Current, curr_trans^, Nptr, np_ptr^ 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];
        IF  (RecPos < BODY_BEG_BD00) OR (RecPos > nd_bottom)
        THEN
            BEGIN
            trError_gg00 := e_illegal_entrypos;
            DumpParent   := true;
            b06dump_bad_page (trTaskId_gg00, 'd',
                  FILE_EXT_COR_BD00, nd_id, np_ptr, 1);
            g01opmsg (sp3p_knldiag, sp3m_error,
                  bd50c9IllegalEntryPos_csp03, csp3_n_btree,
                  'Illegal entry pos       ', RecPos)
            END;
        (*ENDIF*) 
        RecIndex := succ (RecIndex)
        END
    (*ENDWHILE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd50_RecordPositionValid (
            VAR trans   : tgg00_TransContext;
            VAR fileId  : tgg00_FileId;
            nptr        : tbd_nodeptr;
            recPosition : tsp00_Int4) : boolean;
 
BEGIN
IF  (recPosition < BODY_BEG_BD00) OR (recPosition > 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       ', recPosition);
    b06write_filename_and_root (fileId)
    END;
(*ENDIF*) 
bd50_RecordPositionValid := (trans.trError_gg00 = e_ok);
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
