.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$VBD55$
.tt 2 $$$
.tt 3 $JuergenP$branchreorganization$2000-09-07$
***********************************************************
.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  : branchreorganization
=========
.sp
Purpose : overflow and underflow handling of index nodes
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        PROCEDURE
              b55app_new_indexnode (VAR Nptrs : tbd_node_ptrs;
                    VAR Separator      : tbd00_Separator;
                    VAR IndexOrderList : tbd00_OrderList;
                    VAR Current        : tbd_current_tree);
 
        PROCEDURE
              b55p_oflw_branch (VAR Nptrs : tbd_node_ptrs;
                    NewBranchLength    : tsp00_Int4;
                    Left               : tsp00_PageNo;
                    VAR IndexOrderList : tbd00_OrderList;
                    VAR Current        : tbd_current_tree);
 
        PROCEDURE
              b55p_uflw_branch (VAR Nptrs : tbd_node_ptrs;
                    Left               : tsp00_PageNo;
                    VAR IndexOrderList : tbd00_OrderList;
                    VAR Current        : tbd_current_tree);
 
        PROCEDURE
              b55t_oflw_branch (VAR Nptrs : tbd_node_ptrs;
                    NewBranchLength    : tsp00_Int4;
                    Left               : tsp00_PageNo;
                    VAR IndexOrderList : tbd00_OrderList;
                    VAR Current        : tbd_current_tree);
 
        PROCEDURE
              b55t_uflw_branch (VAR Nptrs : tbd_node_ptrs;
                    Left               : tsp00_PageNo;
                    VAR IndexOrderList : tbd00_OrderList;
                    VAR Current        : tbd_current_tree);
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
        FROM
              filesysteminterface_1 : VBD01;
 
        FUNCTION
              b01rec_align (len : tsp00_Int4): tsp00_Int4;
 
      ------------------------------ 
 
        FROM
              error_text_handling : VBD06;
 
        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
              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 (Level  : tsp00_Int2;
                    VAR nptr    : tbd_node_ptrs;
                    VAR Current : tbd_current_tree);
 
        PROCEDURE
              bd13FreePageNo(
                    pageNo               : tsp00_PageNo;
                    pageConverterVersion : tsp00_Int4;
                    VAR current          : tbd_current_tree );
 
        PROCEDURE
              b13r_release_node (VAR nptr : tbd_node_ptrs;
                    VAR Current : tbd_current_tree;
                    lru_info    : tbd_lru_info);
 
        PROCEDURE
              b13w_release_node (VAR nptr : tbd_node_ptrs;
                    VAR Current      : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              systembufferinterface : VBD20;
 
        FUNCTION
              bd20IsPageExclusiveLocked (
                    pCBlock : tbd_nodeptr) : boolean;
 
      ------------------------------ 
 
        FROM
              branchnodehandling : VBD51;
 
        PROCEDURE
              b51pointer_list (VAR nptr : tbd_nodeptr);
 
        PROCEDURE
              b51sort_branches (VAR nptr : tbd_nodeptr;
                    t : tgg00_TransContextPtr);
 
      ------------------------------ 
 
        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);
 
      ------------------------------ 
 
        FROM
              indexupdateorders : VBD54;
 
        PROCEDURE
              b54add_index (pSep       : tsp00_KeyAddr;
                    SepLen             : tsp00_Int4;
                    n_id               : tsp00_PageNo;
                    n_level            : tsp00_Int2;
                    VAR IndexOrderList : tbd00_OrderList);
 
        PROCEDURE
              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);
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              g10mv (
                    mod_id      : tsp00_C6;
                    mod_num     : tsp00_Int4;
                    source_upb  : tsp00_Int4;
                    dest_upb    : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    src_pos     : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    dest_pos    : tsp00_Int4;
                    length      : tsp00_Int4;
                    VAR e       : tgg00_BasisError);
 
      ------------------------------ 
 
        FROM
              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);
 
      ------------------------------ 
 
        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);
&       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
&             ifdef TRACE
 
        PROCEDURE
              t01page;
 
              tsp00_Page tbd_node
&             endif
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : JuergenP
.sp
.cp 3
Created : 1985-02-08
.sp
.cp 3
.sp
.cp 3
Release :      Date : 2000-09-07
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
 
The routines described below process nodes of the B* index
of the Current tree;  in the following, these nodes are called
branch nodes (branchnodes).
.sp
A branch node 'overflows' if a new branch entry is to be inserted in
it or the separator of one of its branches is to be replaced with a
new, longer separator and there is no longer enough space available
in the node.
.sp
With the exception of the root, each node in the B* index
has what is called an environment in the form of a left and/or right
neighbor node (on the same level in the tree).  If there is no
environment or if the nodes concerned are too full, a new, empty
node can be added (as new left or right neighbor to the overflowing
node) in order to create an environment suitable for the
reorganization (given there is another node available -- otherwise
b_no_more_space is sent).  The reorganization then consists of
redistributing the branches of the nodes concerned in such a way that
sufficient space is made available in each one for the addition of a
new branch.  This redistribution generally makes it necessary to modify
the (above-lying section of the) B* index; this modification must be
carried out before the change operation that originally caused the
reorganization can occur.
.sp 2
A branch node is 'underfilled' if it is less than half full following
the deletion of one of its branches or the replacement of one of its
separators with a shorter one.
.sp
No special attention is given if the B* tree root is underfilled;
for the other nodes of the B* index, an attempt can be made to
sufficiently SAPDB_PascalFill all the nodes concerned by redistributing the
entries between the underfilled node and its environment.  Under certain
circumstances, a node that has become superfluous may even be released.
Here, too, a modification of the (above-lying section of the) B* index
must occur immediately afterwards.
.sp
In both cases, all those nodes that have been involved in the
reorganization and have been changed but not released, are written
back at the end of the routine.
.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 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;.cp 5
   branchoverflow(n,left,IndexOrderList,Current,e)
