.ad 8
.bm 8
.fm 4
.bt $Copyright (c) 2000-2005 SAP AG$$Page %$
.tm 12
.hm 6
.hs 3
.tt 1 $SQL$Project Distributed Database System$VBD51$
.tt 2 $$$
.tt 3 $JuergenP$branchnodehandling$1999-10-12$
***********************************************************
.nf
 
 .nf
 
    ========== licence begin  GPL
    Copyright (c) 2000-2005 SAP AG
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end
.fo
 
 
.fo
.nf
.sp
Module  : branchnodehandling
=========
.sp
Purpose : operations on index nodes
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        PROCEDURE
              b51add_branch (VAR nptr  : tbd_node_ptrs;
                    index              : tsp00_Int4;
                    left               : tsp00_PageNo;
                    VAR separator      : tbd00_Separator;
                    VAR indexorderlist : tbd00_OrderList;
                    VAR current        : tbd_current_tree);
 
        PROCEDURE
              b51del_branch (VAR nptr  : tbd_node_ptrs;
                    index              : tsp00_Int4;
                    left               : tsp00_PageNo;
                    VAR indexorderlist : tbd00_OrderList;
                    VAR current        : tbd_current_tree);
 
        PROCEDURE
              b51divert_rightnext(left : tsp00_PageNo;
                    old_right   : tsp00_PageNo;
                    new_right   : tsp00_PageNo;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b51ldivert_leftnext (right : tsp00_PageNo;
                    new_left    : tsp00_PageNo;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b51new_branchroot (VAR nptr : tbd_node_ptrs;
                    VAR RightSeparator : tbd00_Separator;
                    VAR indexorderlist : tbd00_OrderList;
                    VAR current        : tbd_current_tree);
 
        PROCEDURE
              b51next_branch (VAR nptr : tbd_nodeptr;
                    VAR index : integer;
                    VAR last  : boolean);
 
        PROCEDURE
              b51pointer_list (VAR nptr : tbd_nodeptr);
 
        PROCEDURE
              b51repl_branch (VAR nptr : tbd_node_ptrs;
                    index              : tsp00_Int4;
                    left               : tsp00_PageNo;
                    VAR separator      : tbd00_Separator;
                    VAR indexorderlist : tbd00_OrderList;
                    VAR current        : tbd_current_tree);
 
        PROCEDURE
              bd51SearchBranch (VAR Current : tbd_current_tree;
                    pSepKey      : tsp00_KeyAddr (* ptocSynonym tsp00_KeyPtr *);
                    KeyLen       : tsp00_Int4;
                    VAR Nptr     : tbd_nodeptr;
                    VAR RecIndex : tsp00_Int4);
 
        PROCEDURE
              b51sort_branches (VAR nptr : tbd_nodeptr;
                    t : tgg00_TransContextPtr);
 
        PROCEDURE
              b51tadd_branch (VAR nptr  : tbd_node_ptrs;
                    index              : tsp00_Int4;
                    left               : tsp00_PageNo;
                    VAR separator      : tbd00_Separator;
                    pIndexOrderList    : tsp00_Addr;
                    VAR current        : tbd_current_tree);
 
        PROCEDURE
              b51tdel_branch (VAR nptr  : tbd_node_ptrs;
                    index              : tsp00_Int4;
                    left               : tsp00_PageNo;
                    pIndexOrderList    : tsp00_Addr;
                    VAR current        : tbd_current_tree);
 
        PROCEDURE
              b51trepl_branch (VAR nptr : tbd_node_ptrs;
                    index              : tsp00_Int4;
                    left               : tsp00_PageNo;
                    VAR separator      : tbd00_Separator;
                    pIndexOrderList    : tsp00_Addr;
                    VAR current        : tbd_current_tree);
 
        PROCEDURE
              b51tnew_branchroot (VAR nptr : tbd_node_ptrs;
                    VAR RightSeparator : tbd00_Separator;
                    pIndexOrderList    : tsp00_Addr;
                    VAR current        : tbd_current_tree);
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
        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
              systembufferinterface : VBD20;
 
        FUNCTION
              bd20IsPageExclusiveLocked (
                    pCBlock : tbd_nodeptr) : boolean;
 
      ------------------------------ 
 
        FROM
              branchhandling : VBD52;
 
        PROCEDURE
              bd52GetSepKey (VAR nptr : tbd_nodeptr;
                    RecIndex   : tsp00_Int4;
                    VAR SepKey : tgg00_Lkey;
                    t          : tgg00_TransContextPtr);
 
        PROCEDURE
              bd52PutSeparatorIntoNode (VAR nptr : tbd_nodeptr;
                    RecIndex      : tsp00_Int4;
                    VAR Separator : tbd00_Separator;
                    t             : tgg00_TransContextPtr);
 
        PROCEDURE
              bd52PutSepLeafCount (pRec : tgg00_RecPtr;
                    LeafCount     : tsp00_Int4);
 
        FUNCTION
              bd52SubtreePno (VAR nptr : tbd_nodeptr;
                    RecIndex : tsp00_Int4) : tsp00_PageNo;
 
      ------------------------------ 
 
        FROM
              branchreorganization : VBD55;
 
        PROCEDURE
              b55app_new_indexnode (VAR nptr : tbd_node_ptrs;
                    VAR separator      : tbd00_Separator;
                    VAR indexorderlist : tbd00_OrderList;
                    VAR current        : tbd_current_tree);
 
        PROCEDURE
              b55p_oflw_branch (VAR nptr : tbd_node_ptrs;
                    new_bl             : tsp00_Int4;
                    left               : tsp00_PageNo;
                    VAR indexorderlist : tbd00_OrderList;
                    VAR current        : tbd_current_tree);
 
        PROCEDURE
              b55p_uflw_branch (VAR nptr : tbd_node_ptrs;
                    left               : tsp00_PageNo;
                    VAR indexorderlist : tbd00_OrderList;
                    VAR current        : tbd_current_tree);
 
        PROCEDURE
              b55t_oflw_branch (VAR nptr : tbd_node_ptrs;
                    new_bl             : tsp00_Int4;
                    left               : tsp00_PageNo;
                    pIndexOrderList    : tsp00_Addr;
                    VAR current        : tbd_current_tree);
 
        PROCEDURE
              b55t_uflw_branch (VAR nptr : tbd_node_ptrs;
                    left               : tsp00_PageNo;
                    pIndexOrderList    : tsp00_Addr;
                    VAR current        : tbd_current_tree);
 
        PROCEDURE
              b55tapp_new_indexnode (VAR Nptrs : tbd_node_ptrs;
                    VAR Separator      : tbd00_Separator;
                    pIndexOrderList    : tsp00_Addr;
                    VAR Current        : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              indexupdateorders    : VBD54;
 
        PROCEDURE
              b54del_index (pSep       : tsp00_KeyAddr;
                    SepLen             : tsp00_Int4;
                    n_level            : tsp00_Int2;
                    VAR indexorderlist : tbd00_OrderList);
 
        PROCEDURE
              b54repl_index (pOldSep     : tsp00_KeyAddr;
                    OldSepLen            : tsp00_Int4;
                    pNewSep              : tsp00_KeyAddr;
                    NewSepLen            : 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);
 
        FUNCTION
              b54tdel_index (pSep       : tsp00_KeyAddr;
                    SepLen             : tsp00_Int4;
                    n_level            : tsp00_Int2;
                    pIndexOrderList    : tsp00_Addr) : boolean;
 
        FUNCTION
              b54trepl_index (pOldSep     : tsp00_KeyAddr;
                    OldSepLen            : tsp00_Int4;
                    pNewSep              : tsp00_KeyAddr;
                    NewSepLen            : tsp00_Int4;
                    n_id                 : tsp00_PageNo;
                    n_level              : tsp00_Int2;
                    pIndexOrderList      : tsp00_Addr) : boolean;
 
        PROCEDURE
              b54texecute_indexorder (
                    pIndexOrderList    : tsp00_Addr;
                    VAR current        : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              nodehandling : VBD13;
 
        PROCEDURE
              b13free_node (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd13GetNode (VAR Current : tbd_current_tree;
                    Pno          : tsp00_PageNo;
                    PageLockMode : tbd00_PageLockMode;
                    NodeReq      : tbd_node_request;
                    VAR Nptrs    : tbd_node_ptrs);
 
        PROCEDURE
              b13new_node (lno : tsp00_Int2;
                    VAR nptr    : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b13r_release_node (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree;
                    lru_info    : tbd_lru_info);
 
        PROCEDURE
              b13w_release_node (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              BD_Wrapper : VBD999;
 
        PROCEDURE
              bd999RemoveTransHistoryInfoFromPage (
                    TaskId   : tsp00_TaskId;
                    VAR Page : tbd_node);
 
        FUNCTION
              bd999IsEmptyIndexOrderList(
                    pIndexOrderList : tsp00_Addr) : boolean;
 
        PROCEDURE
              bd999PopIndexOrder(
                    pIndexOrderList : tsp00_Addr);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01glob : tgg00_KernelGlobals;
 
        PROCEDURE
              g01abort (msg_no : tsp00_Int4;
                    msg_label  : tsp00_C8;
                    msg_text   : tsp00_C24;
                    bad_value  : tsp00_Int4);
 
        PROCEDURE
              g01opmsg (msg_prio : tsp3_priority;
                    msg_type  : tsp3_msg_type;
                    msg_no    : tsp00_Int4;
                    msg_label : tsp00_C8;
                    msg_text  : tsp00_C24;
                    msg_value : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              GG_cpp_auxiliary_functions : VGG06;
 
        PROCEDURE
              gg06PnoPut (VAR Cint4 : tgg90_Cint4; int4 : tsp00_Int4);
 
        FUNCTION
              gg06PnoGet (VAR Cint4 : tgg90_Cint4): tsp00_Int4;
 
        FUNCTION
              gg06Align (
                    length    : tsp00_Int4;
                    alignment : tsp00_Int4) : tsp00_Int4;
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              SAPDB_PascalMove (
                    mod_id      : tsp00_C6;
                    mod_num     : tsp00_Int4;
                    source_upb  : tsp00_Int4;
                    dest_upb    : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    src_pos     : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    dest_pos    : tsp00_Int4;
                    length      : tsp00_Int4;
                    VAR e       : tgg00_BasisError);
 
        PROCEDURE
              SAPDB_PascalOverlappingMove (
                    mod_id      : tsp00_C6;
                    mod_num     : tsp00_Int4;
                    source_upb  : tsp00_Int4;
                    dest_upb    : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    src_pos     : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    dest_pos    : tsp00_Int4;
                    length      : tsp00_Int4;
                    VAR e       : tgg00_BasisError);
 
      ------------------------------ 
 
        FROM
              RTE-Extension-30 : VSP30;
 
        PROCEDURE
              s30cmp1 (VAR buf1  : tsp00_Key;
                    fieldpos1    : tsp00_Int4;
                    fieldlength1 : tsp00_Int4;
                    VAR buf2     : tsp00_Key;
                    fieldpos2    : tsp00_Int4;
                    fieldlength2 : tsp00_Int4;
                    VAR l_result : tsp00_LcompResult);
 
      ------------------------------ 
 
        FROM
              entryhandling : VBD35;
 
        PROCEDURE
              b35add_space (VAR nptr : tbd_nodeptr;
                    pos  : tsp00_Int4;
                    plus : tsp00_Int4;
                    t    : tgg00_TransContextPtr);
 
        PROCEDURE
              b35del_space (VAR nptr : tbd_nodeptr;
                    pos   : tsp00_Int4;
                    minus : tsp00_Int4;
                    t     : tgg00_TransContextPtr);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01page (layer : tgg00_Debug;
                    VAR n   : tbd_node;
                    start_p : tsp00_Int4;
                    stop_p  : tsp00_Int4);
 
        PROCEDURE
              t01int4 (layer : tgg00_Debug;
                    nam  : tsp00_Sname;
                    pno  : tsp00_Int4);
&       endif
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
        PROCEDURE
              b06dump_bad_page;
 
              tbd_univ_ptr tbd_nodeptr
 
        FUNCTION
              bd20IsPageExclusiveLocked;
 
              tbd02_pDataCBlock tbd_nodeptr
 
        PROCEDURE
              s30cmp1;
 
              tsp00_MoveObj tsp00_Key
&             ifdef TRACE
 
        PROCEDURE
              t01page;
 
              tsp00_Page tbd_node
&             endif
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : JuergenP
.sp
.cp 3
Created : 1979-11-15
.sp
.cp 3
.sp
.cp 3
Release :      Date : 1999-10-12
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
 
The routines described below operate on the nodes of the
current B* index.  The current B* index is the index section of
the B* tree that is determined by the last call of the routine
b30adjust_tree (see treehandling) to have been executed.  If
no such call exists, the effect of the routines is undefined.
.sp
The entries of the nodes of the B* index are called branches; the
nodes themselves are called branch nodes.  A branch consists of a key,
called a separator, and a pointer to the root of a subtree.  Each
node of the B* index is itself the root of a subtree that is
responsible for a closed key interval with the limits kmin and kmax
(i.e. it contains precisely those leaves whose entries must begin with
these keys, if they are contained in the tree).  Each branch node
contains at least two branches and the branches are sorted for each
node in ascending sequence by separators.
.sp
The first branch has the separator kmin.  For any pair of consecutive
branches with the separators s1 and s2 (s1 < s2), the following
applies: the branch with s1 points to the root of the subtree that is
responsible for the key interval from s1 [incl] to s2 (excl), that is
mathematically spoken the left closed right open interval [s1, s2).  The
last branch of a node with the separator s is responsible for the
closed key interval (s,kmax).
.sp
In the case of the branch node that forms the root of the B* tree,
kmin is always the lowest key and kmax is always the highest key
possible for the given key type.  The values of kmin and kmax for
all other nodes can be derived from the description above.  When
the first separator in a branch node is changed, it is important
to note that the separator for the branch that points to this node
(in the parent node) must also be changed; this means that the node
is 're-indexed'.  In addition, consecutive branches point to
neighboring nodes.
.sp
Each change in a branch node refers back to an order in an
order list provided for this purpose.  For a more detailed
description, see the module indexupdateorders.
.sp 2
   current
.sp
This variable contains the following information on the
current B* tree:
.sp ;.of 2
- the page number 'root' of the root of the tree,
.br ;.in ;.of 2
- the type ft of the file managed by the tree
(see filesysteminterface),
.br ;.in ;.of 2
- the type kt of the entry key (see filesysteminterface)
.br ;.in ;.of 2
- the type rkt of the record key in the inversion lists, if
the file is an inversion (see filesysteminterface)
.br ;.in ;.of 2
- the type st of the separators in the B* index (see indexing)
.br ;.in ;.of 2
- the buffer type bt, which depends on whether a temporary file,
the system file or another permanent file is involved
(see systembufferinterface VBD20).
.sp 2
   indexorderlist
.sp
In this list, information is managed for a possible index update
or an index reorganization
(see VBD54, indexupdateorders !).
.sp 2
   b51next_branch (n,bpos,last,current)
.sp
If the last branch of the node n begins at the position bpos,
'last' is set to TRUE.  Otherwise, 'last' is set to FALSE and
bpos supplies the beginning position of the next branch in n.
.sp 2
   b51search_branch(k,n,bpos,current)
.sp
This routine requires that the key k be located within the key
interval for which the subtree with the root n is responsible.  It
furnishes in bpos the beginning position of the branch that points
to the subtree responsible for k.
.sp 2
   b51add_branch(n,pos,left,sep,sepl,subroot,
                  indexorderlist,current,e)
.sp
This routine is called only to process the order currently being
run in the order list.  It forms a branch with the separator sep
of the length sepl and a pointer to the subtree root with the page
number subroot and inserts it in the node n at position pos.
After the branch has been inserted, the order being run is deleted
from the list.
.br
If the node n no longer has enough space available for the new branch,
the branch is not inserted; instead, the branches of the node and of
its left or right neighbor node are redistributed in order to create
enough space in each of the nodes involved for a new branch.  In this
case, the order currently being run remains in the order list.
.br
In any case, at the end of the routine, all nodes that have been
changed are written back.
Possible acknowledgements in e:
   - e_ok
   - b_no_more_space
   - b_disk_not_accessible
.sp 2
   b51del_branch(n,bpos,left,
                 indexorderlist,current,e)
.sp
This routine is called only to process the order currently being run
in the order list.  It deletes the branch beginning in node n at
position bpos from the node and deletes the order being run from the
order list.  If this was the first branch of the node, the node is
re-indexed; if, following the deletion, the node is underfilled
(see nodehandling), the branches of the node and of its left or right
neighbor node are redistributed in order to achieve a better balance
of the contents of the nodes.  At the end of the routine, all nodes
that have been changed are written back.
Possible acknowledgements in e:
   - e_ok
   - b_disk_not_accessible
.sp 2
   b51repl_branch(n,bpos,left,sep,sepl,subroot,
                  indexorderlist,current,e)
.sp
This routine is called only to process the order currently being
run in the order list.  It forms a new branch with the separator sep
of the length sepl and a pointer to the subtree root with the page
number subroot and substitutes it for the branch beginning in
node n at position bpos.  This requires that the order of branches
in the node be retained throughout.  After the replacement has been
executed, the order being run is deleted from the list.
.br
If the first branch of the node is replaced, the node is re-indexed.
.br
If the new branch is longer than the branch it is replacing and the
node no longer has enough space available, the routine proceeds as
described in b51add_branch.
.br
If the new branch is shorter than the branch it is replacing and
the node is then underfilled, the routine proceeds as described in
b51del_branch.
.br
In any case, at the end of the routine, all nodes that have been
changed are written back.
Possible acknowledgements in e:
   - e_ok
   - b_no_more_space
   - b_disk_not_accessible
.sp 2
   b51new_branchroot(n,sep,sepl,rightsubroot,
                         indexorderlist,current,e)
.sp
This routine requires that n be the current root of the current
B* tree.  It creates a new root with the following two branches:
the first has a minimum key as its separator and points to the
current root; the second has the separator sep of the length sepl
and points to the subtree root with the page number rightsubroot.
the new root is assigned the same page number as the former one,
whereas the node n receives a new page number!  At the end of
the routine, all the nodes that have been changed are written
back.
Possible acknowledgements in e:
   - e_ok
   - b_no_more_space
   - b_disk_not_accessible
.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
 
Each branch of a branch node is implemented by a branch entry
in the body of the node.  The branch entries are stored in each node
beginning at body_beg by their logical sequence (ascending order
by separators) and in physically consecutive order.  During a
reorganization they are not split, so that nothing is ever appended
to the branch nodes.
.sp
The length of a branch entry is very small compared to the maximum
contents of a node; moreover, operations that modify the B* index (as
opposed to the read routines) are very rare.  These two suppositions
are the dominating features in the outline of B* index reorganization:
if there is no space found in the node for a new entry, first a
reorganization of the B* index is carried out in which
enough space is made available in the node concerned for a new branch
entry of the maximum length.  The order for inserting the new (or
replacing the old) branch must again be carried out.  Normally, if it is
determined after the deletion or replacement of a branch entry that
the node is underfilled, a reorganization of the B* index is carried
out.  No reorganization is carried out, however, if an order for the
re-indexing of a node is pending in order to keep the reorganization
from becoming too extensive.
.sp
The only way the B* index can be expanded by one level is by calling
b51new_branchroot; page numbers are exchanged so that the root of
the B* tree remains the same.  If the current root was a leaf, all
pointers to this leaf are deleted from the key memory so that the
exchange of page numbers does not result in an inconsistent state.
If, after a branch is deleted from the root of the B* tree, only
one branch remains in the node (dummy_root), the root is replaced
by the root of its only subtree; in this case as well, page numbers
are exchanged so that the page number of the root of the B* tree remains
the same.  This is the only case in which the B* tree can shrink
by a level.
.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:
 
.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :
 
 
CONST
      MSG_NOT_EXCL_LOCKED = 'Index is not excl locked';
 
 
(*------------------------------*) 
 
PROCEDURE
      b51add_branch (VAR nptr  : tbd_node_ptrs;
            index              : tsp00_Int4;
            left               : tsp00_PageNo;
            VAR separator      : tbd00_Separator;
            VAR indexorderlist : tbd00_OrderList;
            VAR current        : tbd_current_tree);
 
VAR
      RecPos    : tsp00_Int4;
      amount    : tsp00_Int4;
 
BEGIN
WITH separator, current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    IF  (sepHead_bd00.hrecLen_gg00 < sizeof (sepHead_bd00))  OR
        (sepHead_bd00.hrecLen_gg00 > sizeof (separator)   )
    THEN
        trError_gg00 := e_illegal_branchlength;
&   ifdef TRACE
    (*ENDIF*) 
    t01int4 (bd_index, 'index       ', index);
    t01int4 (bd_index, 'sep length  ', sepHead_bd00.hrecLen_gg00);
    t01int4 (bd_index, 'bottom      ', np_ptr^.nd_bottom);
    t01int4 (bd_index, 'rec count   ', np_ptr^.nd_record_cnt);
&   endif
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  g01glob.bd_lock_check AND (NOT bd20IsPageExclusiveLocked (np_cbptr))
        THEN
            g01abort (csp3_bd_msg, csp3_n_btree, MSG_NOT_EXCL_LOCKED, np_ptr^.nd_id);
        (*ENDIF*) 
        IF  (np_ptr^.nd_bottom + sepHead_bd00.hrecLen_gg00) >
            (MAX_BOTTOM_BD00 - ((np_ptr^.nd_record_cnt + 1) * POINTERSIZE_BD00))
        THEN
            WITH np_ptr^ DO
                BEGIN
                IF  NOT nd_sorted
                THEN
                    b51sort_branches (np_ptr, curr_trans);
                (*ENDIF*) 
                curr_lvl_1_pno := NIL_PAGE_NO_GG00;
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    IF  (nd_right = NIL_PAGE_NO_GG00) AND (index >= nd_record_cnt)
                    THEN
                        b55app_new_indexnode (nptr, separator, indexorderlist, current)
                    ELSE
                        b55p_oflw_branch (nptr, gg06Align (sepHead_bd00.hrecLen_gg00,
                              REC_ALIGN_BD00), left, indexorderlist, current)
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDWITH*) 
        ELSE
            WITH np_ptr^ DO
                BEGIN
&               ifdef TRACE
                t01page (bd_index, np_ptr^, 1, nd_bottom);
&               endif
                RecPos    := nd_bottom;
                nd_bottom := nd_bottom + gg06Align (sepHead_bd00.hrecLen_gg00, REC_ALIGN_BD00);
                (*  put branch *)
                SAPDB_PascalMove ('VBD51 ',   1,    
                      sizeof (separator), sizeof (np_ptr^),
                      @separator, 1, @np_ptr^, RecPos, sepHead_bd00.hrecLen_gg00, trError_gg00);
                IF  trError_gg00 = e_move_error
                THEN
                    BEGIN
                    trError_gg00 := e_data_page_corrupted;
                    b06dump_bad_page (trTaskId_gg00, 'd',
                          FILE_EXT_COR_BD00, nd_id, np_ptr, 1)
                    END
                ELSE
                    BEGIN
&                   ifdef TRACE
                    t01page (bd_index, np_ptr^, 1, nd_bottom);
                    t01page (bd_index, np_ptr^,
                          MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00) ,
                          sizeof (np_ptr^));
&                   endif
                    (*  list update *)
                    amount := (nd_record_cnt - index) * POINTERSIZE_BD00;
                    IF  amount > 0
                    THEN
                        BEGIN
                        SAPDB_PascalOverlappingMove ('VBD51 ',   2,    
                              sizeof (np_ptr^), sizeof (np_ptr^),
                              @np_ptr^, (MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00)),
                              @np_ptr^, MAX_BOTTOM_BD00 - ((nd_record_cnt + 1) * POINTERSIZE_BD00),
                              amount, 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;
&                   ifdef TRACE
                    (*ENDIF*) 
                    t01page (bd_index, np_ptr^,
                          MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00),
                          sizeof (np_ptr^));
&                   endif
                    nd_record_cnt           := succ (nd_record_cnt);
                    nd_sorted               := false;
                    nd_pointer_list [MAX_POINTERINDEX_BD00 - index] := RecPos;
&                   ifdef TRACE
                    t01page (bd_index, np_ptr^,
                          MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00),
                          sizeof (np_ptr^));
&                   endif
                    WITH indexorderlist DO
                        olstCount_bd00 := pred (olstCount_bd00);
                    (*ENDWITH*) 
                    END;
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    IF  (nd_level > succ (LEAF_LEVEL_BD00)) OR
                        (indexorderlist.olstCount_bd00 = 0) OR
                        (curr_lvl_1_pno = NIL_PAGE_NO_GG00)
                    THEN
                        b13w_release_node (nptr, current)
                    (*ENDIF*) 
                (*ENDIF*) 
                END
            (*ENDWITH*) 
        (*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
      b51del_branch (VAR nptr  : tbd_node_ptrs;
            index              : tsp00_Int4;
            left               : tsp00_PageNo;
            VAR indexorderlist : tbd00_OrderList;
            VAR current        : tbd_current_tree);
 
VAR
      is_dummy         : boolean;
      underflow        : boolean;
      lno              : tsp00_Int2;
      RecLen           : tsp00_Int4;
      DelSpaceLen      : tsp00_Int4;
      i                : tsp00_Int4;
      RecPos           : tsp00_Int4;
      next             : tsp00_PageNo;
      pRec             : tgg00_RecPtr;
      nnptr            : tbd_node_ptrs;
      OldSepKey        : tgg00_Lkey;
      NewSepKey        : tgg00_Lkey;
 
BEGIN
WITH nptr.np_ptr^, current, curr_tree_id, curr_trans^ DO
    BEGIN
&   ifdef TRACE
    t01int4 (bd_index, 'curr pageNo ', nptr.np_ptr^.nd_id);
    t01int4 (bd_index, 'rec Index   ', index);
    IF  left <> NIL_PAGE_NO_GG00
    THEN
        t01int4 (bd_index, 'left pageNo ', left);
    (*ENDIF*) 
    t01page  (bd_index, nptr.np_ptr^, 1, nd_bottom);
    t01page  (bd_index, nptr.np_ptr^,
          MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00), sizeof (nptr.np_ptr^));
&   endif
    IF  g01glob.bd_lock_check AND (NOT bd20IsPageExclusiveLocked (nptr.np_cbptr))
    THEN
        g01abort (csp3_bd_msg, csp3_n_btree, MSG_NOT_EXCL_LOCKED, nd_id);
    (*ENDIF*) 
    nnptr.np_ptr   := NIL;
    nnptr.np_cbptr := NIL;
    is_dummy       := false;
    WITH indexorderlist DO
        olstCount_bd00 := pred (olstCount_bd00);
    (*ENDWITH*) 
    IF  index = FIRST_REC_INDEX_BD00
    THEN
        bd52GetSepKey (nptr.np_ptr, index, OldSepKey, curr_trans);
    (*ENDIF*) 
    pRec        := @nd_body [nd_pointer_list [MAX_POINTERINDEX_BD00 - index]];
    RecLen      := pRec^.recLen_gg00;
    DelSpaceLen := gg06Align (RecLen, REC_ALIGN_BD00);
    RecPos      := nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
    b35del_space (nptr.np_ptr, RecPos, DelSpaceLen, curr_trans);
    (*  list update *)
    FOR i := FIRST_REC_INDEX_BD00 TO nd_record_cnt - 1 DO
        BEGIN
        IF  nd_pointer_list [MAX_POINTERINDEX_BD00 - i] > RecPos
        THEN
            nd_pointer_list [MAX_POINTERINDEX_BD00 - i] :=
                  nd_pointer_list [MAX_POINTERINDEX_BD00 - i] - DelSpaceLen
        (*ENDIF*) 
        END;
    (*ENDFOR*) 
    IF  (index < nd_record_cnt - 1) AND (trError_gg00 = e_ok)
    THEN
        BEGIN
        SAPDB_PascalOverlappingMove ('VBD51 ',   3,    
              sizeof (nptr.np_ptr^), sizeof (nptr.np_ptr^),
              @nptr.np_ptr^, MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00),
              @nptr.np_ptr^, MAX_BOTTOM_BD00 - ((nd_record_cnt - 1) * POINTERSIZE_BD00),
              ((nd_record_cnt - 1) - index) * POINTERSIZE_BD00, 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.np_ptr, 1)
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        nd_record_cnt := pred (nd_record_cnt);
        IF  (index = FIRST_REC_INDEX_BD00) AND (left = NIL_PAGE_NO_GG00)
        THEN
            IF  nd_bottom > BODY_BEG_BD00
            THEN
                BEGIN
                (* *)
                (* leftmost index node *)
                (* replace first separator by empty separator (key length 0) *)
                (* *)
                RecPos               := nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
                pRec                 := @nd_body [RecPos];
                DelSpaceLen          := gg06Align (pRec^.recKeyLen_gg00, REC_ALIGN_BD00);
                pRec^.recKeyLen_gg00 := 0;
                pRec^.recLen_gg00    := sizeof (pRec^.recHead_gg00) + sizeof (tbd00_SepLeafCount);
                IF  DelSpaceLen > 0
                THEN
                    b35del_space (nptr.np_ptr, RecPos + pRec^.recLen_gg00,
                          DelSpaceLen, curr_trans);
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    IF  DelSpaceLen > 0
                    THEN
                        FOR i := FIRST_REC_INDEX_BD00 TO nd_record_cnt - 1 DO
                            BEGIN
                            IF  nd_pointer_list [MAX_POINTERINDEX_BD00 - i] > RecPos
                            THEN
                                nd_pointer_list [MAX_POINTERINDEX_BD00 - i] :=
                                      nd_pointer_list [MAX_POINTERINDEX_BD00 - i] - DelSpaceLen
                            (*ENDIF*) 
                            END;
                        (*ENDFOR*) 
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            ELSE
                IF  nd_right <> NIL_PAGE_NO_GG00
                THEN
                    BEGIN
                    (* *)
                    (* nd_right is new leftmost index node replace 1.*)
                    (*  separator by empty separator (length 0)      *)
                    (* *)
                    bd13GetNode (current, nd_right, plmLock_ebd00, nr_for_update, nnptr);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        RecPos               :=
                              nnptr.np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
                        pRec                 := @nnptr.np_ptr^.nd_body [RecPos];
                        DelSpaceLen          := gg06Align (pRec^.recKeyLen_gg00, REC_ALIGN_BD00);
                        pRec^.recKeyLen_gg00 := 0;
                        pRec^.recLen_gg00    :=
                              sizeof (pRec^.recHead_gg00) + sizeof (tbd00_SepLeafCount);
                        IF  DelSpaceLen > 0
                        THEN
                            b35del_space (nnptr.np_ptr, RecPos + pRec^.recLen_gg00,
                                  DelSpaceLen, curr_trans);
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            WITH nnptr, np_ptr^ DO
                                BEGIN
                                IF  DelSpaceLen > 0
                                THEN
                                    FOR i := FIRST_REC_INDEX_BD00 TO nd_record_cnt - 1 DO
                                        BEGIN
                                        IF  nd_pointer_list [MAX_POINTERINDEX_BD00 - i] > RecPos
                                        THEN
                                            nd_pointer_list [MAX_POINTERINDEX_BD00 - i] :=
                                                  nd_pointer_list [MAX_POINTERINDEX_BD00 - i] - DelSpaceLen
                                        (*ENDIF*) 
                                        END;
                                    (*ENDFOR*) 
                                (*ENDIF*) 
                                b13w_release_node (nnptr, current)
                                END
                            (*ENDWITH*) 
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDIF*) 
        IF  (index = FIRST_REC_INDEX_BD00) AND
            (nd_id <> fileRoot_gg00      ) AND
            (nd_bottom > BODY_BEG_BD00   ) AND
            (left <> NIL_PAGE_NO_GG00    )
        THEN
            BEGIN
            bd52GetSepKey (nptr.np_ptr, index, NewSepKey, curr_trans);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                lno            := nd_level;
                curr_lvl_1_pno := NIL_PAGE_NO_GG00;
                b54repl_index (@OldSepKey.keyVal_gg00, OldSepKey.keyLen_gg00,
                      @NewSepKey.keyVal_gg00, NewSepKey.keyLen_gg00,
                      nd_id, lno, indexorderlist);
                b13w_release_node (nptr, current)
                END
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            IF  (nd_id <> fileRoot_gg00) AND (nd_bottom = BODY_BEG_BD00)
            THEN
                BEGIN
                IF  left <> NIL_PAGE_NO_GG00
                THEN
                    BEGIN
                    (*  divert pointer from left node *)
                    bd13GetNode (current, left, plmLock_ebd00, nr_for_update, nnptr);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        next := nnptr.np_ptr^.nd_right;
                        IF  next = nd_id
                        THEN
                            nnptr.np_ptr^.nd_right := nd_right
                        ELSE
                            trError_gg00 := e_invalid_index_structure
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        b13w_release_node (nnptr, current)
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    lno := nd_level;
                    b54del_index (@OldSepKey.keyVal_gg00, OldSepKey.keyLen_gg00,
                          lno, indexorderlist);
                    b54execute_indexorder (indexorderlist, current);
                    IF  trError_gg00 = e_ok
                    THEN
                        b13free_node (nptr, current);
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                IF  ftsDynamic_egg00 IN fileType_gg00
                THEN
                    underflow :=
                          (nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00)
                          < QUATER_COVERING_BD00)
                          AND
                          (nd_id <> fileRoot_gg00)
                ELSE
                    underflow :=
                          (nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00)
                          < HALF_COVERING_BD00)
                          AND
                          (nd_id <> fileRoot_gg00);
                (*ENDIF*) 
                IF  underflow
                THEN
                    BEGIN
                    curr_lvl_1_pno := NIL_PAGE_NO_GG00;
                    IF  NOT nd_sorted
                    THEN
                        b51sort_branches (nptr.np_ptr, curr_trans);
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        b55p_uflw_branch (nptr, left, indexorderlist, current)
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    bd51dummy_root (nptr, is_dummy, current);
                    IF  (trError_gg00 = e_ok) AND is_dummy
                    THEN
                        BEGIN
                        curr_lvl_1_pno := NIL_PAGE_NO_GG00;
                        bd51del_branchroot (nptr, current)
                        END
                    ELSE
                        BEGIN
                        IF  (nd_level > succ (LEAF_LEVEL_BD00 )) OR
                            (indexorderlist.olstCount_bd00 = 0 ) OR
                            (curr_lvl_1_pno = NIL_PAGE_NO_GG00 )
                        THEN
                            b13w_release_node (nptr, current)
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 <> e_ok
    THEN
        BEGIN
        IF  nptr.np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  nnptr.np_ptr <> NIL
        THEN
            b13r_release_node (nnptr, current, lru_normal)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b51divert_rightnext (left : tsp00_PageNo;
            old_right   : tsp00_PageNo;
            new_right   : tsp00_PageNo;
            VAR current : tbd_current_tree);
 