.sp
It is required that 'left' and 'right' contain the page numbers
of the left and right neighbors of the node n (or nil_page_no
if the neighbor does not exist).  This routine reorganizes the
node n and its environment in such a way that all nodes that then
contain branches that were formerly contained in n have enough
space available for a new branch entry (of the maximum length).
The order to modify the (above-lying section of the)
B* index is added to the relevant order list in such a way that
it is the next order to be executed.  One of the following messages
is sent back to e:
.sp
   - e_ok
   - b_no_more_space
   - b_disk_not_accessible
.sp 2
   branchunderflow(n,left,IndexOrderList,Current,e)
.sp
It is required that 'left' and 'right' contain the page numbers
of the left and right neighbors of the node n (or nil_page_no
if the neighbor does not exist).  If it is possible to achieve a
more balanced SAPDB_PascalFill of the nodes and also to SAPDB_PascalFill the nodes
sufficiently by redistributing the branches of n and its
environment, such a redistribution is carried out.  The order to
reorganize the (above-lying section of the) B* index is added to
the relevant order list in such a way that it is the next order
to be executed.
One of the following messages is sent back to e:
.sp
   - e_ok
   - b_disk_not_accessible
.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
 
For implementation, it is assumed that the routine
branchoverflow is called most often during the setup (i.e. during
the initial loading) of a file (and hence also of its B* index).  At that
time, the most favorable filling of the leaves is achieved by
loading the file sequentially in descending or ascending order by
keys (see leafoverflow module).  In this case, the B* index is
built up from lower left to upper right with the addition always
beginning at the lower left point.  This is why, during overflow
handling, an attempt is first made to achieve a suitable
redistribution to the right neighbor (balance_to_right).  If
this fails, an attempt is made to redistribute to the
left neighbor (balance_to_left).  If both attempts fail, a new
node is requested; it is then considered to be a new right neighbor
to n and a redistribution is carried out with this node
(balance_to_right).
.sp
The redistribution of branches between the two nodes will then
take place only if it will create enough space in each of the two
nodes for a new branch and no branch entry must be split in the
process.  An adequate condition for this redistribution is that
the two nodes together have enough space available for three branch
entries of the maximum length before redistribution takes place.
.sp
If a new node was requested for the reorganization, a new branch
entry to this node (in the above-lying section of the B* index) is
ordered after the redistribution.  Otherwise, an order is
issued for the node whose branches have overflowed into its
neighbor node such that the old separator in the branch to this
node is to be replaced by the Current new separator.
.sp 2
When a file is deleted by a series of get_next/del_record calls,
the B* index is dismantled step by step from lower left to upper
right.  In branchunderflow, an attempt is first made to insert in
the underfilled node the entire contents of its right neighbor
(bd55merge_branches).  If this is not possible but the right neighbor does
exist, an attempt is made to correct the underflow by distributing the
relevant branches more evenly between the two nodes (balance_to_right).
If this attempt also fails, the two attempts are repeated with the
left neighbor (bd55merge_branches, balance_to_left).  Only when all the
eligible nodes are full to just below the lower limit can it occur that
neither a merge nor a balance (without splitting a branch) is possible.
In this case, the underfilled node is written back unchanged.
.sp
When the contents of two nodes are being balanced
(balance_to_left/right), the length of the contents overflowing into
the neighbor node is given in oflw.  The orientation value for this is
the optimal length opt_oflw, which is calculated without taking entry
limits into account.
.br
When two nodes are merged (bd55merge_branches), the right node is always
released and an order is issued to delete the branch in the (above-
lying section of the) B* index that has led to it up to now.
.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
      b55app_new_indexnode (VAR Nptrs : tbd_node_ptrs;
            VAR Separator      : tbd00_Separator;
            VAR IndexOrderList : tbd00_OrderList;
            VAR Current        : tbd_current_tree);
 
VAR
      NptrsRight : tbd_node_ptrs;
 
BEGIN
&ifdef TRACE
t01int4 (bd_index, 'nd_id       ', Nptrs.np_ptr^.nd_id);
&endif
WITH Current, curr_tree_id, curr_trans^ DO
    BEGIN
    trError_gg00        := e_ok;
    NptrsRight.np_ptr   := NIL;
    NptrsRight.np_cbptr := NIL;
    b13new_node (Nptrs.np_ptr^.nd_level, NptrsRight, Current);
    IF  trError_gg00 = e_ok
    THEN
        WITH NptrsRight, np_ptr^ DO
            BEGIN
            nd_bottom := nd_bottom + b01rec_align (Separator.sepHead_bd00.hrecLen_gg00);
            nd_pointer_list [MAX_POINTERINDEX_BD00] := BODY_BEG_BD00;
            bd52PutSeparatorIntoNode (np_ptr, FIRST_REC_INDEX_BD00, Separator, curr_trans);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                Nptrs.np_ptr^.nd_right := NptrsRight.np_ptr^.nd_id;
                nd_record_cnt          := succ (nd_record_cnt);