VAR
      nptr : tbd_node_ptrs;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    bd13GetNode (current, left, plmLock_ebd00, nr_for_update, nptr);
    IF  trError_gg00 = e_ok
    THEN
        IF  (ftsPerm_egg00 in fileType_gg00) AND (NOT (hsNoLog_egg00 in fileHandling_gg00))
        THEN
            IF  nptr.np_ptr^.nd_right = old_right
            THEN
                BEGIN
                nptr.np_ptr^.nd_right := new_right;
                b13w_release_node (nptr, current)
                END
            ELSE
                BEGIN
                trError_gg00 := e_invalid_leaves_structure;
                b13r_release_node (nptr, current, lru_normal)
                END
            (*ENDIF*) 
        ELSE
            BEGIN
            nptr.np_ptr^.nd_right := new_right;
            b13w_release_node (nptr, current)
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b51ldivert_leftnext (right : tsp00_PageNo;
            new_left    : tsp00_PageNo;
            VAR current : tbd_current_tree);
 
VAR
      nptr : tbd_node_ptrs;
 
BEGIN
WITH current.curr_trans^ DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    bd13GetNode (current, right, plmLock_ebd00, nr_for_update, nptr);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        nptr.np_ptr^.nd_left := new_left;
        b13w_release_node (nptr, current)
        END;
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b51new_branchroot (VAR nptr : tbd_node_ptrs;
            VAR RightSeparator : tbd00_Separator;
            VAR indexorderlist : tbd00_OrderList;
            VAR current        : tbd_current_tree);
 