&               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
                IndexOrderList.olstCount_bd00 := pred (IndexOrderList.olstCount_bd00);
                b54add_index (@Separator.sepKey_bd00.keyVal_gg00, Separator.sepKey_bd00.keyLen_gg00,
                      nd_id, Nptrs.np_ptr^.nd_level, IndexOrderList)
                END
            ELSE
                b13free_node (NptrsRight, Current)
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        curr_lvl_1_pno := NIL_PAGE_NO_GG00;
        IF  ftsPerm_egg00 in fileType_gg00
        THEN
            BEGIN
            b13w_release_node (NptrsRight, Current);
            IF  trError_gg00 = e_ok
            THEN
                b13w_release_node (Nptrs, Current)
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            b13w_release_node (NptrsRight, Current);
            b13w_release_node (Nptrs, Current);
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (NptrsRight.np_ptr <> NIL)
    THEN
        b13r_release_node (NptrsRight, Current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b55p_oflw_branch (VAR Nptrs : tbd_node_ptrs;
            NewBranchLength    : tsp00_Int4;
            Left               : tsp00_PageNo;
            VAR IndexOrderList : tbd00_OrderList;
            VAR Current        : tbd_current_tree);
 
VAR
      Level            : tsp00_Int2;
      Covering         : tsp00_Int4;
      NeighborCovering : tsp00_Int4;
      Right            : tsp00_PageNo;
      NptrsNeighbor    : tbd_node_ptrs;
 
BEGIN
WITH Current, curr_tree_id, curr_trans^ DO
    BEGIN
    trError_gg00           := e_ok;
    NptrsNeighbor.np_ptr   := NIL;
    NptrsNeighbor.np_cbptr := NIL;
    NewBranchLength        := b01rec_align(NewBranchLength) + POINTERSIZE_BD00;
    WITH Nptrs, np_ptr^ DO
        BEGIN
        IF  g01glob.bd_lock_check AND (NOT bd20IsPageExclusiveLocked (np_cbptr))
        THEN
            g01abort (csp3_bd_msg, csp3_n_btree, MSG_NOT_EXCL_LOCKED, nd_id);
        (*ENDIF*) 
        Covering := nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00);
        Right    := nd_right;
        Level    := nd_level;
        END;
    (*ENDWITH*) 
    IF  (Right = NIL_PAGE_NO_GG00) OR (ftsDynamic_egg00 in fileType_gg00)
    THEN
        trError_gg00 := e_no_more_space
    ELSE
        BEGIN
        bd13GetNode (Current, Right, plmLock_ebd00, nr_for_update, NptrsNeighbor);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            WITH NptrsNeighbor.np_ptr^ DO
                NeighborCovering :=
                      nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00);
            (*ENDWITH*) 
            IF  (Covering + NeighborCovering + NewBranchLength) > 2 * FULLCOVERING_BD00
            THEN
                BEGIN
                b13r_release_node (NptrsNeighbor, Current, lru_normal);
                trError_gg00 := e_no_more_space
                END
            ELSE
                BEGIN
                IF  NOT NptrsNeighbor.np_ptr^.nd_sorted
                THEN
                    b51sort_branches (NptrsNeighbor.np_ptr, curr_trans);
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    bd55balance_to_right (Current, Nptrs, NptrsNeighbor, NewBranchLength,
                          Covering, NeighborCovering, IndexOrderList);
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    WITH Nptrs.np_ptr^ DO
                        BEGIN
                        nd_write_cnt := 0;
                        nd_checksum  := 0
                        END;
                    (*ENDWITH*) 
                    WITH NptrsNeighbor.np_ptr^ DO
                        BEGIN
                        nd_write_cnt := 0;
                        nd_checksum  := 0
                        END;
                    (*ENDWITH*) 
                    b13w_release_node (NptrsNeighbor, Current);
                    IF  trError_gg00 = e_ok
                    THEN
                        b13w_release_node (Nptrs, Current)
                    (*ENDIF*) 
                    END
                ELSE
                    b13r_release_node (NptrsNeighbor, Current, lru_normal)
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 = e_no_more_space) AND (NOT (ftsDynamic_egg00 in fileType_gg00))
    THEN
        IF  Left <> NIL_PAGE_NO_GG00
        THEN
            BEGIN
            trError_gg00 := e_ok;
            bd13GetNode (Current, Left, plmLock_ebd00, nr_for_update, NptrsNeighbor);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                WITH NptrsNeighbor.np_ptr^ DO
                    NeighborCovering := nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00);
                (*ENDWITH*) 
                IF  (Covering + NeighborCovering + NewBranchLength) >
                    2 * FULLCOVERING_BD00
                THEN
                    BEGIN
                    b13r_release_node (NptrsNeighbor, Current, lru_normal);
                    trError_gg00 := e_no_more_space
                    END
                ELSE
                    BEGIN
                    IF  NOT NptrsNeighbor.np_ptr^.nd_sorted
                    THEN
                        b51sort_branches (NptrsNeighbor.np_ptr, curr_trans);
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        bd55balance_to_left (Current, Nptrs, NptrsNeighbor, NewBranchLength,
                              Covering, NeighborCovering, IndexOrderList);
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        WITH Nptrs.np_ptr^ DO
                            BEGIN
                            nd_write_cnt := 0;
                            nd_checksum  := 0
                            END;
                        (*ENDWITH*) 
                        WITH NptrsNeighbor.np_ptr^ DO
                            BEGIN
                            nd_write_cnt := 0;
                            nd_checksum  := 0
                            END;
                        (*ENDWITH*) 
                        b13w_release_node (Nptrs, Current);
                        IF  trError_gg00 = e_ok
                        THEN
                            b13w_release_node (NptrsNeighbor, Current)
                        (*ENDIF*) 
                        END
                    ELSE
                        b13r_release_node (NptrsNeighbor, Current, lru_normal)
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  trError_gg00 = e_no_more_space
    THEN
        BEGIN
        trError_gg00 := e_ok;
        b13new_node (Level, NptrsNeighbor, Current);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            NptrsNeighbor.np_ptr^.nd_right := Right;
            NeighborCovering               := 0;
            bd55balance_to_right (Current, Nptrs, NptrsNeighbor, NewBranchLength,
                  Covering, NeighborCovering, IndexOrderList);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                Nptrs.np_ptr^.nd_right := NptrsNeighbor.np_ptr^.nd_id;
                b13w_release_node (NptrsNeighbor, Current);
                IF  trError_gg00 = e_ok
                THEN
                    b13w_release_node (Nptrs, Current);
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        b54execute_indexorder (IndexOrderList, Current);
    (*ENDIF*) 
    IF  trError_gg00 <> e_ok
    THEN
        BEGIN
        IF  Nptrs.np_ptr <> NIL
        THEN
            b13r_release_node (Nptrs, Current, lru_normal);
        (*ENDIF*) 
        IF  NptrsNeighbor.np_ptr <> NIL
        THEN
            b13r_release_node (NptrsNeighbor, Current, lru_normal);
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b55p_uflw_branch (VAR Nptrs : tbd_node_ptrs;
            Left               : tsp00_PageNo;
            VAR IndexOrderList : tbd00_OrderList;
            VAR Current        : tbd_current_tree);
 
VAR
      Level             : tsp00_Int2;
      DummyBranchLength : tsp00_Int4;
      Covering          : tsp00_Int4;
      NeighborCovering  : tsp00_Int4;
      Right             : tsp00_PageNo;
      FreePno           : tsp00_PageNo;
      freePageVersion   : tsp00_Int4;
      NptrsNeighbor     : tbd_node_ptrs;
 
BEGIN
WITH Current, curr_tree_id, curr_trans^ DO
    BEGIN
    trError_gg00           := e_ok;
    NptrsNeighbor.np_ptr   := NIL;
    NptrsNeighbor.np_cbptr := NIL;
    DummyBranchLength      := 0;
    FreePno                := NIL_PAGE_NO_GG00;
    WITH Nptrs, np_ptr^ DO
        BEGIN
        IF  g01glob.bd_lock_check AND (NOT bd20IsPageExclusiveLocked (np_cbptr))
        THEN
            g01abort (csp3_bd_msg, csp3_n_btree, MSG_NOT_EXCL_LOCKED, nd_id);
        (*ENDIF*) 
        Covering := nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00);
        Right    := nd_right;
        Level    := nd_level
        END;
    (*ENDWITH*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  Right = NIL_PAGE_NO_GG00
        THEN
            trError_gg00 := e_no_more_space
        ELSE
            BEGIN
            bd13GetNode (Current, Right, plmLock_ebd00, nr_for_update, NptrsNeighbor);
            IF  trError_gg00 = e_ok
            THEN   (* nCovering > 0 *)
                BEGIN
                WITH NptrsNeighbor.np_ptr^ DO
                    NeighborCovering := nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00);
                (*ENDWITH*) 
                IF  ((Covering + NeighborCovering <= FULLCOVERING_BD00) AND
                    (NOT (ftsDynamic_egg00 in fileType_gg00)))
                    OR
                    (Covering + NeighborCovering <= HALF_COVERING_BD00)
                THEN
                    BEGIN
                    IF  NOT NptrsNeighbor.np_ptr^.nd_sorted
                    THEN
                        b51sort_branches (NptrsNeighbor.np_ptr, curr_trans);
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        bd55merge_branches (Current, Nptrs, NptrsNeighbor, IndexOrderList);
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        FreePno                := NptrsNeighbor.np_ptr^.nd_id;
                        freePageVersion        := NptrsNeighbor.np_ptr^.nd_conv_version;
                        NptrsNeighbor.np_ptr   := NIL;
                        NptrsNeighbor.np_cbptr := NIL;
                        IF  trError_gg00 = e_ok
                        THEN
                            b13w_release_node (Nptrs, Current)
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                ELSE
                    IF  ftsDynamic_egg00 in fileType_gg00
                    THEN
                        BEGIN
                        b13r_release_node (NptrsNeighbor, Current, lru_normal);
                        trError_gg00 := e_no_more_space
                        END
                    ELSE
                        BEGIN
                        IF  NOT NptrsNeighbor.np_ptr^.nd_sorted
                        THEN
                            b51sort_branches (NptrsNeighbor.np_ptr, curr_trans);
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            bd55balance_to_left (Current, NptrsNeighbor, Nptrs,
                                  DummyBranchLength, NeighborCovering, Covering,
                                  IndexOrderList);
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            WITH Nptrs.np_ptr^ DO
                                BEGIN
                                nd_write_cnt := 0;
                                nd_checksum  := 0
                                END;
                            (*ENDWITH*) 
                            WITH NptrsNeighbor.np_ptr^ DO
                                BEGIN
                                nd_write_cnt := 0;
                                nd_checksum  := 0
                                END;
                            (*ENDWITH*) 
                            b13w_release_node (NptrsNeighbor, Current);
                            IF  trError_gg00 = e_ok
                            THEN
                                b13w_release_node (Nptrs, Current)
                            (*ENDIF*) 
                            END
                        ELSE
                            b13r_release_node (NptrsNeighbor, Current, lru_normal)
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  (trError_gg00 = e_no_more_space) AND (NOT (ftsDynamic_egg00 in fileType_gg00))
        THEN
            IF  Left <> NIL_PAGE_NO_GG00
            THEN
                BEGIN
                trError_gg00 := e_ok;
                bd13GetNode (Current, Left, plmLock_ebd00, nr_for_update, NptrsNeighbor);
                IF  trError_gg00 = e_ok
                THEN   (* nCovering > 0 *)
                    BEGIN
                    WITH NptrsNeighbor.np_ptr^ DO
                        NeighborCovering := nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00);
                    (*ENDWITH*) 
                    IF  (Covering + NeighborCovering) <= FULLCOVERING_BD00
                    THEN
                        BEGIN
                        IF  NOT NptrsNeighbor.np_ptr^.nd_sorted
                        THEN
                            b51sort_branches (NptrsNeighbor.np_ptr, curr_trans);
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            bd55merge_branches (Current, NptrsNeighbor, Nptrs, IndexOrderList);
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            FreePno         := Nptrs.np_ptr^.nd_id;
                            freePageVersion := Nptrs.np_ptr^.nd_conv_version;
                            Nptrs.np_ptr    := NIL;
                            Nptrs.np_cbptr  := NIL;
                            IF  trError_gg00 = e_ok
                            THEN
                                b13w_release_node (NptrsNeighbor, Current)
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        IF  NOT NptrsNeighbor.np_ptr^.nd_sorted
                        THEN
                            b51sort_branches (NptrsNeighbor.np_ptr, curr_trans);
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            bd55balance_to_right (Current, NptrsNeighbor, Nptrs,
                                  DummyBranchLength, NeighborCovering, Covering,
                                  IndexOrderList);
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            WITH Nptrs.np_ptr^ DO
                                BEGIN
                                nd_write_cnt := 0;
                                nd_checksum  := 0
                                END;
                            (*ENDWITH*) 
                            WITH NptrsNeighbor.np_ptr^ DO
                                BEGIN
                                nd_write_cnt := 0;
                                nd_checksum  := 0
                                END;
                            (*ENDWITH*) 
                            b13w_release_node (Nptrs, Current);
                            IF  trError_gg00 = e_ok
                            THEN
                                b13w_release_node (NptrsNeighbor, Current)
                            (*ENDIF*) 
                            END
                        ELSE
                            b13r_release_node (NptrsNeighbor, Current, lru_normal)
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b54execute_indexorder (IndexOrderList, Current);
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (FreePno <> NIL_PAGE_NO_GG00)
        THEN
            bd13FreePageNo (FreePno, freePageVersion, Current);
        (*ENDIF*) 
        IF  trError_gg00 = e_no_more_space
        THEN
            BEGIN
            trError_gg00 := e_ok;
            b13w_release_node (Nptrs, Current)
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 <> e_ok
    THEN
        BEGIN
        IF  Nptrs.np_ptr <> NIL
        THEN
            b13r_release_node (Nptrs, Current, lru_normal);
        (*ENDIF*) 
        IF  NptrsNeighbor.np_ptr <> NIL
        THEN
            b13r_release_node (NptrsNeighbor, Current, lru_normal)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b55t_oflw_branch (VAR Nptrs : tbd_node_ptrs;
            NewBranchLength    : tsp00_Int4;
            Left               : tsp00_PageNo;
            VAR IndexOrderList : tbd00_OrderList;
            VAR Current        : tbd_current_tree);
 