VAR
      lno             : tsp00_Int2;
      RecIndex        : tsp00_Int4;
      PointerListSize : tsp00_Int4;
      new_leftptr     : tbd_node_ptrs;
      leftsubroot     : tsp00_PageNo;
      rightsubroot    : tsp00_PageNo;
      LeftSeparator   : tbd00_Separator;
      pRec            : tgg00_RecPtr;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    (* *)
    (* nptr^.nd_id = current.fileRoot_gg00*)
    (* *)
&   ifdef TRACE
    t01int4 (bd_index, 'nd_right    ',nptr.np_ptr^.nd_right);
&   endif
    lno                  := nptr.np_ptr^.nd_level;
    curr_lvl_1_pno       := NIL_PAGE_NO_GG00;
    new_leftptr.np_ptr   := NIL;
    new_leftptr.np_cbptr := NIL;
    rightsubroot         := nptr.np_ptr^.nd_right;
    b13new_node (lno, new_leftptr, current);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        (* *)
        (* Move only content of root into new node. No    *)
        (* modification of header and trailer. Exception: *)
        (* nd_bottom, nd_record_cnt and nd_right.         *)
        (* *)
        IF  lno = LEAF_LEVEL_BD00
        THEN
            BEGIN
            (* because of content switch new page *)
            (* has to be treated as an index page *)
            currLeafPageCountDelta_bd00  := currLeafPageCountDelta_bd00  -1;
            currIndexPageCountDelta_bd00 := currIndexPageCountDelta_bd00 +1;
            END;
        (*ENDIF*) 
        leftsubroot := new_leftptr.np_ptr^.nd_id;
        SAPDB_PascalMove ('VBD51 ',   4,    
              sizeof (nptr.np_ptr^), sizeof (new_leftptr.np_ptr^),
              @nptr.np_ptr^, BODY_BEG_BD00,
              @new_leftptr.np_ptr^, BODY_BEG_BD00,
              nptr.np_ptr^.nd_bottom - BODY_BEG_BD00, trError_gg00);
        (* *)
        PointerListSize := nptr.np_ptr^.nd_record_cnt * POINTERSIZE_BD00;
        SAPDB_PascalMove ('VBD51 ',   5,    
              sizeof (nptr.np_ptr^), sizeof (new_leftptr.np_ptr^),
              @nptr.np_ptr^, MAX_BOTTOM_BD00 - PointerListSize,
              @new_leftptr.np_ptr^, MAX_BOTTOM_BD00 - PointerListSize,
              PointerListSize, 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*) 
        IF  trError_gg00 = e_ok
        THEN
            WITH new_leftptr, np_ptr^ DO
                BEGIN
                nd_bottom     := nptr.np_ptr^.nd_bottom;
                nd_record_cnt := nptr.np_ptr^.nd_record_cnt;
                IF  lno > LEAF_LEVEL_BD00
                THEN
                    nd_right := rightsubroot
                ELSE
                    (* temporary nptr.np_ptr^.nd_right could be *)
                    (* not equal to NIL_PAGE_NO_GG00             *)
                    nd_right := nptr.np_ptr^.nd_right;
                (*ENDIF*) 
                IF  (ftsTemp_egg00 in fileType_gg00) AND
                    (lno = LEAF_LEVEL_BD00         )
                THEN
                    b51ldivert_leftnext (nd_right, leftsubroot, current)
                (*ENDIF*) 
                END
            (*ENDWITH*) 
        ELSE
            b13free_node (new_leftptr, current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b13w_release_node (new_leftptr, current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            WITH nptr.np_ptr^ DO
                BEGIN
                (* *)
                (* Adjust new root page *)
                (* *)
                nd_id                   := fileRoot_gg00;
                nd_checktype            := chckChecksumData_egg00;
                nd_sorted               := false;
                nd_write_cnt            := 0;
                nd_checksum             := 0;
                nd_level                := succ (lno);
                nd_right                := NIL_PAGE_NO_GG00;
                ndLeafCount_bd00        := 0;
                nd_bottom               := BODY_BEG_BD00;
                RecIndex                := FIRST_REC_INDEX_BD00;
                nd_pointer_list [MAX_POINTERINDEX_BD00 - RecIndex] := nd_bottom;
                nd_record_cnt           := 1;
                nd_trailer              := nd_header;
                (* *)
                (* min index *)
                (* *)
                WITH LeftSeparator.sepHead_bd00 DO
                    BEGIN
                    hrecKeyLen_gg00 := 0;
                    hrecLen_gg00    := sizeof (LeftSeparator.sepHead_bd00)
                          + sizeof (tbd00_SepLeafCount);
                    gg06PnoPut (LeftSeparator.sepHead_bd00.hrecPno_gg00, leftsubroot)
                    END;
                (*ENDWITH*) 
&               ifdef TRACE
                t01page (bd_index, nptr.np_ptr^, 1, sizeof (nd_full_header));
&               endif
                bd52PutSeparatorIntoNode  (nptr.np_ptr, RecIndex, LeftSeparator, curr_trans);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    pRec := @nptr.np_ptr^.nd_body [nd_bottom];
                    bd52PutSepLeafCount (pRec, 0);
                    nd_bottom := BODY_BEG_BD00 + gg06Align (LeftSeparator.sepHead_bd00.hrecLen_gg00, REC_ALIGN_BD00);
&                   ifdef TRACE
                    t01page (bd_index, nptr.np_ptr^, 1, nd_bottom);
&                   endif
                    RecIndex                                           := succ (FIRST_REC_INDEX_BD00);
                    nd_pointer_list [MAX_POINTERINDEX_BD00 - RecIndex] := nd_bottom;
                    nd_record_cnt                                      := succ (nd_record_cnt);
                    bd52PutSeparatorIntoNode (nptr.np_ptr, RecIndex, RightSeparator, curr_trans);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        pRec := @nptr.np_ptr^.nd_body [nd_bottom];
                        bd52PutSepLeafCount (pRec, 0);
                        nd_bottom := nd_bottom + gg06Align (RightSeparator.sepHead_bd00.hrecLen_gg00, REC_ALIGN_BD00);
&                       ifdef TRACE
                        t01page (bd_index, nptr.np_ptr^, 1, nd_bottom);
                        t01page (bd_index, nptr.np_ptr^,
                              MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00), sizeof (nptr.np_ptr^));
&                       endif
                        WITH indexorderlist DO
                            olstCount_bd00 := pred (olstCount_bd00);
                        (*ENDWITH*) 
                        b13w_release_node (nptr, current)
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDWITH*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 <> e_ok
    THEN
        BEGIN
        IF  nptr.np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  new_leftptr.np_ptr <> NIL
        THEN
            b13r_release_node (new_leftptr, current, lru_normal)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b51next_branch (VAR nptr : tbd_nodeptr;
            VAR index : integer;
            VAR last  : boolean);
 
BEGIN
IF  (nptr^.nd_record_cnt - 1 = index)
THEN
    last := true
ELSE
    BEGIN
    last  := false;
    index := succ (index)
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b51pointer_list (VAR nptr : tbd_nodeptr);
 
VAR
      Finish   : boolean;
      RecIndex : tsp00_Int4;
      RecPos   : tsp00_Int4;
      pRec     : tgg00_RecPtr;
 
BEGIN
WITH nptr^ DO
    BEGIN
    RecIndex := FIRST_REC_INDEX_BD00;
    RecPos   := BODY_BEG_BD00;
    Finish   := false;
    REPEAT
        nd_pointer_list [MAX_POINTERINDEX_BD00 - RecIndex] := RecPos;
        pRec   := @nd_body [ RecPos];
        RecPos := RecPos + gg06Align (pRec^.recLen_gg00, REC_ALIGN_BD00);
        IF  RecPos >= nd_bottom
        THEN
            Finish := true
        ELSE
            RecIndex := succ (RecIndex)
        (*ENDIF*) 
    UNTIL
        Finish;
    (*ENDREPEAT*) 
    nd_record_cnt := RecIndex + 1
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b51repl_branch (VAR nptr : tbd_node_ptrs;
            index              : tsp00_Int4;
            left               : tsp00_PageNo;
            VAR separator      : tbd00_Separator;
            VAR indexorderlist : tbd00_OrderList;
            VAR current        : tbd_current_tree);
 
VAR
      l_result  : tsp00_LcompResult;
      lno       : tsp00_Int2;
      i         : tsp00_Int4;
      bpos      : tsp00_Int4;
      diff      : tsp00_Int4;
      OldRecLen : tsp00_Int4;
      pRec      : tgg00_RecPtr;
      rnptr     : tbd_node_ptrs;
      OldSepKey : tgg00_Lkey;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    IF  index = FIRST_REC_INDEX_BD00
    THEN
        bd52GetSepKey (np_ptr, index, OldSepKey, curr_trans);
    (*ENDIF*) 
    pRec      := @np_ptr^.nd_body [np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - index]];
    OldRecLen := pRec^.recLen_gg00;
    IF  (pRec^.recPno_gg00 <> separator.sepHead_bd00.hrecPno_gg00)
    THEN
        BEGIN
        trError_gg00 := e_invalid_index_structure;
        b06write_filename_and_root( curr_tree_id );
        b06dump_bad_page (trTaskId_gg00, 'd',
              FILE_EXT_COR_BD00, np_ptr^.nd_id, np_ptr, 1);
        g01opmsg (sp3p_console, sp3m_error,
              csp3_b51x1_invalid_separator, csp3_n_btree,
              'B51: SepPno Update      ', np_ptr^.nd_id);
        g01opmsg (sp3p_console, sp3m_error,
              csp3_b51x1_invalid_separator, csp3_n_btree,
              'B51:    OldSepPno       ', gg06PnoGet(pRec^.recPno_gg00));
        g01abort (csp3_b51x1_invalid_separator, csp3_n_btree,
              'B51:    NewSepPno       ', gg06PnoGet(separator.sepHead_bd00.hrecPno_gg00));
        END;
    (* *)
    (* +++security check , 'cause of problems with R3 port (BEGIN)+++ *)
    (*ENDIF*) 
    IF  (index < np_ptr^.nd_record_cnt - 1)
    THEN
        BEGIN
        (* not greatest key on page *)
        pRec := @np_ptr^.nd_body [np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - (index + 1)]];
        WITH separator DO
            s30cmp1 (sepKey_bd00.keyVal_gg00, 1, sepKey_bd00.keyLen_gg00,
                  pRec^.recKey_gg00.keyVal_gg00, 1, pRec^.recKeyLen_gg00, l_result);
        (*ENDWITH*) 
        IF  l_result = l_greater
        THEN
            BEGIN
            trError_gg00 := e_invalid_index_structure;
            b06dump_bad_page (trTaskId_gg00, 'd',
                  FILE_EXT_COR_BD00, np_ptr^.nd_id, np_ptr, 1);
            b06write_filename_and_root( curr_tree_id );
            g01opmsg (sp3p_console, sp3m_error,
                  csp3_b51x1_invalid_separator, csp3_n_btree,
                  'B51: new_sep > next_sep ', index);
            g01abort (csp3_b51x1_invalid_separator, csp3_n_btree,
                  'B51: new_sep > next_sep ', index);
            END
        (*ENDIF*) 
        END
    ELSE
        IF  np_ptr^.nd_right <> NIL_PAGE_NO_GG00
        THEN
            BEGIN
            rnptr.np_ptr := NIL;
            bd13GetNode (current, np_ptr^.nd_right, plmLock_ebd00, nr_for_read, rnptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                pRec := @rnptr.np_ptr^.nd_body [rnptr.np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00]];
                WITH separator DO
                    s30cmp1 (sepKey_bd00.keyVal_gg00, 1, sepKey_bd00.keyLen_gg00,
                          pRec^.recKey_gg00.keyVal_gg00, 1, pRec^.recKeyLen_gg00, l_result);
                (*ENDWITH*) 
                IF  l_result = l_greater
                THEN
                    BEGIN
                    trError_gg00 := e_invalid_index_structure;
                    b06dump_bad_page (trTaskId_gg00, 'd',
                          FILE_EXT_COR_BD00, np_ptr^.nd_id, np_ptr, 1);
                    b06write_filename_and_root( curr_tree_id );
                    g01opmsg (sp3p_console, sp3m_error,
                          csp3_b51x2_invalid_separator,
                          csp3_n_btree, 'B51: new_sep > next_sep ',
                          index);
                    g01abort (csp3_b51x2_invalid_separator, csp3_n_btree,
                          'B51: new_sep > next_sep ', index);
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  rnptr.np_ptr <> NIL
            THEN
                b13r_release_node (rnptr, current, lru_normal)
            (*ENDIF*) 
            END;
        (* *)
        (* +++security check , 'cause of problems with R3 port (END) +++ *)
        (*ENDIF*) 
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  g01glob.bd_lock_check AND (NOT bd20IsPageExclusiveLocked (np_cbptr))
        THEN
            g01abort (csp3_bd_msg, csp3_n_btree, MSG_NOT_EXCL_LOCKED, np_ptr^.nd_id);
        (*ENDIF*) 
        IF  np_ptr^.nd_bottom + (separator.sepHead_bd00.hrecLen_gg00 - OldRecLen) >
            MAX_BOTTOM_BD00 - (np_ptr^.nd_record_cnt * POINTERSIZE_BD00)
        THEN
            BEGIN
            IF  NOT np_ptr^.nd_sorted
            THEN
                b51sort_branches (np_ptr, curr_trans);
            (*ENDIF*) 
            curr_lvl_1_pno := NIL_PAGE_NO_GG00;
            diff           := gg06Align (separator.sepHead_bd00.hrecLen_gg00, REC_ALIGN_BD00) -
                  gg06Align (OldRecLen, REC_ALIGN_BD00);
            IF  trError_gg00 = e_ok
            THEN
                b55p_oflw_branch (nptr, diff, left, indexorderlist, current)
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            bpos := np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
            diff := 0;
            IF  separator.sepHead_bd00.hrecLen_gg00 > OldRecLen
            THEN
                BEGIN
                diff := gg06Align (separator.sepHead_bd00.hrecLen_gg00, REC_ALIGN_BD00) -
                      gg06Align (OldRecLen, REC_ALIGN_BD00);
                b35add_space (np_ptr, bpos, diff, curr_trans)
                END
            ELSE
                IF  separator.sepHead_bd00.hrecLen_gg00 < OldRecLen
                THEN
                    BEGIN
                    diff := gg06Align (separator.sepHead_bd00.hrecLen_gg00, REC_ALIGN_BD00) -
                          gg06Align (OldRecLen, REC_ALIGN_BD00) ;
                    b35del_space (np_ptr, bpos, abs (diff), curr_trans)
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                bd52PutSeparatorIntoNode (np_ptr, index, separator, curr_trans);
                IF  diff <> 0
                THEN
                    FOR i := FIRST_REC_INDEX_BD00 TO np_ptr^.nd_record_cnt - 1 DO
                        BEGIN
                        IF  np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - i] > bpos
                        THEN
                            np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - i] :=
                                  np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - i] + diff
                        (*ENDIF*) 
                        END;
                    (*ENDFOR*) 
                (*ENDIF*) 
                WITH indexorderlist DO
                    olstCount_bd00 := pred (olstCount_bd00);
                (*ENDWITH*) 
                IF  (index = FIRST_REC_INDEX_BD00  ) AND
                    (np_ptr^.nd_id <> fileRoot_gg00)
                THEN
                    BEGIN
                    lno            := np_ptr^.nd_level;
                    curr_lvl_1_pno := NIL_PAGE_NO_GG00;
                    b54repl_index (@OldSepKey.keyVal_gg00, OldSepKey.keyLen_gg00,
                          @separator.sepKey_bd00.keyVal_gg00, separator.sepKey_bd00.keyLen_gg00,
                          np_ptr^.nd_id, lno, indexorderlist);
                    b13w_release_node (nptr, current)
                    END
                ELSE
                    BEGIN
                    IF  (np_ptr^.nd_level > succ (LEAF_LEVEL_BD00)) OR
                        (indexorderlist.olstCount_bd00 = 0        ) OR
                        (curr_lvl_1_pno = NIL_PAGE_NO_GG00        )
                    THEN
                        b13w_release_node (nptr, current)
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd51SearchBranch (VAR Current : tbd_current_tree;
            pSepKey      : tsp00_KeyAddr;
            KeyLen       : tsp00_Int4;
            VAR Nptr     : tbd_nodeptr;
            VAR RecIndex : tsp00_Int4);
 