VAR
      Level             : tsp00_Int2;
      Covering         : tsp00_Int4;
      NeighborCovering : tsp00_Int4;
      Right            : tsp00_PageNo;
      NptrsNeighbor    : tbd_node_ptrs;
 
BEGIN
WITH Current, curr_trans^ DO
    BEGIN
    NptrsNeighbor.np_ptr   := NIL;
    NptrsNeighbor.np_cbptr := NIL;
    WITH Nptrs, np_ptr^ DO
        BEGIN
        IF  g01glob.bd_lock_check AND (NOT bd20IsPageExclusiveLocked (np_cbptr))
        THEN
            g01abort (csp3_bd_msg, csp3_n_btree, MSG_NOT_EXCL_LOCKED, nd_id);
        (*ENDIF*) 
        Covering := nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00);
        Right    := nd_right
        END;
    (*ENDWITH*) 
    NewBranchLength := b01rec_align (NewBranchLength) + POINTERSIZE_BD00;
    IF  (Right = NIL_PAGE_NO_GG00) OR  (ftsDynamic_egg00 in curr_tree_id.fileType_gg00)
    THEN
        trError_gg00 := e_no_more_space
    ELSE
        BEGIN
        bd13GetNode (Current, Right, plmLock_ebd00, nr_for_update, NptrsNeighbor);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            WITH NptrsNeighbor.np_ptr^ DO
                NeighborCovering := nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00);
            (*ENDWITH*) 
            IF  (Covering + NeighborCovering + NewBranchLength) > 2 * FULLCOVERING_BD00
            THEN
                trError_gg00 := e_no_more_space
            ELSE
                BEGIN
                IF  NOT NptrsNeighbor.np_ptr^.nd_sorted
                THEN
                    b51sort_branches (NptrsNeighbor.np_ptr, curr_trans);
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    bd55balance_to_right (Current, Nptrs, NptrsNeighbor, NewBranchLength,
                          Covering, NeighborCovering, IndexOrderList)
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_no_more_space
            THEN
                b13r_release_node (NptrsNeighbor, Current, lru_normal)
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 = e_no_more_space) AND (NOT (ftsDynamic_egg00 in curr_tree_id.fileType_gg00))
    THEN
        BEGIN
        trError_gg00 := e_ok;
        IF  Left = NIL_PAGE_NO_GG00
        THEN
            trError_gg00 := e_no_more_space
        ELSE
            BEGIN
            bd13GetNode (Current, Left, plmLock_ebd00, nr_for_update, NptrsNeighbor);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                WITH NptrsNeighbor.np_ptr^ DO
                    NeighborCovering := nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00);
                (*ENDWITH*) 
                IF  (Covering + NeighborCovering + NewBranchLength) > 2 * FULLCOVERING_BD00
                THEN
                    trError_gg00 := e_no_more_space
                ELSE
                    BEGIN
                    IF  NOT NptrsNeighbor.np_ptr^.nd_sorted
                    THEN
                        b51sort_branches(NptrsNeighbor.np_ptr,curr_trans);
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        bd55balance_to_left (Current, Nptrs, NptrsNeighbor,
                              NewBranchLength, Covering, NeighborCovering,
                              IndexOrderList)
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_no_more_space
            THEN
                b13r_release_node (NptrsNeighbor, Current, lru_normal)
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_no_more_space
    THEN
        BEGIN
        trError_gg00 := e_ok;
        Level        := Nptrs.np_ptr^.nd_level;
        b13new_node (Level, NptrsNeighbor, Current);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            NptrsNeighbor.np_ptr^.nd_right := Nptrs.np_ptr^.nd_right;
            Nptrs.np_ptr^.nd_right         := NptrsNeighbor.np_ptr^.nd_id;
            NeighborCovering               := 0;
            bd55balance_to_right (Current, Nptrs, NptrsNeighbor, NewBranchLength,
                  Covering, NeighborCovering, IndexOrderList)
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        b54execute_indexorder (IndexOrderList, Current);
    (*ENDIF*) 
    IF  trError_gg00 <> e_ok
    THEN
        BEGIN
        IF  Nptrs.np_ptr <> NIL
        THEN
            b13r_release_node (Nptrs, Current, lru_normal);
        (*ENDIF*) 
        IF  NptrsNeighbor.np_ptr <> NIL
        THEN
            b13r_release_node (NptrsNeighbor, Current, lru_normal)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b55t_uflw_branch (VAR Nptrs : tbd_node_ptrs;
            Left               : tsp00_PageNo;
            VAR IndexOrderList : tbd00_OrderList;
            VAR Current        : tbd_current_tree);
 