VAR
      Found      : boolean;
      LResult    : tsp00_LcompResult;
      LowerBound : tsp00_Int4;
      UpperBound : tsp00_Int4;
      Count      : tsp00_Int4;
      RecPos     : tsp00_Int4;
      pRec       : tgg00_RecPtr;
 
BEGIN
WITH Current, curr_trans^, Nptr^ DO
    BEGIN
    IF  pSepKey = NIL
    THEN
        RecIndex := FIRST_REC_INDEX_BD00
    ELSE
        BEGIN
        (*  upb <= lwb *)
        UpperBound := nd_record_cnt - 1;
        LowerBound := FIRST_REC_INDEX_BD00;
        Found := false;
        REPEAT
            Count := UpperBound - LowerBound + 1;
            IF  Count > 2
            THEN
                BEGIN
                RecIndex := UpperBound - (Count DIV 2);
                RecPos   := nd_pointer_list [MAX_POINTERINDEX_BD00 - RecIndex];
                pRec     := @nd_body [RecPos];
                IF  pRec^.recLen_gg00 > sizeof (tbd00_Separator)
                THEN
                    trError_gg00 := e_illegal_branchlength;
                (*ENDIF*) 
                s30cmp1 (pSepKey^, 1, KeyLen,
                      pRec^.recKey_gg00.keyVal_gg00, 1,
                      pRec^.recKeyLen_gg00, LResult);
                IF  LResult = l_greater
                THEN
                    LowerBound := RecIndex
                ELSE
                    IF  LResult = l_less
                    THEN
                        UpperBound := RecIndex
                    ELSE (*  LResult = l_equal *)
                        Found := true;
                    (*ENDIF*) 
                (*ENDIF*) 
                END (*  count > 2 *)
            ELSE
                BEGIN
                RecIndex := UpperBound;
                RecPos   := nd_pointer_list [MAX_POINTERINDEX_BD00 - RecIndex];
                pRec     := @nd_body [RecPos];
                IF  pRec^.recLen_gg00 > sizeof (tbd00_Separator)
                THEN
                    trError_gg00 := e_illegal_branchlength;
                (*ENDIF*) 
                s30cmp1 (pSepKey^, 1, KeyLen,
                      pRec^.recKey_gg00.keyVal_gg00, 1,
                      pRec^.recKeyLen_gg00, LResult);
                IF  (LResult = l_greater) OR (LResult = l_equal)
                THEN
                    RecIndex := UpperBound
                ELSE
                    RecIndex := LowerBound;
                (*ENDIF*) 
                Found := true
                END
            (*ENDIF*) 
        UNTIL
            Found
        (*ENDREPEAT*) 
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
&ifdef TRACE
t01int4 (bd_index,'RecIndex    ', RecIndex);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      b51sort_branches (VAR nptr : tbd_nodeptr;
            t : tgg00_TransContextPtr);
 