VAR
      Covering          : tsp00_Int4;
      NeighborCovering  : tsp00_Int4;
      DummyBranchLength : tsp00_Int4;
      Right             : tsp00_PageNo;
      NptrsNeighbor     : tbd_node_ptrs;
 
BEGIN
WITH Current, curr_trans^ DO
    BEGIN
    NptrsNeighbor.np_ptr   := NIL;
    NptrsNeighbor.np_cbptr := NIL;
    WITH Nptrs, np_ptr^ DO
        BEGIN
        IF  g01glob.bd_lock_check AND (NOT bd20IsPageExclusiveLocked (np_cbptr))
        THEN
            g01abort (csp3_bd_msg, csp3_n_btree, MSG_NOT_EXCL_LOCKED, nd_id);
        (*ENDIF*) 
        Right    := nd_right;
        Covering := nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00)
        END;
    (*ENDWITH*) 
    DummyBranchLength := 0;
    IF  Right = NIL_PAGE_NO_GG00
    THEN
        trError_gg00 := e_no_more_space
    ELSE
        BEGIN
        bd13GetNode (Current, Right, plmLock_ebd00, nr_for_update, NptrsNeighbor);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            WITH NptrsNeighbor.np_ptr^ DO
                NeighborCovering := nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00);
            (*ENDWITH*) 
            IF  ((Covering + NeighborCovering <= FULLCOVERING_BD00) AND
                (NOT (ftsDynamic_egg00 in curr_tree_id.fileType_gg00)))
                OR
                (Covering + NeighborCovering <= HALF_COVERING_BD00)
            THEN
                BEGIN
                IF  NOT NptrsNeighbor.np_ptr^.nd_sorted
                THEN
                    b51sort_branches (NptrsNeighbor.np_ptr, curr_trans);
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    bd55merge_branches (Current, Nptrs, NptrsNeighbor, IndexOrderList)
                (*ENDIF*) 
                END
            ELSE
                IF  ftsDynamic_egg00 in curr_tree_id.fileType_gg00
                THEN
                    trError_gg00 := e_no_more_space
                ELSE
                    BEGIN
                    IF  NOT NptrsNeighbor.np_ptr^.nd_sorted
                    THEN
                        b51sort_branches(NptrsNeighbor.np_ptr,curr_trans);
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        bd55balance_to_left (Current, NptrsNeighbor, Nptrs,
                              DummyBranchLength, NeighborCovering, Covering, IndexOrderList)
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            IF  trError_gg00 = e_no_more_space
            THEN
                b13r_release_node (NptrsNeighbor, Current, lru_normal)
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_no_more_space
    THEN
        BEGIN
        trError_gg00 := e_ok;
        IF  (Left = NIL_PAGE_NO_GG00) OR (ftsDynamic_egg00 in curr_tree_id.fileType_gg00)
        THEN
            trError_gg00 := e_no_more_space
        ELSE
            BEGIN
            bd13GetNode (Current, Left, plmLock_ebd00, nr_for_update, NptrsNeighbor);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                WITH NptrsNeighbor.np_ptr^ DO
                    NeighborCovering := nd_bottom - BODY_BEG_BD00 + (nd_record_cnt * POINTERSIZE_BD00);
                (*ENDWITH*) 
                IF  (Covering + NeighborCovering) <= FULLCOVERING_BD00
                THEN
                    BEGIN
                    IF  NOT NptrsNeighbor.np_ptr^.nd_sorted
                    THEN
                        b51sort_branches(NptrsNeighbor.np_ptr,curr_trans);
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        bd55merge_branches (Current, NptrsNeighbor, Nptrs, IndexOrderList)
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    IF  NOT NptrsNeighbor.np_ptr^.nd_sorted
                    THEN
                        b51sort_branches (NptrsNeighbor.np_ptr,curr_trans);
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        bd55balance_to_right (Current, NptrsNeighbor, Nptrs,
                              DummyBranchLength, NeighborCovering, Covering, IndexOrderList)
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  trError_gg00 = e_no_more_space
                THEN
                    b13r_release_node (NptrsNeighbor, Current, lru_normal)
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_no_more_space
        THEN
            BEGIN
            trError_gg00 := e_ok;
            b13w_release_node (Nptrs, Current)
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        b54execute_indexorder (IndexOrderList, Current);
    (*ENDIF*) 
    IF  trError_gg00 <> e_ok
    THEN
        BEGIN
        IF  Nptrs.np_ptr <> NIL
        THEN
            b13r_release_node (Nptrs, Current, lru_normal);
        (*ENDIF*) 
        IF  NptrsNeighbor.np_ptr <> NIL
        THEN
            b13r_release_node (NptrsNeighbor, Current, lru_normal)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd55merge_branches (VAR Current : tbd_current_tree;
            VAR NptrsLeft      : tbd_node_ptrs;
            VAR NptrsRight     : tbd_node_ptrs;
            VAR IndexOrderList : tbd00_OrderList);
 
VAR
      Level  : tsp00_Int2;
      Amount : tsp00_Int4;
      SepKey : tgg00_Lkey;
 
BEGIN
WITH Current, curr_trans^ DO
    BEGIN
&   ifdef TRACE
    t01page (bd_oflw, NptrsLeft.np_ptr^, 1, NptrsLeft.np_ptr^.nd_bottom);
    t01page (bd_oflw, NptrsLeft.np_ptr^,
          MAX_BOTTOM_BD00 - (NptrsLeft.np_ptr^.nd_record_cnt * POINTERSIZE_BD00),
          sizeof (NptrsLeft.np_ptr^));
    t01page (bd_oflw, NptrsRight.np_ptr^, 1, NptrsRight.np_ptr^.nd_bottom);
    t01page (bd_oflw, NptrsRight.np_ptr^,
          MAX_BOTTOM_BD00 - (NptrsRight.np_ptr^.nd_record_cnt * POINTERSIZE_BD00),
          sizeof (NptrsRight.np_ptr^));
&   endif
    trError_gg00 := e_ok;
    Amount       := NptrsRight.np_ptr^.nd_bottom - BODY_BEG_BD00;
    bd52GetSepKey (NptrsRight.np_ptr, FIRST_REC_INDEX_BD00, SepKey, curr_trans);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        Level := NptrsRight.np_ptr^.nd_level;
        b54del_index (@SepKey.keyVal_gg00, SepKey.keyLen_gg00, Level, IndexOrderList);
        NptrsLeft.np_ptr^.nd_right := NptrsRight.np_ptr^.nd_right;
        g10mv ('VBD55 ',   1,    
              sizeof (NptrsRight.np_ptr^), sizeof (NptrsLeft.np_ptr^),
              @NptrsRight.np_ptr^, BODY_BEG_BD00,
              @NptrsLeft.np_ptr^, NptrsLeft.np_ptr^.nd_bottom, 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,
                  NptrsRight.np_ptr^.nd_id, NptrsRight.np_ptr, 1);
            b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                  NptrsLeft.np_ptr^.nd_id, NptrsLeft.np_ptr, 1)
            END
        ELSE
            BEGIN
            NptrsLeft.np_ptr^.nd_bottom := NptrsLeft.np_ptr^.nd_bottom + Amount;
&           ifdef TRACE
            t01page (bd_oflw, NptrsLeft.np_ptr^, 1, NptrsLeft.np_ptr^.nd_bottom);
&           endif
            b51pointer_list (NptrsLeft.np_ptr);
            IF  ftsTemp_egg00 in curr_tree_id.fileType_gg00
            THEN
                BEGIN
                b13w_release_node (NptrsLeft, Current);
                IF  trError_gg00 = e_ok
                THEN
                    b13free_node (NptrsRight, Current);
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd55balance_to_right (VAR Current : tbd_current_tree;
            VAR Nptrs          : tbd_node_ptrs;
            VAR NptrsRight     : tbd_node_ptrs;
            NewBranchLength    : tsp00_Int4;
            Covering           : tsp00_Int4;
            RightCovering      : tsp00_Int4;
            VAR IndexOrderList : tbd00_OrderList);
 
VAR
      Level        : tsp00_Int2;
      oflw         : tsp00_Int4;
      opt_oflw     : tsp00_Int4;
      ptrlist_oflw : tsp00_Int4;
      RecPos       : tsp00_Int4;
      RecIndex     : tsp00_Int4;
      OldSepKey    : tgg00_Lkey;
      NewSepKey    : tgg00_Lkey;
 
BEGIN
&ifdef TRACE
t01page (bd_oflw, Nptrs.np_ptr^, 1, Nptrs.np_ptr^.nd_bottom);
t01page (bd_oflw, Nptrs.np_ptr^,
      MAX_BOTTOM_BD00 - (Nptrs.np_ptr^.nd_record_cnt * POINTERSIZE_BD00),
      sizeof (Nptrs.np_ptr^));
t01page (bd_oflw, NptrsRight.np_ptr^, 1, NptrsRight.np_ptr^.nd_bottom);
t01page (bd_oflw, NptrsRight.np_ptr^,
      MAX_BOTTOM_BD00 - (NptrsRight.np_ptr^.nd_record_cnt * POINTERSIZE_BD00),
      sizeof (NptrsRight.np_ptr^));
&endif
WITH Current, curr_tree_id, curr_trans^ DO
    BEGIN
    trError_gg00   := e_ok;
    Level          := Nptrs.np_ptr^.nd_level;
    opt_oflw       := Covering - ((Covering + RightCovering) DIV 2);
    IF  opt_oflw <= 0
    THEN
        trError_gg00 := e_no_more_space
    ELSE
        BEGIN
        ptrlist_oflw := 0;
        RecIndex     := Nptrs.np_ptr^.nd_record_cnt - 1;
        oflw         := 0;
        REPEAT
            WITH Nptrs.np_ptr^ DO
                BEGIN
                RecPos       := nd_pointer_list [MAX_POINTERINDEX_BD00 - RecIndex];
                oflw         := nd_bottom - RecPos;
                RecIndex     := pred (RecIndex);
                ptrlist_oflw := ptrlist_oflw + POINTERSIZE_BD00
                END
            (*ENDWITH*) 
        UNTIL
            oflw + ptrlist_oflw  >= opt_oflw;
        (*ENDREPEAT*) 
        IF  (Covering + NewBranchLength - oflw - ptrlist_oflw > FULLCOVERING_BD00     ) OR
            (RightCovering + NewBranchLength + oflw + ptrlist_oflw > FULLCOVERING_BD00)
        THEN
            trError_gg00 := e_no_more_space
        ELSE
            BEGIN
            IF  RightCovering > 0
            THEN
                bd52GetSepKey (NptrsRight.np_ptr, FIRST_REC_INDEX_BD00, OldSepKey, curr_trans);
            (*ENDIF*) 
            b35add_space (NptrsRight.np_ptr, BODY_BEG_BD00, oflw, curr_trans);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                Nptrs.np_ptr^.nd_bottom := Nptrs.np_ptr^.nd_bottom - oflw;
                g10mv ('VBD55 ',   2,    
                      sizeof (Nptrs.np_ptr^), sizeof (NptrsRight.np_ptr^),
                      @Nptrs.np_ptr^, Nptrs.np_ptr^.nd_bottom,
                      @NptrsRight.np_ptr^, BODY_BEG_BD00, oflw, 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,
                          Nptrs.np_ptr^.nd_id, Nptrs.np_ptr, 1);
                    b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                          NptrsRight.np_ptr^.nd_id, NptrsRight.np_ptr, 1)
                    END
                ELSE
                    BEGIN
&                   ifdef TRACE
                    t01page (bd_oflw, Nptrs.np_ptr^, 1, Nptrs.np_ptr^.nd_bottom);
                    t01page (bd_oflw, NptrsRight.np_ptr^, 1, NptrsRight.np_ptr^.nd_bottom);