VAR
      Finish       : boolean;
      RecIndex     : tsp00_Int4;
      SourceRecPos : tsp00_Int4;
      TargetRecPos : tsp00_Int4;
      pRec         : tgg00_RecPtr;
      nn           : tbd_node;
 
BEGIN
IF  NOT nptr^.nd_sorted
THEN
    BEGIN
    nn           := nptr^;
    RecIndex     := FIRST_REC_INDEX_BD00;
    TargetRecPos := BODY_BEG_BD00;
    Finish       := false;
    WITH t^ DO
        REPEAT
            WITH nn DO
                BEGIN
                SourceRecPos := nd_pointer_list [MAX_POINTERINDEX_BD00 - RecIndex];
                pRec         := @nd_body [SourceRecPos];
                END;
            (*ENDWITH*) 
            SAPDB_PascalMove ('VBD51 ',   6,    
                  sizeof (nn), sizeof (nptr^), @nn, SourceRecPos,
                  @nptr^, TargetRecPos, pRec^.recLen_gg00, trError_gg00);
            IF  trError_gg00 = e_move_error
            THEN
                BEGIN
                trError_gg00 := e_data_page_corrupted;
                b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                      nn.nd_id, @nn, 1)
                END;
            (*ENDIF*) 
            nptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - RecIndex] := TargetRecPos;
            TargetRecPos := TargetRecPos + gg06Align (pRec^.recLen_gg00, REC_ALIGN_BD00);
            IF  TargetRecPos >= nptr^.nd_bottom
            THEN
                Finish := true
            ELSE
                RecIndex := succ (RecIndex);
            (*ENDIF*) 
        UNTIL
            (Finish OR (trError_gg00 <> e_ok));
        (*ENDREPEAT*) 
    (*ENDWITH*) 
    nptr^.nd_sorted := true
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd51del_branchroot (VAR pRoot : tbd_node_ptrs;
            VAR current : tbd_current_tree);
 