&                   endif
                    b51pointer_list (Nptrs.np_ptr);
                    b51pointer_list (NptrsRight.np_ptr);
                    bd52GetSepKey (NptrsRight.np_ptr, FIRST_REC_INDEX_BD00,
                          NewSepKey, curr_trans);
                    IF  RightCovering > 0
                    THEN
                        b54repl_index (@OldSepKey.keyVal_gg00, OldSepKey.keyLen_gg00,
                              @NewSepKey.keyVal_gg00, NewSepKey.keyLen_gg00,
                              NptrsRight.np_ptr^.nd_id, Level, IndexOrderList)
                    ELSE
                        b54add_index (@NewSepKey.keyVal_gg00, NewSepKey.keyLen_gg00,
                              NptrsRight.np_ptr^.nd_id, Level, IndexOrderList);
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  (ftsTemp_egg00 in fileType_gg00) AND (trError_gg00 = e_ok)
                THEN
                    BEGIN
                    b13w_release_node (NptrsRight, Current);
                    b13w_release_node (Nptrs, Current);
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd55balance_to_left (VAR Current : tbd_current_tree;
            VAR Nptrs          : tbd_node_ptrs;
            VAR NptrsLeft      : tbd_node_ptrs;
            NewBranchLength    : tsp00_Int4;
            Covering           : tsp00_Int4;
            LeftCovering       : tsp00_Int4;
            VAR IndexOrderList : tbd00_OrderList);
 
VAR
      Level        : tsp00_Int2;
      oflw         : tsp00_Int4;
      opt_oflw     : tsp00_Int4;
      ptrlist_oflw : tsp00_Int4;
      RecPos       : tsp00_Int4;
      RecIndex     : tsp00_Int4;
      OldSepKey    : tgg00_Lkey;
      NewSepKey    : tgg00_Lkey;
 
BEGIN
&ifdef TRACE
t01page (bd_oflw, NptrsLeft.np_ptr^, 1, NptrsLeft.np_ptr^.nd_bottom);
t01page (bd_oflw, NptrsLeft.np_ptr^,
      MAX_BOTTOM_BD00 - (NptrsLeft.np_ptr^.nd_record_cnt * POINTERSIZE_BD00),
      sizeof (NptrsLeft.np_ptr^));
t01page (bd_oflw, Nptrs.np_ptr^, 1, Nptrs.np_ptr^.nd_bottom);
t01page (bd_oflw, Nptrs.np_ptr^,
      MAX_BOTTOM_BD00 - (Nptrs.np_ptr^.nd_record_cnt * POINTERSIZE_BD00),
      sizeof (Nptrs.np_ptr^));
&endif
WITH Current, curr_tree_id, curr_trans^ DO
    BEGIN
    trError_gg00   := e_ok;
    (* Covering >> halfcovering *)
    opt_oflw := Covering - ((Covering + LeftCovering) DIV 2);
    IF  opt_oflw <= 0
    THEN
        trError_gg00 := e_no_more_space
    ELSE
        BEGIN
        ptrlist_oflw := - POINTERSIZE_BD00;
        RecIndex     := FIRST_REC_INDEX_BD00;
        oflw         := 0;
        WITH Nptrs.np_ptr^ DO
            BEGIN
            Level := nd_level;
            REPEAT
                IF  RecIndex < nd_record_cnt - 1
                THEN
                    RecPos := nd_pointer_list [MAX_POINTERINDEX_BD00 - RecIndex]
                ELSE
                    RecPos := nd_bottom;
                (*ENDIF*) 
                oflw         := RecPos - BODY_BEG_BD00;
                ptrlist_oflw := ptrlist_oflw + POINTERSIZE_BD00;
                RecIndex     := succ (RecIndex)
            UNTIL
                oflw + ptrlist_oflw >= opt_oflw
            (*ENDREPEAT*) 
            END;
        (*ENDWITH*) 
        IF  (Covering + NewBranchLength - oflw - ptrlist_oflw > FULLCOVERING_BD00    ) OR
            (LeftCovering + NewBranchLength + oflw + ptrlist_oflw > FULLCOVERING_BD00)
        THEN
            trError_gg00 := e_no_more_space
        ELSE
            BEGIN
            bd52GetSepKey (Nptrs.np_ptr, FIRST_REC_INDEX_BD00, OldSepKey, curr_trans);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                g10mv ('VBD55 ',   3,    
                      sizeof (Nptrs.np_ptr^), sizeof (NptrsLeft.np_ptr^),
                      @Nptrs.np_ptr^, BODY_BEG_BD00,
                      @NptrsLeft.np_ptr^, NptrsLeft.np_ptr^.nd_bottom, oflw,
                      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,
                          Nptrs.np_ptr^.nd_id, Nptrs.np_ptr, 1);
                    b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                          NptrsLeft.np_ptr^.nd_id, NptrsLeft.np_ptr, 1)
                    END
                ELSE
                    BEGIN
                    NptrsLeft.np_ptr^.nd_bottom := NptrsLeft.np_ptr^.nd_bottom + oflw;
                    b35del_space (Nptrs.np_ptr, BODY_BEG_BD00, oflw, curr_trans);
&                   ifdef TRACE
                    t01page (bd_oflw, NptrsLeft.np_ptr^, 1, NptrsLeft.np_ptr^.nd_bottom);
                    t01page (bd_oflw, Nptrs.np_ptr^, 1, Nptrs.np_ptr^.nd_bottom);
&                   endif
                    bd52GetSepKey (Nptrs.np_ptr, FIRST_REC_INDEX_BD00, NewSepKey, curr_trans);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        b54repl_index (@OldSepKey.keyVal_gg00, OldSepKey.keyLen_gg00,
                              @NewSepKey.keyVal_gg00, NewSepKey.keyLen_gg00,
                              Nptrs.np_ptr^.nd_id, Level, IndexOrderList);
                        b51pointer_list (Nptrs.np_ptr);
                        b51pointer_list (NptrsLeft.np_ptr);
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  (ftsTemp_egg00 in fileType_gg00) AND (trError_gg00 = e_ok)
            THEN
                BEGIN
                b13w_release_node (Nptrs, Current);
                b13w_release_node (NptrsLeft, Current);
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