VAR
      initialRootLevel : tsp00_Int2;
      PointerListSize  : tsp00_Int4;
      SubRoot          : tsp00_PageNo;
      pSubRoot         : tbd_node_ptrs;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    (* *)
    (* pRoot^.nd_id = current.fileRoot_gg00*)
    (* *)
    pSubRoot.np_ptr   := NIL;
    pSubRoot.np_cbptr := NIL;
    curr_lvl_1_pno    := NIL_PAGE_NO_GG00;
    IF  pRoot.np_ptr^.nd_bottom = BODY_BEG_BD00
    THEN
        BEGIN
        pRoot.np_ptr^.nd_level := LEAF_LEVEL_BD00;
        b13w_release_node (pRoot, current)
        END
    ELSE
        BEGIN
        (* *)
        (* Move content of leftmost leaf into root *)
        (* *)
        initialRootLevel := pRoot.np_ptr^.nd_level;
        SubRoot          := bd52SubtreePno (pRoot.np_ptr, FIRST_REC_INDEX_BD00);
        bd13GetNode (current, SubRoot, plmLock_ebd00, nr_for_update, pSubRoot);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            SAPDB_PascalMove ('VBD51 ',   7,    
                  sizeof (pSubRoot.np_ptr^), sizeof (pRoot.np_ptr^),
                  @pSubRoot.np_ptr^, BODY_BEG_BD00, @pRoot.np_ptr^, BODY_BEG_BD00,
                  pSubRoot.np_ptr^.nd_bottom - BODY_BEG_BD00, trError_gg00);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                (* references to trans history info has been moved to root, delete them from source *)
                bd999RemoveTransHistoryInfoFromPage (trTaskId_gg00, pSubRoot.np_ptr^);
                PointerListSize := pSubRoot.np_ptr^.nd_record_cnt * POINTERSIZE_BD00;
                SAPDB_PascalMove ('VBD51 ',   8,    
                      sizeof (pSubRoot.np_ptr^), sizeof (pRoot.np_ptr^),
                      @pSubRoot.np_ptr^, MAX_BOTTOM_BD00 - PointerListSize,
                      @pRoot.np_ptr^,   MAX_BOTTOM_BD00 - PointerListSize,
                      PointerListSize, trError_gg00)
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_move_error
            THEN
                BEGIN
                trError_gg00 := e_data_page_corrupted;
                b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                      pSubRoot.np_ptr^.nd_id, pSubRoot.np_ptr, 1);
                b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                      pRoot.np_ptr^.nd_id, pRoot.np_ptr, 1)
                END
            ELSE
                BEGIN
                pRoot.np_ptr^.nd_bottom     := pSubRoot.np_ptr^.nd_bottom;
                pRoot.np_ptr^.nd_record_cnt := pSubRoot.np_ptr^.nd_record_cnt;
                pRoot.np_ptr^.nd_level      := pSubRoot.np_ptr^.nd_level;
                b13w_release_node (pRoot, current);
                IF  trError_gg00 = e_ok
                THEN
                    b13free_node (pSubRoot, current);
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  (trError_gg00 = e_ok) AND (initialRootLevel = FIRST_INDEX_LEVEL_BD00)
            THEN
                BEGIN
                (* because of content switch droped subroot *)
                (* page has to be treated as an index page  *)
                currLeafPageCountDelta_bd00  := currLeafPageCountDelta_bd00  +1;
                currIndexPageCountDelta_bd00 := currIndexPageCountDelta_bd00 -1;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  pSubRoot.np_ptr <> NIL
        THEN
            b13r_release_node (pSubRoot, current, lru_normal)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd51dummy_root (VAR nptr : tbd_node_ptrs;
            VAR is_dummy : boolean;
            VAR current  : tbd_current_tree);
 
VAR
      last    : boolean;
      index   : integer;
      leafptr : tbd_node_ptrs;
      subroot : tsp00_PageNo;
 
BEGIN
leafptr.np_ptr   := NIL;
leafptr.np_cbptr := NIL;
IF  nptr.np_ptr^.nd_bottom = BODY_BEG_BD00
THEN
    is_dummy := true
ELSE
    BEGIN
    index := FIRST_REC_INDEX_BD00;
    b51next_branch (nptr.np_ptr, index, last);
    IF  last
    THEN
        BEGIN
        subroot := bd52SubtreePno (nptr.np_ptr, FIRST_REC_INDEX_BD00);
        bd13GetNode (current, subroot, plmLock_ebd00, nr_for_read, leafptr);
        IF  current.curr_trans^.trError_gg00 = e_ok
        THEN
            BEGIN
            IF  leafptr.np_ptr^.nd_right = NIL_PAGE_NO_GG00
            THEN
                is_dummy := true
            ELSE
                is_dummy := false;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  leafptr.np_ptr <> NIL
        THEN
            b13r_release_node (leafptr, current, lru_normal)
        (*ENDIF*) 
        END
    ELSE
        is_dummy := false
    (*ENDIF*) 
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b51tadd_branch (VAR nptr  : tbd_node_ptrs;
            index              : tsp00_Int4;
            left               : tsp00_PageNo;
            VAR separator      : tbd00_Separator;
            pIndexOrderList    : tsp00_Addr;
            VAR current        : tbd_current_tree);
 
VAR
      RecPos    : tsp00_Int4;
      amount    : tsp00_Int4;
 
BEGIN
WITH separator, current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    IF  (sepHead_bd00.hrecLen_gg00 < sizeof (sepHead_bd00))  OR
        (sepHead_bd00.hrecLen_gg00 > sizeof (separator)   )
    THEN
        trError_gg00 := e_illegal_branchlength;
&   ifdef TRACE
    (*ENDIF*) 
    t01int4 (bd_index, 'index       ', index);
    t01int4 (bd_index, 'sep length  ', sepHead_bd00.hrecLen_gg00);
    t01int4 (bd_index, 'bottom      ', np_ptr^.nd_bottom);
    t01int4 (bd_index, 'rec count   ', np_ptr^.nd_record_cnt);
&   endif
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  g01glob.bd_lock_check AND (NOT bd20IsPageExclusiveLocked (np_cbptr))
        THEN
            g01abort (csp3_bd_msg, csp3_n_btree, MSG_NOT_EXCL_LOCKED, np_ptr^.nd_id);
        (*ENDIF*) 
        IF  (np_ptr^.nd_bottom + sepHead_bd00.hrecLen_gg00) >
            (MAX_BOTTOM_BD00 - ((np_ptr^.nd_record_cnt + 1) * POINTERSIZE_BD00))
        THEN
            WITH np_ptr^ DO
                BEGIN
                IF  NOT nd_sorted
                THEN
                    b51sort_branches (np_ptr, curr_trans);
                (*ENDIF*) 
                curr_lvl_1_pno := NIL_PAGE_NO_GG00;
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    IF  (nd_right = NIL_PAGE_NO_GG00) AND (index >= nd_record_cnt)
                    THEN
                        b55tapp_new_indexnode (nptr, separator, pIndexOrderList, current)
                    ELSE
                        b55t_oflw_branch (nptr, gg06Align (sepHead_bd00.hrecLen_gg00,
                              REC_ALIGN_BD00), left, pIndexOrderList, current)
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDWITH*) 
        ELSE
            WITH np_ptr^ DO
                BEGIN
&               ifdef TRACE
                t01page (bd_index, np_ptr^, 1, nd_bottom);
&               endif
                RecPos    := nd_bottom;
                nd_bottom := nd_bottom + gg06Align (sepHead_bd00.hrecLen_gg00, REC_ALIGN_BD00);
                (*  put branch *)
                SAPDB_PascalMove ('VBD51 ',   9,    
                      sizeof (separator), sizeof (np_ptr^),
                      @separator, 1, @np_ptr^, RecPos, sepHead_bd00.hrecLen_gg00, trError_gg00);
                IF  trError_gg00 = e_move_error
                THEN
                    BEGIN
                    trError_gg00 := e_data_page_corrupted;
                    b06dump_bad_page (trTaskId_gg00, 'd',
                          FILE_EXT_COR_BD00, nd_id, np_ptr, 1)
                    END
                ELSE
                    BEGIN
&                   ifdef TRACE
                    t01page (bd_index, np_ptr^, 1, nd_bottom);
                    t01page (bd_index, np_ptr^,
                          MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00) ,
                          sizeof (np_ptr^));
&                   endif
                    (*  list update *)
                    amount := (nd_record_cnt - index) * POINTERSIZE_BD00;
                    IF  amount > 0
                    THEN
                        BEGIN
                        SAPDB_PascalOverlappingMove ('VBD51 ',  10,    
                              sizeof (np_ptr^), sizeof (np_ptr^),
                              @np_ptr^, (MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00)),
                              @np_ptr^, MAX_BOTTOM_BD00 - ((nd_record_cnt + 1) * POINTERSIZE_BD00),
                              amount, 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;
&                   ifdef TRACE
                    (*ENDIF*) 
                    t01page (bd_index, np_ptr^,
                          MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00),
                          sizeof (np_ptr^));
&                   endif
                    nd_record_cnt           := succ (nd_record_cnt);
                    nd_sorted               := false;
                    nd_pointer_list [MAX_POINTERINDEX_BD00 - index] := RecPos;
&                   ifdef TRACE
                    t01page (bd_index, np_ptr^,
                          MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00),
                          sizeof (np_ptr^));
&                   endif
                    bd999PopIndexOrder (pIndexOrderList);
                    END;
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    IF  (nd_level > succ (LEAF_LEVEL_BD00)) OR
                        bd999IsEmptyIndexOrderList (pIndexOrderList) OR
                        (curr_lvl_1_pno = NIL_PAGE_NO_GG00)
                    THEN
                        b13w_release_node (nptr, current)
                    (*ENDIF*) 
                (*ENDIF*) 
                END
            (*ENDWITH*) 
        (*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
      b51tdel_branch (VAR nptr  : tbd_node_ptrs;
            index              : tsp00_Int4;
            left               : tsp00_PageNo;
            pIndexOrderList    : tsp00_Addr;
            VAR current        : tbd_current_tree);
 
VAR
      is_dummy         : boolean;
      underflow        : boolean;
      lno              : tsp00_Int2;
      RecLen           : tsp00_Int4;
      DelSpaceLen      : tsp00_Int4;
      i                : tsp00_Int4;
      RecPos           : tsp00_Int4;
      next             : tsp00_PageNo;
      pRec             : tgg00_RecPtr;
      nnptr            : tbd_node_ptrs;
      OldSepKey        : tgg00_Lkey;
      NewSepKey        : tgg00_Lkey;
 
BEGIN
WITH nptr.np_ptr^, current, curr_tree_id, curr_trans^ DO
    BEGIN
&   ifdef TRACE
    t01int4 (bd_index, 'curr pageNo ', nptr.np_ptr^.nd_id);
    t01int4 (bd_index, 'rec Index   ', index);
    IF  left <> NIL_PAGE_NO_GG00
    THEN
        t01int4 (bd_index, 'left pageNo ', left);
    (*ENDIF*) 
    t01page  (bd_index, nptr.np_ptr^, 1, nd_bottom);
    t01page  (bd_index, nptr.np_ptr^,
          MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00), sizeof (nptr.np_ptr^));
&   endif
    IF  g01glob.bd_lock_check AND (NOT bd20IsPageExclusiveLocked (nptr.np_cbptr))
    THEN
        g01abort (csp3_bd_msg, csp3_n_btree, MSG_NOT_EXCL_LOCKED, nd_id);
    (*ENDIF*) 
    nnptr.np_ptr   := NIL;
    nnptr.np_cbptr := NIL;
    is_dummy       := false;
    bd999PopIndexOrder (pIndexOrderList);
    IF  index = FIRST_REC_INDEX_BD00
    THEN
        bd52GetSepKey (nptr.np_ptr, index, OldSepKey, curr_trans);
    (*ENDIF*) 
    pRec        := @nd_body [nd_pointer_list [MAX_POINTERINDEX_BD00 - index]];
    RecLen      := pRec^.recLen_gg00;
    DelSpaceLen := gg06Align (RecLen, REC_ALIGN_BD00);
    RecPos      := nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
    b35del_space (nptr.np_ptr, RecPos, DelSpaceLen, curr_trans);
    (*  list update *)
    FOR i := FIRST_REC_INDEX_BD00 TO nd_record_cnt - 1 DO
        BEGIN
        IF  nd_pointer_list [MAX_POINTERINDEX_BD00 - i] > RecPos
        THEN
            nd_pointer_list [MAX_POINTERINDEX_BD00 - i] :=
                  nd_pointer_list [MAX_POINTERINDEX_BD00 - i] - DelSpaceLen
        (*ENDIF*) 
        END;
    (*ENDFOR*) 
    IF  (index < nd_record_cnt - 1) AND (trError_gg00 = e_ok)
    THEN
        BEGIN
        SAPDB_PascalOverlappingMove ('VBD51 ',  11,    
              sizeof (nptr.np_ptr^), sizeof (nptr.np_ptr^),
              @nptr.np_ptr^, MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00),
              @nptr.np_ptr^, MAX_BOTTOM_BD00 - ((nd_record_cnt - 1) * POINTERSIZE_BD00),
              ((nd_record_cnt - 1) - index) * POINTERSIZE_BD00, 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.np_ptr, 1)
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        nd_record_cnt := pred (nd_record_cnt);
        IF  (index = FIRST_REC_INDEX_BD00) AND (left = NIL_PAGE_NO_GG00)
        THEN
            IF  nd_bottom > BODY_BEG_BD00
            THEN
                BEGIN
                (* *)
                (* leftmost index node *)
                (* replace first separator by empty separator (key length 0) *)
                (* *)
                RecPos               := nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
                pRec                 := @nd_body [RecPos];
                DelSpaceLen          := gg06Align (pRec^.recKeyLen_gg00, REC_ALIGN_BD00);
                pRec^.recKeyLen_gg00 := 0;
                pRec^.recLen_gg00    := sizeof (pRec^.recHead_gg00) + sizeof (tbd00_SepLeafCount);
                IF  DelSpaceLen > 0
                THEN
                    b35del_space (nptr.np_ptr, RecPos + pRec^.recLen_gg00,
                          DelSpaceLen, curr_trans);
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    IF  DelSpaceLen > 0
                    THEN
                        FOR i := FIRST_REC_INDEX_BD00 TO nd_record_cnt - 1 DO
                            BEGIN
                            IF  nd_pointer_list [MAX_POINTERINDEX_BD00 - i] > RecPos
                            THEN
                                nd_pointer_list [MAX_POINTERINDEX_BD00 - i] :=
                                      nd_pointer_list [MAX_POINTERINDEX_BD00 - i] - DelSpaceLen
                            (*ENDIF*) 
                            END;
                        (*ENDFOR*) 
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            ELSE
                IF  nd_right <> NIL_PAGE_NO_GG00
                THEN
                    BEGIN
                    (* *)
                    (* nd_right is new leftmost index node replace 1.*)
                    (*  separator by empty separator (length 0)      *)
                    (* *)
                    bd13GetNode (current, nd_right, plmLock_ebd00, nr_for_update, nnptr);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        RecPos               :=
                              nnptr.np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
                        pRec                 := @nnptr.np_ptr^.nd_body [RecPos];
                        DelSpaceLen          := gg06Align (pRec^.recKeyLen_gg00, REC_ALIGN_BD00);
                        pRec^.recKeyLen_gg00 := 0;
                        pRec^.recLen_gg00    :=
                              sizeof (pRec^.recHead_gg00) + sizeof (tbd00_SepLeafCount);
                        IF  DelSpaceLen > 0
                        THEN
                            b35del_space (nnptr.np_ptr, RecPos + pRec^.recLen_gg00,
                                  DelSpaceLen, curr_trans);
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            WITH nnptr, np_ptr^ DO
                                BEGIN
                                IF  DelSpaceLen > 0
                                THEN
                                    FOR i := FIRST_REC_INDEX_BD00 TO nd_record_cnt - 1 DO
                                        BEGIN
                                        IF  nd_pointer_list [MAX_POINTERINDEX_BD00 - i] > RecPos
                                        THEN
                                            nd_pointer_list [MAX_POINTERINDEX_BD00 - i] :=
                                                  nd_pointer_list [MAX_POINTERINDEX_BD00 - i] - DelSpaceLen
                                        (*ENDIF*) 
                                        END;
                                    (*ENDFOR*) 
                                (*ENDIF*) 
                                b13w_release_node (nnptr, current)
                                END
                            (*ENDWITH*) 
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDIF*) 
        IF  (index = FIRST_REC_INDEX_BD00) AND
            (nd_id <> fileRoot_gg00      ) AND
            (nd_bottom > BODY_BEG_BD00   ) AND
            (left <> NIL_PAGE_NO_GG00    )
        THEN
            BEGIN
            bd52GetSepKey (nptr.np_ptr, index, NewSepKey, curr_trans);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                lno            := nd_level;
                curr_lvl_1_pno := NIL_PAGE_NO_GG00;
                IF  b54trepl_index (@OldSepKey.keyVal_gg00,
                    OldSepKey.keyLen_gg00, @NewSepKey.keyVal_gg00,
                    NewSepKey.keyLen_gg00, nd_id, lno, pIndexOrderList)
                THEN
                    b13w_release_node (nptr, current)
                ELSE
                    trError_gg00 := e_no_more_memory;
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            IF  (nd_id <> fileRoot_gg00) AND (nd_bottom = BODY_BEG_BD00)
            THEN
                BEGIN
                IF  left <> NIL_PAGE_NO_GG00
                THEN
                    BEGIN
                    (*  divert pointer from left node *)
                    bd13GetNode (current, left, plmLock_ebd00, nr_for_update, nnptr);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        next := nnptr.np_ptr^.nd_right;
                        IF  next = nd_id
                        THEN
                            nnptr.np_ptr^.nd_right := nd_right
                        ELSE
                            trError_gg00 := e_invalid_index_structure
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        b13w_release_node (nnptr, current)
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    lno := nd_level;
                    IF  b54tdel_index (@OldSepKey.keyVal_gg00,
                        OldSepKey.keyLen_gg00, lno, pIndexOrderList)
                    THEN
                        b54texecute_indexorder (pIndexOrderList, current)
                    ELSE
                        trError_gg00 := e_no_more_memory;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        b13free_node (nptr, current);
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                IF  ftsDynamic_egg00 IN fileType_gg00
                THEN
                    underflow :=
                          (nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00)
                          < QUATER_COVERING_BD00)
                          AND
                          (nd_id <> fileRoot_gg00)
                ELSE
                    underflow :=
                          (nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00)
                          < HALF_COVERING_BD00)
                          AND
                          (nd_id <> fileRoot_gg00);
                (*ENDIF*) 
                IF  underflow
                THEN
                    BEGIN
                    curr_lvl_1_pno := NIL_PAGE_NO_GG00;
                    IF  NOT nd_sorted
                    THEN
                        b51sort_branches (nptr.np_ptr, curr_trans);
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        b55t_uflw_branch (nptr, left, pIndexOrderList, current)
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    bd51dummy_root (nptr, is_dummy, current);
                    IF  (trError_gg00 = e_ok) AND is_dummy
                    THEN
                        BEGIN
                        curr_lvl_1_pno := NIL_PAGE_NO_GG00;
                        bd51del_branchroot (nptr, current)
                        END
                    ELSE
                        BEGIN
                        IF  (nd_level > succ (LEAF_LEVEL_BD00 )) OR
                            bd999IsEmptyIndexOrderList (pIndexOrderList) OR
                            (curr_lvl_1_pno = NIL_PAGE_NO_GG00 )
                        THEN
                            b13w_release_node (nptr, current)
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 <> e_ok
    THEN
        BEGIN
        IF  nptr.np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  nnptr.np_ptr <> NIL
        THEN
            b13r_release_node (nnptr, current, lru_normal)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b51tnew_branchroot (VAR nptr : tbd_node_ptrs;
            VAR RightSeparator : tbd00_Separator;
            pIndexOrderList    : tsp00_Addr;
            VAR current        : tbd_current_tree);
 
VAR
      lno             : tsp00_Int2;
      RecIndex        : tsp00_Int4;
      PointerListSize : tsp00_Int4;
      new_leftptr     : tbd_node_ptrs;
      leftsubroot     : tsp00_PageNo;
      rightsubroot    : tsp00_PageNo;
      LeftSeparator   : tbd00_Separator;
      pRec            : tgg00_RecPtr;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    (* *)
    (* nptr^.nd_id = current.fileRoot_gg00*)
    (* *)
&   ifdef TRACE
    t01int4 (bd_index, 'nd_right    ',nptr.np_ptr^.nd_right);
&   endif
    lno                  := nptr.np_ptr^.nd_level;
    curr_lvl_1_pno       := NIL_PAGE_NO_GG00;
    new_leftptr.np_ptr   := NIL;
    new_leftptr.np_cbptr := NIL;
    rightsubroot         := nptr.np_ptr^.nd_right;
    b13new_node (lno, new_leftptr, current);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        (* *)
        (* Move only content of root into new node. No    *)
        (* modification of header and trailer. Exception: *)
        (* nd_bottom, nd_record_cnt and nd_right.         *)
        (* *)
        IF  lno = LEAF_LEVEL_BD00
        THEN
            BEGIN
            (* because of content switch new page *)
            (* has to be treated as an index page *)
            currLeafPageCountDelta_bd00  := currLeafPageCountDelta_bd00  -1;
            currIndexPageCountDelta_bd00 := currIndexPageCountDelta_bd00 +1;
            END;
        (*ENDIF*) 
        leftsubroot := new_leftptr.np_ptr^.nd_id;
        SAPDB_PascalMove ('VBD51 ',  12,    
              sizeof (nptr.np_ptr^), sizeof (new_leftptr.np_ptr^),
              @nptr.np_ptr^, BODY_BEG_BD00,
              @new_leftptr.np_ptr^, BODY_BEG_BD00,
              nptr.np_ptr^.nd_bottom - BODY_BEG_BD00, trError_gg00);
        (* *)
        PointerListSize := nptr.np_ptr^.nd_record_cnt * POINTERSIZE_BD00;
        SAPDB_PascalMove ('VBD51 ',  13,    
              sizeof (nptr.np_ptr^), sizeof (new_leftptr.np_ptr^),
              @nptr.np_ptr^, MAX_BOTTOM_BD00 - PointerListSize,
              @new_leftptr.np_ptr^, MAX_BOTTOM_BD00 - PointerListSize,
              PointerListSize, 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*) 
        IF  trError_gg00 = e_ok
        THEN
            WITH new_leftptr, np_ptr^ DO
                BEGIN
                nd_bottom     := nptr.np_ptr^.nd_bottom;
                nd_record_cnt := nptr.np_ptr^.nd_record_cnt;
                IF  lno > LEAF_LEVEL_BD00
                THEN
                    nd_right := rightsubroot
                ELSE
                    (* temporary nptr.np_ptr^.nd_right could be *)
                    (* not equal to NIL_PAGE_NO_GG00             *)
                    nd_right := nptr.np_ptr^.nd_right;
                (*ENDIF*) 
                IF  (ftsTemp_egg00 in fileType_gg00) AND
                    (lno = LEAF_LEVEL_BD00         )
                THEN
                    b51ldivert_leftnext (nd_right, leftsubroot, current)
                (*ENDIF*) 
                END
            (*ENDWITH*) 
        ELSE
            b13free_node (new_leftptr, current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b13w_release_node (new_leftptr, current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            WITH nptr.np_ptr^ DO
                BEGIN
                (* *)
                (* Adjust new root page *)
                (* *)
                nd_id                   := fileRoot_gg00;
                nd_checktype            := chckChecksumData_egg00;
                nd_sorted               := false;
                nd_write_cnt            := 0;
                nd_checksum             := 0;
                nd_level                := succ (lno);
                nd_right                := NIL_PAGE_NO_GG00;
                ndLeafCount_bd00        := 0;
                nd_bottom               := BODY_BEG_BD00;
                RecIndex                := FIRST_REC_INDEX_BD00;
                nd_pointer_list [MAX_POINTERINDEX_BD00 - RecIndex] := nd_bottom;
                nd_record_cnt           := 1;
                nd_trailer              := nd_header;
                (* *)
                (* min index *)
                (* *)
                WITH LeftSeparator.sepHead_bd00 DO
                    BEGIN
                    hrecKeyLen_gg00 := 0;
                    hrecLen_gg00    := sizeof (LeftSeparator.sepHead_bd00)
                          + sizeof (tbd00_SepLeafCount);
                    gg06PnoPut (LeftSeparator.sepHead_bd00.hrecPno_gg00, leftsubroot)
                    END;
                (*ENDWITH*) 
&               ifdef TRACE
                t01page (bd_index, nptr.np_ptr^, 1, sizeof (nd_full_header));
&               endif
                bd52PutSeparatorIntoNode  (nptr.np_ptr, RecIndex, LeftSeparator, curr_trans);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    pRec := @nptr.np_ptr^.nd_body [nd_bottom];
                    bd52PutSepLeafCount (pRec, 0);
                    nd_bottom := BODY_BEG_BD00 + gg06Align (LeftSeparator.sepHead_bd00.hrecLen_gg00, REC_ALIGN_BD00);
&                   ifdef TRACE
                    t01page (bd_index, nptr.np_ptr^, 1, nd_bottom);
&                   endif
                    RecIndex                                           := succ (FIRST_REC_INDEX_BD00);
                    nd_pointer_list [MAX_POINTERINDEX_BD00 - RecIndex] := nd_bottom;
                    nd_record_cnt                                      := succ (nd_record_cnt);
                    bd52PutSeparatorIntoNode (nptr.np_ptr, RecIndex, RightSeparator, curr_trans);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        pRec := @nptr.np_ptr^.nd_body [nd_bottom];
                        bd52PutSepLeafCount (pRec, 0);
                        nd_bottom := nd_bottom + gg06Align (RightSeparator.sepHead_bd00.hrecLen_gg00, REC_ALIGN_BD00);
&                       ifdef TRACE
                        t01page (bd_index, nptr.np_ptr^, 1, nd_bottom);
                        t01page (bd_index, nptr.np_ptr^,
                              MAX_BOTTOM_BD00 - (nd_record_cnt * POINTERSIZE_BD00), sizeof (nptr.np_ptr^));
&                       endif
                        bd999PopIndexOrder (pIndexOrderList);
                        b13w_release_node (nptr, current)
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDWITH*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 <> e_ok
    THEN
        BEGIN
        IF  nptr.np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  new_leftptr.np_ptr <> NIL
        THEN
            b13r_release_node (new_leftptr, current, lru_normal)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b51trepl_branch (VAR nptr : tbd_node_ptrs;
            index              : tsp00_Int4;
            left               : tsp00_PageNo;
            VAR separator      : tbd00_Separator;
            pIndexOrderList    : tsp00_Addr;
            VAR current        : tbd_current_tree);
 
VAR
      l_result  : tsp00_LcompResult;
      lno       : tsp00_Int2;
      i         : tsp00_Int4;
      bpos      : tsp00_Int4;
      diff      : tsp00_Int4;
      OldRecLen : tsp00_Int4;
      pRec      : tgg00_RecPtr;
      rnptr     : tbd_node_ptrs;
      OldSepKey : tgg00_Lkey;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    IF  index = FIRST_REC_INDEX_BD00
    THEN
        bd52GetSepKey (np_ptr, index, OldSepKey, curr_trans);
    (*ENDIF*) 
    pRec      := @np_ptr^.nd_body [np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - index]];
    OldRecLen := pRec^.recLen_gg00;
    IF  (pRec^.recPno_gg00 <> separator.sepHead_bd00.hrecPno_gg00)
    THEN
        BEGIN
        trError_gg00 := e_invalid_index_structure;
        b06write_filename_and_root( curr_tree_id );
        b06dump_bad_page (trTaskId_gg00, 'd',
              FILE_EXT_COR_BD00, np_ptr^.nd_id, np_ptr, 1);
        g01opmsg (sp3p_console, sp3m_error,
              csp3_b51x1_invalid_separator, csp3_n_btree,
              'B51: SepPno Update      ', np_ptr^.nd_id);
        g01opmsg (sp3p_console, sp3m_error,
              csp3_b51x1_invalid_separator, csp3_n_btree,
              'B51:    OldSepPno       ', gg06PnoGet(pRec^.recPno_gg00));
        g01abort (csp3_b51x1_invalid_separator, csp3_n_btree,
              'B51:    NewSepPno       ', gg06PnoGet(separator.sepHead_bd00.hrecPno_gg00));
        END;
    (* *)
    (* +++security check , 'cause of problems with R3 port (BEGIN)+++ *)
    (*ENDIF*) 
    IF  (index < np_ptr^.nd_record_cnt - 1)
    THEN
        BEGIN
        (* not greatest key on page *)
        pRec := @np_ptr^.nd_body [np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - (index + 1)]];
        WITH separator DO
            s30cmp1 (sepKey_bd00.keyVal_gg00, 1, sepKey_bd00.keyLen_gg00,
                  pRec^.recKey_gg00.keyVal_gg00, 1, pRec^.recKeyLen_gg00, l_result);
        (*ENDWITH*) 
        IF  l_result = l_greater
        THEN
            BEGIN
            trError_gg00 := e_invalid_index_structure;
            b06dump_bad_page (trTaskId_gg00, 'd',
                  FILE_EXT_COR_BD00, np_ptr^.nd_id, np_ptr, 1);
            b06write_filename_and_root( curr_tree_id );
            g01opmsg (sp3p_console, sp3m_error,
                  csp3_b51x1_invalid_separator, csp3_n_btree,
                  'B51: new_sep > next_sep ', index);
            g01abort (csp3_b51x1_invalid_separator, csp3_n_btree,
                  'B51: new_sep > next_sep ', index);
            END
        (*ENDIF*) 
        END
    ELSE
        IF  np_ptr^.nd_right <> NIL_PAGE_NO_GG00
        THEN
            BEGIN
            rnptr.np_ptr := NIL;
            bd13GetNode (current, np_ptr^.nd_right, plmLock_ebd00, nr_for_read, rnptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                pRec := @rnptr.np_ptr^.nd_body [rnptr.np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00]];
                WITH separator DO
                    s30cmp1 (sepKey_bd00.keyVal_gg00, 1, sepKey_bd00.keyLen_gg00,
                          pRec^.recKey_gg00.keyVal_gg00, 1, pRec^.recKeyLen_gg00, l_result);
                (*ENDWITH*) 
                IF  l_result = l_greater
                THEN
                    BEGIN
                    trError_gg00 := e_invalid_index_structure;
                    b06dump_bad_page (trTaskId_gg00, 'd',
                          FILE_EXT_COR_BD00, np_ptr^.nd_id, np_ptr, 1);
                    b06write_filename_and_root( curr_tree_id );
                    g01opmsg (sp3p_console, sp3m_error,
                          csp3_b51x2_invalid_separator,
                          csp3_n_btree, 'B51: new_sep > next_sep ',
                          index);
                    g01abort (csp3_b51x2_invalid_separator, csp3_n_btree,
                          'B51: new_sep > next_sep ', index);
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  rnptr.np_ptr <> NIL
            THEN
                b13r_release_node (rnptr, current, lru_normal)
            (*ENDIF*) 
            END;
        (* *)
        (* +++security check , 'cause of problems with R3 port (END) +++ *)
        (*ENDIF*) 
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  g01glob.bd_lock_check AND (NOT bd20IsPageExclusiveLocked (np_cbptr))
        THEN
            g01abort (csp3_bd_msg, csp3_n_btree, MSG_NOT_EXCL_LOCKED, np_ptr^.nd_id);
        (*ENDIF*) 
        IF  np_ptr^.nd_bottom + (separator.sepHead_bd00.hrecLen_gg00 - OldRecLen) >
            MAX_BOTTOM_BD00 - (np_ptr^.nd_record_cnt * POINTERSIZE_BD00)
        THEN
            BEGIN
            IF  NOT np_ptr^.nd_sorted
            THEN
                b51sort_branches (np_ptr, curr_trans);
            (*ENDIF*) 
            curr_lvl_1_pno := NIL_PAGE_NO_GG00;
            diff           := gg06Align (separator.sepHead_bd00.hrecLen_gg00, REC_ALIGN_BD00) -
                  gg06Align (OldRecLen, REC_ALIGN_BD00);
            IF  trError_gg00 = e_ok
            THEN
                b55t_oflw_branch (nptr, diff, left, pIndexOrderList, current)
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            bpos := np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
            diff := 0;
            IF  separator.sepHead_bd00.hrecLen_gg00 > OldRecLen
            THEN
                BEGIN
                diff := gg06Align (separator.sepHead_bd00.hrecLen_gg00, REC_ALIGN_BD00) -
                      gg06Align (OldRecLen, REC_ALIGN_BD00);
                b35add_space (np_ptr, bpos, diff, curr_trans)
                END
            ELSE
                IF  separator.sepHead_bd00.hrecLen_gg00 < OldRecLen
                THEN
                    BEGIN
                    diff := gg06Align (separator.sepHead_bd00.hrecLen_gg00, REC_ALIGN_BD00) -
                          gg06Align (OldRecLen, REC_ALIGN_BD00) ;
                    b35del_space (np_ptr, bpos, abs (diff), curr_trans)
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                bd52PutSeparatorIntoNode (np_ptr, index, separator, curr_trans);
                IF  diff <> 0
                THEN
                    FOR i := FIRST_REC_INDEX_BD00 TO np_ptr^.nd_record_cnt - 1 DO
                        BEGIN
                        IF  np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - i] > bpos
                        THEN
                            np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - i] :=
                                  np_ptr^.nd_pointer_list [MAX_POINTERINDEX_BD00 - i] + diff
                        (*ENDIF*) 
                        END;
                    (*ENDFOR*) 
                (*ENDIF*) 
                bd999PopIndexOrder (pIndexOrderList);
                IF  (index = FIRST_REC_INDEX_BD00  ) AND
                    (np_ptr^.nd_id <> fileRoot_gg00)
                THEN
                    BEGIN
                    lno            := np_ptr^.nd_level;
                    curr_lvl_1_pno := NIL_PAGE_NO_GG00;
                    IF  b54trepl_index (@OldSepKey.keyVal_gg00,
                        OldSepKey.keyLen_gg00,
                        @separator.sepKey_bd00.keyVal_gg00,
                        separator.sepKey_bd00.keyLen_gg00, np_ptr^.nd_id,
                        lno, pIndexOrderList)
                    THEN
                        b13w_release_node (nptr, current)
                    ELSE
                        trError_gg00 := e_no_more_memory;
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    IF  (np_ptr^.nd_level > succ (LEAF_LEVEL_BD00)) OR
                        bd999IsEmptyIndexOrderList (pIndexOrderList) OR
                        (curr_lvl_1_pno = NIL_PAGE_NO_GG00        )
                    THEN
                        b13w_release_node (nptr, current)
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
