.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$VBD31$
.tt 2 $$$
.tt 3 $JuergenP$leafhandling$$1999-03-29$
***********************************************************
.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  : leafhandling
=========
.sp
Purpose : operation on leafs containing primary data
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        PROCEDURE
              b31add_to_leaf (VAR b : tgg00_Rec;
                    VAR nptr    : tbd_node_ptrs;
                    index       : integer;
                    left        : tsp00_PageNo;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd31AddToLeaf (VAR b : tgg00_Rec;
                    VAR nptr      : tbd_node_ptrs;
                    index         : integer;
                    left          : tsp00_PageNo;
                    VAR current   : tbd_current_tree;
                    useBeforeRef  : boolean;
                    VAR beforeRef : tgg91_PageRef);
 
        PROCEDURE
              bd31AppendToLeaf (
                    VAR b           : tgg00_Rec;
                    VAR nptr        : tbd_node_ptrs;
                    index           : integer;
                    left            : tsp00_PageNo;
                    VAR current     : tbd_current_tree;
                    useBeforeRef    : boolean;
                    VAR beforeRef   : tgg91_PageRef);
 
        PROCEDURE
              b31del_from_leaf (VAR nptr : tbd_node_ptrs;
                    index       : integer;
                    left        : tsp00_PageNo;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b31get_from_leaf (VAR nptr : tbd_node_ptrs;
                    index        : integer;
                    with_kb_lock : boolean;
                    VAR b        : tgg00_Rec;
                    VAR current  : tbd_current_tree);
 
        PROCEDURE
              b31next_search (
                    VAR nptr    : tbd_node_ptrs;
                    VAR index   : integer;
                    VAR current : tbd_current_tree;
                    lruInfo     : tbd_lru_info );
 
        PROCEDURE
              b31nfill_recordbuffer (
                    VAR nptr         : tbd_node_ptrs;
                    VAR test_key     : tgg00_Lkey;
                    VAR tree_pos     : tgg00_FilePos;
                    VAR set_result   : tgg00_BdSetResultRecord;
                    VAR resultBuffer : tsp00_MoveObj;
                    VAR current      : tbd_current_tree);
 
        PROCEDURE
              b31pfill_recordbuffer (
                    VAR nptr         : tbd_node_ptrs;
                    VAR test_key     : tgg00_Lkey;
                    VAR tree_pos     : tgg00_FilePos;
                    VAR set_result   : tgg00_BdSetResultRecord;
                    VAR resultBuffer : tsp00_MoveObj;
                    VAR current      : tbd_current_tree);
 
        PROCEDURE
              b31pointer_list (VAR nptr : tbd_nodeptr);
 
        PROCEDURE
              bd31PrevSearch (
                    VAR recKey        : tsp00_Key (* ptocSynonym tsp00_KeyPtr *);
                    keyLen            : tsp00_Int4;
                    VAR pNodes        : tbd_node_ptrs;
                    VAR recIndex      : integer;
                    VAR prevLeafPage  : tsp00_PageNo;
                    VAR current       : tbd_current_tree;
                    bGetLeafForUpdate : boolean);
 
        PROCEDURE
              b31repl_in_leaf (VAR b : tgg00_Rec;
                    VAR nptr    : tbd_node_ptrs;
                    index       : integer;
                    left        : tsp00_PageNo;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd31ReplaceInLeaf (VAR b : tgg00_Rec;
                    VAR nptr      : tbd_node_ptrs;
                    index         : integer;
                    left          : tsp00_PageNo;
                    VAR current   : tbd_current_tree;
                    VAR beforeRef : tgg91_PageRef;
                    VAR updTrans  : tgg91_TransNo);
 
        PROCEDURE
              b31search_entry (VAR current : tbd_current_tree;
                    VAR rk     : tsp00_Key;
                    KeyLen     : tsp00_Int4;
                    VAR nptr   : tbd_nodeptr;
                    VAR index  : tsp00_Int4;
                    VAR result : tbd_searchresult);
 
        PROCEDURE
              b31sort_entries (VAR nptr : tbd_nodeptr;
                    t : tgg00_TransContextPtr);
 
        PROCEDURE
              b31t_append_to_temp_leaf (VAR b : tgg00_Rec;
                    VAR nptr     : tbd_node_ptrs;
                    VAR tree_pos : tgg00_FilePos;
                    VAR current  : tbd_current_tree);
 
        PROCEDURE
              b31t_prev_temp_search (VAR nptr : tbd_node_ptrs;
                    VAR index   : integer;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b31w_next_search (
                    VAR nptr          : tbd_node_ptrs;
                    VAR index         : integer;
                    VAR current       : tbd_current_tree);
 
.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);
 
        PROCEDURE
              bd06CorruptedTreeHandling (
                    VAR fileId : tgg00_FileId;
                    msgNo      : tsp00_Int4;
                    trError    : tgg00_BasisError);
 
      ------------------------------ 
 
        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
              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);
&       ifdef trace
 
        PROCEDURE
              t01moveobj (
                    debug       : tgg00_Debug;
                    VAR moveobj : tgg00_Rec (*ptocSynonym const void**);
                    startpos    : tsp00_Int4;
                    endpos      : tsp00_Int4);
&       endif
 
      ------------------------------ 
 
        FROM
              filedirectory : VBD17;
 
        FUNCTION
              bd17GetBlobFdirRoot : tsp00_PageNo;
 
      ------------------------------ 
 
        FROM
              systembufferinterface : VBD20;
 
        FUNCTION
              bd20GetDestinationConverterVersion (
                    TaskId  : tsp00_TaskId;
                    pCBlock : tbd_nodeptr) : tgg00_ConverterVersion;
 
        FUNCTION
              bd20IsPageExclusiveLocked (
                    pCBlock : tbd_nodeptr) : boolean;
 
      ------------------------------ 
 
        FROM
              treehandling : VBD30;
 
        PROCEDURE
              bd30GetSubTree (
                    VAR current : tbd_current_tree;
                    indexPageNo : tsp00_PageNo);
 
        PROCEDURE
              bd30ReleaseSubTree(
                    VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              leafoverflow : VBD33;
 
        PROCEDURE
              bd33AppendNewLeaf (
                    VAR current     : tbd_current_tree;
                    VAR rec         : tgg00_Rec;
                    VAR nptr        : tbd_node_ptrs;
                    index           : integer;
                    VAR newLeafPage : tsp00_PageNo);
 
        PROCEDURE
              bd33LeafOverflow (
                    VAR current   : tbd_current_tree;
                    VAR rec       : tgg00_Rec;
                    VAR nptr      : tbd_node_ptrs;
                    index         : integer;
                    left          : tsp00_PageNo);
 
        PROCEDURE
              bd33AppendNewTempLeaf (
                    VAR current     : tbd_current_tree;
                    VAR rec         : tgg00_Rec;
                    VAR nptr        : tbd_node_ptrs;
                    index           : integer;
                    VAR newLeafPage : tsp00_PageNo);
 
        PROCEDURE
              bd33TempLeafOverflow (
                    VAR current   : tbd_current_tree;
                    VAR rec       : tgg00_Rec;
                    VAR nptr      : tbd_node_ptrs;
                    index         : integer;
                    left          : tsp00_PageNo);
 
      ------------------------------ 
 
        FROM
              b34leafunderflow : VBD34;
 
        PROCEDURE
              bd34LeafUnderflow (
                    VAR current : tbd_current_tree;
                    VAR nptr    : tbd_node_ptrs;
                    left        : tsp00_PageNo);
 
        PROCEDURE
              bd34TempLeafUnderflow (
                    VAR current : tbd_current_tree;
                    VAR nptr    : tbd_node_ptrs;
                    left        : tsp00_PageNo);
 
      ------------------------------ 
 
        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);
 
        PROCEDURE
              b35get_entrykey (VAR nptr : tbd_nodeptr;
                    index   : integer;
                    VAR sep : tgg00_Lkey;
                    t       : tgg00_TransContextPtr);
 
        PROCEDURE
              b35next_entry (VAR nptr : tbd_nodeptr;
                    VAR index : integer;
                    VAR last  : boolean);
 
      ------------------------------ 
 
        FROM
              indexhandling : VBD50;
 
        PROCEDURE
              bd50FindFirstLevelIndexNode (
                    VAR reckey  : tsp00_Key;
                    keyLen      : tsp00_Int4;
                    VAR nptrs   : tbd_node_ptrs;
                    VAR neighbs : tbd_neighbors;
                    VAR found   : boolean;
                    VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              branchnodehandling : VBD51;
 
        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
              bd51SearchBranch (VAR Current : tbd_current_tree;
                    pSepKey      : tsp00_KeyAddr;
                    KeyLen       : tsp00_Int4;
                    VAR Nptr     : tbd_nodeptr;
                    VAR RecIndex : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              branchhandling : VBD52;
 
        FUNCTION
              bd52SubtreePno (VAR nptr : tbd_nodeptr;
                    RecIndex : tsp00_Int4) : tsp00_PageNo;
 
      ------------------------------ 
 
        FROM
              indexupdateorders : VBD54;
 
        PROCEDURE
              b54del_index (pSep       : tsp00_KeyAddr;
                    SepLen             : tsp00_Int4;
                    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;
 
        PROCEDURE
              b54texecute_indexorder (
                    pIndexOrderList    : tsp00_Addr;
                    VAR current        : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              FileDir_Wrapper : VBD998;
 
        PROCEDURE
              bd998ModifyPageAndRecordCount (
                    VAR trans           : tgg00_TransContext;
                    convVersion         : tgg00_ConverterVersion;
                    VAR fileNo          : tgg00_Surrogate;
                    leafPageCountDelta  : tsp00_Int4;
                    indexPageCountDelta : tsp00_Int4;
                    entryCountDelta     : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              BD_Wrapper : VBD999;
 
        FUNCTION
              Data_GetRecLen (pRec : tgg00_RecPtr) : integer;
 
        FUNCTION
              Data_GetKeyLen (pRec : tgg00_RecPtr) : integer;
 
        PROCEDURE
              bd999CopyRecord (
                    pRec                 : tgg00_RecPtr;
                    withTransHistoryInfo : boolean;
                    destSize             : tsp00_Int4;
                    pDest                : tsp00_Addr;
                    VAR destPos          : tsp00_Int4;
                    VAR e                : tgg00_BasisError);
 
        PROCEDURE
              bd999CreateTransHistoryInfo (
                    VAR transContext : tgg00_TransContext;
                    VAR node         : tbd_node;
                    pRec             : tgg00_RecPtr;
                    VAR beforeRef    : tgg91_PageRef;
                    VAR e            : tgg00_BasisError);
 
        PROCEDURE
              bd999UpdateTransHistoryInfo (
                    TaskId        : tsp00_TaskId;
                    pOldRec       : tgg00_RecPtr;
                    pNewRec       : tgg00_RecPtr;
                    VAR beforeRef : tgg91_PageRef (*ptocconst*);
                    VAR updTrans  : tgg91_TransNo (*ptocconst*);
                    VAR e         : tgg00_BasisError);
 
        FUNCTION
              bd999UnpackRow (
                    VAR Source      : tgg00_Rec;
                    VAR Destination : tgg00_Rec) : tgg00_RecPtr;
 
        PROCEDURE
              bd999CreateIndexOrderList(
                    VAR trans           : tgg00_TransContext;
                    VAR pIndexOrderList : tsp00_Addr);
 
        PROCEDURE
              bd999DestroyIndexOrderList(
                    VAR trans           : tgg00_TransContext;
                    VAR pIndexOrderList : tsp00_Addr);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        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;
 
        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
              KB_transaction : VKB53;
 
        PROCEDURE
              k53bd_share_lock (VAR t : tgg00_TransContext;
                    VAR file_id       : tgg00_FileId;
                    VAR rec_buf       : tgg00_Rec);
 
      ------------------------------ 
 
        FROM
              RTE-Extension-30 : VSP30;
 
        PROCEDURE
              s30cmp (VAR buf1   : tsp00_Key;
                    fieldpos1    : tsp00_Int4;
                    fieldlength1 : tsp00_Int4;
                    VAR buf2     : tbd_node;
                    fieldpos2    : tsp00_Int4;
                    fieldlength2 : tsp00_Int4;
                    VAR l_result : tsp00_LcompResult);
 
        PROCEDURE
              s30cmp1 (VAR buf1  : tsp00_Key;
                    fieldpos1    : tsp00_Int4;
                    fieldlength1 : tsp00_Int4;
                    VAR buf2     : tgg00_RecBody;
                    fieldpos2    : tsp00_Int4;
                    fieldlength2 : tsp00_Int4;
                    VAR l_result : tsp00_LcompResult);
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
        PROCEDURE
              b06dump_bad_page;
 
              tbd_univ_ptr tbd_nodeptr
 
        FUNCTION
              bd20GetDestinationConverterVersion;
 
              tbd02_pDataCBlock tbd_nodeptr
 
        FUNCTION
              bd20IsPageExclusiveLocked;
 
              tbd02_pDataCBlock tbd_nodeptr
 
        PROCEDURE
              s30cmp;
 
              tsp00_MoveObj tsp00_Key
              tsp00_MoveObj tbd_node
 
        PROCEDURE
              s30cmp1;
 
              tsp00_MoveObj tsp00_Key
              tsp00_MoveObj tgg00_RecBody
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  :
.sp
.cp 3
Created : 1979-11-13
.sp
.cp 3
.sp
.cp 3
Release :      Date : 1999-03-29
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
 
The routines described below operate on the leaves of the
current B* tree (VAR current, see treehandling).  They require that
this tree serve to maintain a primary file (see filesysteminterface)
and that, consequently, record entries are accommodated in the leaves.
.sp
The
.oc _/1;tree_address
of a record entry consists of the page number of the leaf and the
position at which the record entry begins within the leaf.  If more
than one entry begins in a leaf, their positions are sorted in a
list in ascending order by record keys; the entries themselves
can be unordered within the leaf.  Consecutive record entries are
accomodated in neighboring leaves.
.sp
The tree addresses of some of the last record entries to be
referenced are temporarily stored in a short-term memory
(see keymemory) in order to support the sequential processing
of the file.  Whenever the routines described below change the
tree addresses of record entries, they implement the necessary
corrections in the short-term memory themselves.
.sp
The nodes of the current B* tree that are not leaves form the
B* index, which contains a (generally multilevel) index of the
record entries of the tree (see indexhandling).  Changes in the
leaves may result in the need for minor modifications in the
B* index.  If this is the case, the routines concerned compile
suitable orders into a special order list (VAR indexorderlist,
see indexupdateorders) that must be sequentially processed after
the routine has been executed.
.sp 2;.cp 4
b31add_to_leaf(b,nptr,index,left,bd_use_info,
.br
               current,e)
.sp
The record in record buffer b is inserted in the leaf indicated by
the pointer nptr at the position to be determined via 'index'.
If bd_unbuffered is contained in bd_use_info, each page that is
updated is written through to the secondary storage.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_no_more_space
   - b_disk_not_accessible
.sp 2
b31append_to_leaf(b,nptr,index,page_fill_limit,
.br
                left,bd_use_info,current,e)
.sp
The record in record buffer b is inserted after the last record
entry in the leaf indicated by the pointer nptr.  This occurs,
however, only if page_fill_limit will not be exceeded; otherwise,
a new leaf would be appended to the tree.
If bd_unbuffered is contained in bd_use_info, each page that is
changed is written through to the secondary storage.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_no_more_space
   - b_disk_not_accessible
.sp 2
b31repl_in_leaf(b,nptr,index,left,bd_use_info,
.br
                current,e)
.sp
In the leaf indicated by the pointer nptr, the record identified
by 'index' is replaced by the record in record buffer b.
This requires that the two records have the same key.
If bd_unbuffered is contained in bd_use_info, each page that is
changed is written through to the secondary storage.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_no_more_space
   - b_disk_not_accessible
.sp 2
b31del_from_leaf (nptr, index, left, current)
.sp
In the leaf indicated by the pointer nptr, the record identified by
'index' is deleted from the current B* tree.
If bd_unbuffered IN current.curr_tree_id.bd_use each page that is
changed is written through to the secondary storage.
.br
Some possible acknowledgements in current.curr_trans^.trError_gg00:
   - e_ok
.sp 2
b31get_from_leaf (nptr, index, with_kb_lock, b, current)
.sp
The record identified by 'index' is copied from the leaf indicated by
the pointer nptr to the record buffer b.
.br
Some possible acknowledgements in current.curr_trans^.trError_gg00:
   - e_ok
   - e_illegal_entrypos
   - e_invalid_entrypos
.sp 2
b31search_entry(rk,nptr,index,result,current,e)
.sp
This routine searches the leaf indicated by the pointer nptr for
the record entry with the key rk and displays (when e = e_ok)
in 'result' the result of the search as follows:
.sp ;.of 12
thisfound : The entry was found and 'index' is returned.
.br ;.of 12
nextfound : None of the entries in the leaf have this key but
at least one entry has a higher key; the index of the entry
with the higher key is returned.
.br ;.of 12
lastfound : All entries in the leaf have keys smaller than rk;
'index' returns the index of the last of these entries.
.br ;.of 12
nonefound : There are no entries in the leaf.
.sp ;.in
Some possible acknowledgements in e:
   - e_ok
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_illegal_entrylength
.sp 2
bd31PrevSearch (rk,nptr,index,current,e)
.sp
This routine returns the index of the record entry preceeding
the entry identified by the leaf pointer nptr and by the index
'index'.  If this entry is located in the left neighbor leaf, the
pointer to this leaf is also supplied.  This requires that such a
predecessor exist.
.br
Some possible acknowledgements in e :
  - e_ok
  - b_no_prev_record
  - b_disk_not_accessible
.sp 2
b31next_search (nptr, index, current)
.sp
This routine returns the index of the record entry following the
entry identified by the leaf pointer nptr and by the index
'index'.  If this entry is located on the right neighbor leaf,
the pointer to this leaf is also supplied.  This requires that such
a successor exist.
.br
Some possible acknowledgements in current.curr_trans^.trError_gg00 :
  - e_ok
  - e_no_next_record
.sp 2
b31pfill_recordbuffer(nptr,test_key,tree_pos,set_result,b,
.br
                      current,e)
.sp
This routine returns record buffer b with a maximum of 'cnt'
record entries with keys that are lower than or the same as the
key of the entry identified by the leaf pointer nptr and by
the index 'index'.  If the left edge of the leaf is reached
before the limit condition has been fulfilled, the additional entries
are taken from a possible neighbor leaf on the left.  If the record
buffer is full or the left edge of the leaf has been reached,
b_buffer_limit is sent to e.
.br
Other possible acknowledgements in e:
  - e_ok
  - b_illegal_entrypos
  - b_invalid_entrypos
.sp 2
b31nfill_recordbuffer(nptr,test_key,tree_pos,set_result,b,
.br
                      current,e)
.sp
This routine returns record buffer b with a maximum of 'cnt'
record entries with keys that are higher than or the same as the key
of the entry identified by the leaf pointer nptr and by the index
'index'.  If the right edge of the leaf is reached before the
limit condition has been fulfilled, the additional entries are taken
from a possible neighbor leaf on the right.  If the record buffer is
full or the maximum number of entries 'count' has been reached,
b_buffer_limit is sent to e.
.br
Other possible acknowledgements in e:
  - e_ok
  - b_illegal_entrypos
  - b_invalid_entrypos
  - b_no_next_record
  - b_disk_not_accessible
.sp 2
A leafunderflow handling may be done.
.sp
.br;If bd_unbuffered IN current.curr_tree_id.bd_use each page that is
changed is written through to the secondary storage.
.br;Some possible acknowledgements in current.curr_trans^.trError_gg00:
   - e_ok
.sp 2
b31sort_entries(nptr)
.sp
In this routine, the record entries in the leaf indicated by the
pointer nptr are sorted according to the sequence determined by the
index 'pointer_list'.
.sp 2
b31pointer_list(nptr)
.sp
In this routine, the index 'pointer_list' in the leaf indicated
by the pointer nptr is restructured.  This requires that the
record entries be sorted in ascending order by record keys.
.CM *-END-* specification -------------------------------
.sp2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
 
Here the leaf_routines are refined insofar as their
effect remains limited to an individual leaf.
.sp
A record is left-justified when it is supplied to or stored in
the record buffer.
.sp ;.cp 5
Record buffer:
.sp
.nf
   +-------------------+---------   ...   ----+
   |     record        |           unused     |
   +-------------------+---------   ...   ----+
.fo
.sp 2;.cp 5
The record itself has the following structure:
.sp
.nf
   +----+----+-----------------+
   | el | kl |    fields       |
   +----+----+-----------------+
.fo
.sp
   el : record length including length field
.br
   kl : record key length excluding length field
.sp 2
When a new record entry is inserted or an old entry is replaced
with a new, longer entry, the case may arise that there is no longer
sufficient space available in the relevant leaf.  At this point,
the record entries of the leaf and of its neighbors are
redistributed to include the new entry (see bd33LeafOverflow).
.sp
Or, on the other hand, the case may arise that when a record entry
is deleted or when an old record entry is replaced by a new,
shorter entry, the leaf is then no longer sufficiently
filled.  As a rule, this is acceptable for the root of a tree
(so that even an empty root can remain!); however, if the leaf
has neighbors, an attempt is made to correct the underflow
by redistributing the record entries (see b34leafunderflow).
.sp
Each leaf has a pointer to its right neighbor, if there is such a
neighbor.  The pointers are also used for leaf reorganization
and release operations.
.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 = 'Leaf is not excl locked ';
      (* *)
      c_with_transinfo = true;
      (*inlineC #include "SAPDB/DataAccess/Data_RecordHeaderAccess.h"*)
 
 
(*------------------------------*) 
 
PROCEDURE
      b31add_to_leaf (VAR b : tgg00_Rec;
            VAR nptr    : tbd_node_ptrs;
            index       : integer;
            left        : tsp00_PageNo;
            VAR current : tbd_current_tree);
 
VAR
      dummyRef : tgg91_PageRef;
 
BEGIN
bd31AddToLeaf (b, nptr, index, left, current,
      NOT c_with_transinfo, dummyRef);
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd31AddToLeaf (
            VAR b         : tgg00_Rec;
            VAR nptr      : tbd_node_ptrs;
            index         : integer;
            left          : tsp00_PageNo;
            VAR current   : tbd_current_tree;
            useBeforeRef  : boolean;
            VAR beforeRef : tgg91_PageRef);
 
VAR
      target      : tsp00_Int2;
      recordLen   : tsp00_Int4;
      convVersion : tgg00_ConverterVersion;
      amount      : tsp00_Int4;
      source_pos  : tsp00_Int4;
      pRec        : tgg00_RecPtr;
 
BEGIN
WITH nptr, np_ptr^, current, curr_tree_id, curr_trans^ DO
    BEGIN
&   ifdef TRACE
    IF  NOT bd20IsPageExclusiveLocked (np_cbptr)
    THEN
        g01abort (csp3_bd_msg, csp3_n_btree, MSG_NOT_EXCL_LOCKED, nd_id);
&   endif
    (*ENDIF*) 
    recordLen   := b.recLen_gg00;
    convVersion := bd20GetDestinationConverterVersion (trTaskId_gg00, np_cbptr);
    IF  (nd_bottom + recordLen) > (MAX_BOTTOM_BD00 - ((nd_record_cnt+1)*POINTERSIZE_BD00))
    THEN
        BEGIN
        IF  NOT nd_sorted
        THEN
            b31sort_entries (np_ptr, curr_trans);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  ftsPerm_egg00 in fileType_gg00
            THEN
                bd33LeafOverflow (current, b, nptr, index, left)
            ELSE
                bd33TempLeafOverflow (current, b, nptr, index, left);
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        target    := nd_bottom;
        nd_bottom := nd_bottom + gg06Align (recordLen, REC_ALIGN_BD00);
        SAPDB_PascalMove ('VBD31 ',   1,    
              sizeof (b), sizeof (np_ptr^),
              @b, 1, @np_ptr^, target, recordLen, trError_gg00);
        (*  pointer list update *)
        IF  nd_record_cnt > 0
        THEN
            BEGIN
            amount := (nd_record_cnt - index) * POINTERSIZE_BD00;
            source_pos := MAX_BOTTOM_BD00 - ((nd_record_cnt)*POINTERSIZE_BD00);
            SAPDB_PascalOverlappingMove ('VBD31 ',   2,    
                  sizeof (np_ptr^), sizeof (np_ptr^),
                  @np_ptr^, source_pos,
                  @np_ptr^, source_pos-POINTERSIZE_BD00, amount, trError_gg00);
            END;
        (*ENDIF*) 
        IF  useBeforeRef AND NOT (ftsTemp_egg00 in fileType_gg00) AND (trError_gg00 = e_ok)
        THEN
            BEGIN
            pRec := @nd_body [target];
            bd999CreateTransHistoryInfo (curr_trans^, np_ptr^, pRec, beforeRef, 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, nd_id, np_ptr, 1)
            END
        ELSE
            BEGIN
            nd_pointer_list [MAX_POINTERINDEX_BD00 - index] := target;
            nd_record_cnt := nd_record_cnt + 1;
            nd_sorted     := false;
            b13w_release_node (nptr, current)
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        bd31_ModifyPageAndRecordCount (current, 1, convVersion)
    ELSE
        BEGIN
        IF  np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  ftsConcurrent_egg00 IN fileType_gg00
        THEN
            bd06CorruptedTreeHandling (curr_tree_id,
                  bd31x1TreeUpdateFailed_csp03, trError_gg00);
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd31AppendToLeaf (
            VAR b           : tgg00_Rec;
            VAR nptr        : tbd_node_ptrs;
            index           : integer;
            left            : tsp00_PageNo;
            VAR current     : tbd_current_tree;
            useBeforeRef    : boolean;
            VAR beforeRef   : tgg91_PageRef);
 
VAR
      target      : tsp00_Int2;
      recordLen   : tsp00_Int4;
      convVersion : tgg00_ConverterVersion;
      newLeafPage : tsp00_PageNo;
      pRec        : tgg00_RecPtr;
 
BEGIN
WITH nptr, np_ptr^, current, curr_tree_id, curr_trans^ DO
    BEGIN
&   ifdef TRACE
    IF  NOT bd20IsPageExclusiveLocked (np_cbptr)
    THEN
        g01abort (csp3_bd_msg, csp3_n_btree, MSG_NOT_EXCL_LOCKED, nd_id);
&   endif
    (*ENDIF*) 
    recordLen   := b.recLen_gg00;
    convVersion := bd20GetDestinationConverterVersion (trTaskId_gg00, np_cbptr);
    IF  ((nd_bottom + recordLen) > (MAX_BOTTOM_BD00 - ((nd_record_cnt+1)*POINTERSIZE_BD00)))
        OR
        ((nd_bottom >= NINETY_PERCENT_COV_BD00) AND (nd_right = NIL_PAGE_NO_GG00))
    THEN
        IF  nd_right = NIL_PAGE_NO_GG00
        THEN
            BEGIN
            IF  ftsPerm_egg00 in fileType_gg00
            THEN
                bd33AppendNewLeaf (current, b, nptr, index, newLeafPage)
            ELSE
                bd33AppendNewTempLeaf (current, b, nptr, index, newLeafPage);
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            IF  NOT nd_sorted
            THEN
                b31sort_entries (np_ptr, curr_trans);
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  ftsPerm_egg00 in fileType_gg00
                THEN
                    bd33LeafOverflow (current, b, nptr, index + 1, left)
                ELSE
                    bd33TempLeafOverflow (current, b, nptr, index + 1, left);
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
    ELSE
        BEGIN
        target    := nd_bottom;
        nd_bottom := nd_bottom + gg06Align (recordLen, REC_ALIGN_BD00);
        SAPDB_PascalMove ('VBD31 ',   3,    
              sizeof (b), sizeof (np_ptr^),
              @b, 1, @np_ptr^, target, recordLen, trError_gg00);
        IF  useBeforeRef AND NOT (ftsTemp_egg00 in fileType_gg00) AND (trError_gg00 = e_ok)
        THEN
            BEGIN
            pRec := @nd_body [target];
            bd999CreateTransHistoryInfo (curr_trans^, np_ptr^, pRec, beforeRef, 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,
                  nd_id, np_ptr, 1)
            END
        ELSE
            BEGIN
            nd_pointer_list [MAX_POINTERINDEX_BD00 - (index + 1)] := target;
            nd_record_cnt := nd_record_cnt + 1;
            nd_sorted     := false;
            b13w_release_node (nptr, current)
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        bd31_ModifyPageAndRecordCount (current, 1, convVersion)
    ELSE
        BEGIN
        IF  np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  ftsConcurrent_egg00 IN fileType_gg00
        THEN
            bd06CorruptedTreeHandling (curr_tree_id,
                  bd31x2TreeUpdateFailed_csp03, trError_gg00);
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b31del_from_leaf (VAR nptr : tbd_node_ptrs;
            index       : integer;
            left        : tsp00_PageNo;
            VAR current : tbd_current_tree);
 
VAR
      bUpdateLeftLinkage : boolean;
      pRec               : tgg00_RecPtr;
      convVersion        : tgg00_ConverterVersion;
      i                  : tsp00_Int4;
      source_pos         : tsp00_Int4;
      cnt                : tsp00_Int4;
      pos                : tsp00_Int4;
      DelSpaceLen        : tsp00_Int4;
      oldsep             : tgg00_Lkey;
 
BEGIN
WITH nptr, np_ptr^, current, curr_tree_id, curr_trans^ DO
    BEGIN
    bUpdateLeftLinkage := (ftsTemp_egg00 IN fileType_gg00) OR
          (eftsClustered_egg00 IN currExtendedFileTypeSet_bd00);
&   ifdef TRACE
    IF  NOT bd20IsPageExclusiveLocked (np_cbptr)
    THEN
        g01abort (csp3_bd_msg, csp3_n_btree, MSG_NOT_EXCL_LOCKED, nd_id);
&   endif
    (*ENDIF*) 
    convVersion := bd20GetDestinationConverterVersion (trTaskId_gg00, np_cbptr);
    IF  nd_record_cnt = 1
    THEN
        b35get_entrykey (np_ptr, FIRST_REC_INDEX_BD00, oldsep, curr_trans);
    (*ENDIF*) 
    pos         := nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
    pRec        := @nd_body [pos];
    DelSpaceLen := gg06Align (Data_GetRecLen(pRec), REC_ALIGN_BD00);
    b35del_space (np_ptr, pos, DelSpaceLen, curr_trans);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        FOR i := FIRST_REC_INDEX_BD00 TO nd_record_cnt - 1 DO
            IF  nd_pointer_list [MAX_POINTERINDEX_BD00 - i] > pos
            THEN
                nd_pointer_list [MAX_POINTERINDEX_BD00 - i] :=
                      nd_pointer_list [MAX_POINTERINDEX_BD00 - i] - DelSpaceLen;
            (*ENDIF*) 
        (*ENDFOR*) 
        IF  index < nd_record_cnt - 1
        THEN
            BEGIN
            cnt        := POINTERSIZE_BD00 * (nd_record_cnt - 1 - index);
            source_pos := MAX_BOTTOM_BD00 - ((nd_record_cnt)*POINTERSIZE_BD00);
            SAPDB_PascalOverlappingMove ('VBD31 ',   4,    
                  sizeof (np_ptr^), sizeof (np_ptr^),
                  @np_ptr^, source_pos,
                  @np_ptr^, source_pos + POINTERSIZE_BD00, cnt, trError_gg00);
            IF  trError_gg00 = e_move_error
            THEN
                BEGIN
                trError_gg00 := e_data_page_corrupted;
                b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1)
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        nd_record_cnt := nd_record_cnt - 1;
        IF  (nd_id <> fileRoot_gg00) AND (nd_bottom = BODY_BEG_BD00)
        THEN
            BEGIN
            IF  left <> NIL_PAGE_NO_GG00
            THEN
                b51divert_rightnext (left, nd_id, nd_right, current);
            (*ENDIF*) 
            IF  (bUpdateLeftLinkage) AND (nd_right <> NIL_PAGE_NO_GG00) AND (trError_gg00 = e_ok)
            THEN
                b51ldivert_leftnext (nd_right, left, current);
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  ftsPerm_egg00 in fileType_gg00
                THEN
                    bd31del_sep (oldsep, nd_level, current)
                ELSE
                    bd31tdel_sep (oldsep, nd_level, current);
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    b13free_node (nptr, current)
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            IF  ((nd_bottom - BODY_BEG_BD00 + ((nd_record_cnt)*POINTERSIZE_BD00)) < HALF_COVERING_BD00)
                AND (nd_id <> fileRoot_gg00)
                AND (NOT (ftsDynamic_egg00 IN fileType_gg00))
            THEN
                BEGIN
                IF  NOT nd_sorted
                THEN
                    b31sort_entries (np_ptr, curr_trans);
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    IF  ftsPerm_egg00 in fileType_gg00
                    THEN
                        bd34LeafUnderflow (current, nptr, left)
                    ELSE
                        bd34TempLeafUnderflow (current, nptr, left);
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            ELSE
                b13w_release_node (nptr, current)
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        bd31_ModifyPageAndRecordCount (current, -1, convVersion)
    ELSE
        BEGIN
        IF  np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  ftsConcurrent_egg00 IN fileType_gg00
        THEN
            bd06CorruptedTreeHandling (curr_tree_id,
                  bd31x3TreeUpdateFailed_csp03, trError_gg00);
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b31get_from_leaf (VAR nptr : tbd_node_ptrs;
            index        : integer;
            with_kb_lock : boolean;
            VAR b        : tgg00_Rec;
            VAR current  : tbd_current_tree);
 
VAR
      source : tsp00_Int4;
      pos    : tsp00_Int4;
      pRec   : tgg00_RecPtr;
 
BEGIN
WITH nptr, np_ptr^, current, curr_trans^ DO
    BEGIN
    source := nd_pointer_list[ MAX_POINTERINDEX_BD00 - index ];
    IF  (source < BODY_BEG_BD00) OR (source > nd_bottom)
    THEN
        BEGIN
        trError_gg00 := e_illegal_entrypos;
        b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1);
        g01opmsg (sp3p_knldiag, sp3m_error, csp03_b31_1_illegal_entrypos,
              csp3_n_btree, 'Illegal entry pos       ', source);
        b06write_filename_and_root (curr_tree_id)
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        pRec := @nd_body[source];
        pos  := 1;
        IF  pRec^.recVarcolOffset_gg00 < 0 (* PTS 1139184 *)
        THEN
            pRec := bd999UnpackRow (pRec^, b)
        ELSE
            SAPDB_PascalMove ('VBD31 ',   5,    
                  sizeof (np_ptr^), sizeof (b),
                  @np_ptr^, source, @b, 1, pRec^.recLen_gg00, trError_gg00);
        (*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, nd_id, np_ptr, 1);
            b06write_filename_and_root (curr_tree_id)
            END
        ELSE
            BEGIN
            IF  with_kb_lock
            THEN
                k53bd_share_lock (curr_trans^, curr_tree_id, b);
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    b13r_release_node (nptr, current, lru_normal);
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b31next_search (
            VAR nptr    : tbd_node_ptrs;
            VAR index   : integer;
            VAR current : tbd_current_tree;
            lruInfo     : tbd_lru_info );
 
VAR
      last          : boolean;
      nextLeafPage  : tsp00_PageNo;
      nextIndexPage : tsp00_PageNo;
 
BEGIN
WITH nptr, current, curr_trans^ DO
    BEGIN
    nextLeafPage := np_ptr^.nd_right;
    b35next_entry (np_ptr, index, last);
    IF  NOT last
    THEN
        trError_gg00 := e_ok
    ELSE
        IF  nextLeafPage = NIL_PAGE_NO_GG00
        THEN
            trError_gg00 := e_no_next_record
        ELSE
            BEGIN
            IF  (ftsPerm_egg00 IN curr_tree_id.fileType_gg00) AND
                (currRightBound_bd00 = np_ptr^.nd_id        ) AND (* subtree boundary reached *)
                (currIndexNptrs_bd00.np_ptr <> NIL          )
            THEN
                nextIndexPage := currIndexNptrs_bd00.np_ptr^.nd_right
            ELSE
                nextIndexPage := NIL_PAGE_NO_GG00;
            (*ENDIF*) 
            b13r_release_node (nptr, current, lruInfo);
            IF  nextIndexPage <> NIL_PAGE_NO_GG00
            THEN
                BEGIN
                bd30ReleaseSubTree (current);
                bd30GetSubTree (current, nextIndexPage)
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                bd13GetNode (current, nextLeafPage, plmLock_ebd00, nr_for_read, nptr);
                index := FIRST_REC_INDEX_BD00
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b31nfill_recordbuffer (
            VAR nptr         : tbd_node_ptrs;
            VAR test_key     : tgg00_Lkey;
            VAR tree_pos     : tgg00_FilePos;
            VAR set_result   : tgg00_BdSetResultRecord;
            VAR resultBuffer : tsp00_MoveObj;
            VAR current      : tbd_current_tree);
 
VAR
      searchResult : tsp00_LcompResult;
      pRec         : tgg00_RecPtr;
      source       : integer;
      fillPosition : integer;
 
BEGIN
WITH nptr, tree_pos, set_result, current, curr_trans^ DO
    BEGIN
    fillPosition     := 1;
    resultBuffer [1] := chr (0);
    resultBuffer [2] := chr (0);
    REPEAT
        WITH np_ptr^ DO
            BEGIN
            source := nd_pointer_list[ MAX_POINTERINDEX_BD00 - tpsIndex_gg00 ];
            IF  (source < BODY_BEG_BD00) OR (source > nd_bottom)
            THEN
                BEGIN
                trError_gg00 := e_illegal_entrypos;
                b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                      nd_id, np_ptr, 1);
                g01opmsg (sp3p_knldiag, sp3m_error, csp03_b31_3_illegal_entrypos,
                      csp3_n_btree, 'Illegal entry pos       ', source);
                b06write_filename_and_root (curr_tree_id)
                END
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            pRec := @np_ptr^.nd_body[source];
            IF  (fillPosition + Data_GetRecLen(pRec) - 1) > bd_max_fill_len
            THEN
                trError_gg00 := e_buffer_limit
            ELSE
                BEGIN
                searchResult := l_equal;
                IF  bd_key_check_len > 0
                THEN
                    s30cmp (test_key.k, 1, bd_key_check_len, np_ptr^,
                          source + cgg_rec_key_offset, bd_key_check_len, searchResult);
                (*ENDIF*) 
                IF  searchResult <> l_equal
                THEN
                    BEGIN
                    (* J.P. 19.12.96 Join optimization for inv_only *)
                    IF  fillPosition = 1
                    THEN
                        bd999CopyRecord (pRec, false, sizeof(resultBuffer),
                              @resultBuffer, fillPosition, trError_gg00);
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        trError_gg00 := e_no_next_record
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    bd_rec_cnt := bd_rec_cnt + 1;
                    bd999CopyRecord (pRec, false, sizeof(resultBuffer), @resultBuffer,
                          fillPosition, 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,
                              np_ptr^.nd_id, np_ptr, 1);
                        b06write_filename_and_root (curr_tree_id)
                        END
                    ELSE
                        BEGIN
                        bd_fill_len := fillPosition - 1;
                        IF  bd_rec_cnt < bd_max_rec_cnt
                        THEN
                            BEGIN
                            IF  tpsIndex_gg00 < np_ptr^.nd_record_cnt - 1
                            THEN
                                tpsIndex_gg00 := tpsIndex_gg00 + 1
                            ELSE
                                BEGIN (* go to next leaf, if possible *)
                                IF  np_ptr^.nd_right = NIL_PAGE_NO_GG00
                                THEN
                                    BEGIN
                                    (* do not set tpsPno_gg00 to NIL_PAGE_NO !!*)
                                    tpsIndex_gg00 := NIL_RECINDEX_BD00;
                                    END
                                ELSE
                                    BEGIN
                                    tpsPno_gg00 := np_ptr^.nd_right;
                                    b13r_release_node (nptr, current, lru_normal);
                                    bd13GetNode (current, tpsPno_gg00, plmLock_ebd00,
                                          nr_for_read, nptr);
                                    IF  trError_gg00 = e_ok
                                    THEN
                                        tpsIndex_gg00 := FIRST_REC_INDEX_BD00
                                    (*ENDIF*) 
                                    END
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
    UNTIL
        (tpsIndex_gg00 = NIL_RECINDEX_BD00) OR (bd_rec_cnt = bd_max_rec_cnt) OR (trError_gg00 <> e_ok);
    (*ENDREPEAT*) 
    IF  np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    IF  (trError_gg00 = e_no_next_record) AND (bd_rec_cnt > 0)
    THEN
        trError_gg00 := e_ok;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  (tpsIndex_gg00 = NIL_RECINDEX_BD00) AND (bd_rec_cnt = 0)
        THEN
            trError_gg00 := e_no_next_record
        (*ENDIF*) 
        END
    ELSE
        IF  (trError_gg00 <> e_no_next_record) AND (trError_gg00 <> e_buffer_limit)
        THEN
            tpsPno_gg00 := NIL_PAGE_NO_GG00
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b31pfill_recordbuffer (
            VAR nptr         : tbd_node_ptrs;
            VAR test_key     : tgg00_Lkey;
            VAR tree_pos     : tgg00_FilePos;
            VAR set_result   : tgg00_BdSetResultRecord;
            VAR resultBuffer : tsp00_MoveObj;
            VAR current      : tbd_current_tree);
 
VAR
      enough       : boolean;
      searchResult : tsp00_LcompResult;
      pRec         : tgg00_RecPtr;
      recIndex     : integer;
      source       : integer;
      fillPosition : integer;
 
BEGIN
WITH nptr, set_result, current, curr_trans^ DO
    BEGIN
    enough       := false;
    fillPosition := 1;
    recIndex     := tree_pos.tpsIndex_gg00;
    REPEAT
        WITH np_ptr^ DO
            BEGIN
            source := nd_pointer_list[ MAX_POINTERINDEX_BD00 - recIndex ];
            IF  (source < BODY_BEG_BD00) OR (source > nd_bottom)
            THEN
                BEGIN
                trError_gg00 := e_illegal_entrypos;
                b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                      nd_id, np_ptr, 1);
                g01opmsg (sp3p_knldiag, sp3m_error, csp03_b31_4_illegal_entrypos,
                      csp3_n_btree, 'Illegal entry pos       ', source);
                b06write_filename_and_root (curr_tree_id)
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                pRec := @nd_body[ source ];
                IF  (fillPosition + Data_GetRecLen(pRec) - 1) > bd_max_fill_len
                THEN
                    trError_gg00 := e_buffer_limit
                ELSE
                    BEGIN
                    searchResult := l_equal;
                    IF  bd_key_check_len > 0
                    THEN
                        s30cmp (test_key.k, 1, bd_key_check_len, np_ptr^,
                              source + cgg_rec_key_offset, bd_key_check_len,
                              searchResult);
                    (*ENDIF*) 
                    IF  searchResult <> l_equal
                    THEN
                        trError_gg00 := e_no_prev_record
                    ELSE
                        BEGIN
                        bd_rec_cnt := bd_rec_cnt + 1;
                        bd999CopyRecord (pRec, false, sizeof(resultBuffer), @resultBuffer,
                              fillPosition, 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,
                                  np_ptr^.nd_id, np_ptr, 1);
                            b06write_filename_and_root (curr_tree_id)
                            END
                        ELSE
                            BEGIN
                            bd_fill_len := bd_fill_len + Data_GetRecLen(pRec);
                            IF  bd_rec_cnt < bd_max_rec_cnt
                            THEN
                                b31t_prev_temp_search (nptr, recIndex, current)
                            ELSE
                                enough := true
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDWITH*) 
    UNTIL
        enough OR (trError_gg00 <> e_ok);
    (*ENDREPEAT*) 
    IF  np_ptr <> NIL
    THEN
        BEGIN
        tree_pos.tpsPno_gg00   := np_ptr^.nd_id;
        tree_pos.tpsIndex_gg00 := recIndex;
        b13r_release_node (nptr, current, lru_normal)
        END;
    (*ENDIF*) 
    IF  (trError_gg00 = e_no_prev_record) AND (bd_rec_cnt > 0)
    THEN
        BEGIN
        trError_gg00 := e_ok;
        IF  bd_rec_cnt <> 1 (* is not used for subsequent b07ctreplace with treePos *)
        THEN
            tree_pos.tpsIndex_gg00 := NIL_RECINDEX_BD00;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (trError_gg00 <> e_no_prev_record) AND
        (trError_gg00 <> e_buffer_limit)
    THEN
        tree_pos.tpsPno_gg00 := NIL_PAGE_NO_GG00
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b31pointer_list (VAR nptr : tbd_nodeptr);
 
VAR
      finish : boolean;
      pRec   : tgg00_RecPtr;
      index  : integer;
      epos   : integer;
 
BEGIN
WITH nptr^ DO
    BEGIN
    IF  BODY_BEG_BD00 < nd_bottom
    THEN
        BEGIN
        index  := FIRST_REC_INDEX_BD00;
        epos   := BODY_BEG_BD00;
        finish := false;
        REPEAT
            nd_pointer_list[ MAX_POINTERINDEX_BD00 - index ] := epos;
            pRec := @nd_body [epos];
            epos := epos + gg06Align (Data_GetRecLen(pRec), REC_ALIGN_BD00);
            IF  epos >= nd_bottom
            THEN
                finish := true
            ELSE
                index := index + 1
            (*ENDIF*) 
        UNTIL
            finish;
        (*ENDREPEAT*) 
        nd_record_cnt := index + 1
        END
    ELSE
        nd_record_cnt := 0;
    (*ENDIF*) 
    nd_sorted := true
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd31PrevSearch (
            VAR recKey        : tsp00_Key;
            keyLen            : tsp00_Int4;
            VAR pNodes        : tbd_node_ptrs;
            VAR recIndex      : integer;
            VAR prevLeafPage  : tsp00_PageNo;
            VAR current       : tbd_current_tree;
            bGetLeafForUpdate : boolean);
 
VAR
      bFound       : boolean;
      sepRecIndex  : tsp00_Int4;
      pSepNodes    : tbd_node_ptrs;
      sepNeighbour : tbd_neighbors;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    IF  recIndex > FIRST_REC_INDEX_BD00
    THEN
        recIndex := recIndex - 1
    ELSE
        IF  pNodes.np_ptr^.nd_id = fileRoot_gg00
        THEN
            trError_gg00 := e_no_prev_record
        ELSE
            BEGIN
            prevLeafPage       := NIL_PAGE_NO_GG00;
            pSepNodes.np_ptr   := NIL;
            pSepNodes.np_cbptr := NIL;
            (* *)
            b13r_release_node (pNodes, current, lru_normal);
            bd30ReleaseSubTree (current);
            IF  trError_gg00 = e_ok
            THEN
                bd50FindFirstLevelIndexNode (recKey, keyLen, pSepNodes, sepNeighbour, bFound, current);
            (*ENDIF*) 
            IF  (trError_gg00 = e_ok) AND (NOT bFound)
            THEN
                trError_gg00 := e_no_prev_record;
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                bd51SearchBranch (current, @recKey, keyLen, pSepNodes.np_ptr, sepRecIndex);
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  sepRecIndex > FIRST_REC_INDEX_BD00
                THEN
                    sepRecIndex := sepRecIndex - 1
                ELSE
                    BEGIN (* move to left index node on level one *)
                    IF  sepNeighbour.ln = NIL_PAGE_NO_GG00
                    THEN
                        trError_gg00 := e_no_prev_record
                    ELSE
                        BEGIN
                        IF  ftsPerm_egg00 IN fileType_gg00
                        THEN
                            BEGIN
                            (* pSepNodes is equal to currIndexNptrs_bd00 *)
                            bd30ReleaseSubTree (current);
                            bd30GetSubTree (current, sepNeighbour.ln);
                            IF  trError_gg00 = e_ok
                            THEN
                                pSepNodes := currIndexNptrs_bd00
                            (*ENDIF*) 
                            END
                        ELSE
                            BEGIN
                            (* for temp trees no currIndexNptrs_bd00 is available *)
                            b13r_release_node (pSepNodes, current, lru_normal);
                            bd13GetNode (current, sepNeighbour.ln, plmLock_ebd00, nr_for_read, pSepNodes)
                            END;
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            sepRecIndex := pSepNodes.np_ptr^.nd_record_cnt - 1
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                prevLeafPage := bd52SubtreePno (pSepNodes.np_ptr, sepRecIndex);
                IF  bGetLeafForUpdate
                THEN
                    bd13GetNode (current, prevLeafPage, plmLock_ebd00, nr_for_update, pNodes)
                ELSE
                    bd13GetNode (current, prevLeafPage, plmLock_ebd00, nr_for_read, pNodes);
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    recIndex := pNodes.np_ptr^.nd_record_cnt - 1
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  (ftsTemp_egg00 IN fileType_gg00) AND (pSepNodes.np_ptr <> NIL)
            THEN
                b13r_release_node (pSepNodes, current, lru_normal)
            (*ENDIF*) 
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b31repl_in_leaf (VAR b : tgg00_Rec;
            VAR nptr    : tbd_node_ptrs;
            index       : integer;
            left        : tsp00_PageNo;
            VAR current : tbd_current_tree);
 
VAR
      dummyRef    : tgg91_PageRef;
      dummyTrans  : tgg91_TransNo;
 
BEGIN
bd31ReplaceInLeaf (b, nptr, index, left, current, dummyRef, dummyTrans);
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd31ReplaceInLeaf (
            VAR b         : tgg00_Rec;
            VAR nptr      : tbd_node_ptrs;
            index         : integer;
            left          : tsp00_PageNo;
            VAR current   : tbd_current_tree;
            VAR beforeRef : tgg91_PageRef;
            VAR updTrans  : tgg91_TransNo);
 
VAR
      target      : tsp00_Int2;
      newlength   : tsp00_Int4;
      oldlength   : tsp00_Int4;
      cnt         : tsp00_Int4;
      i           : tsp00_Int4;
      diff        : tsp00_Int4;
      source_pos  : tsp00_Int4;
      DelSpaceLen : tsp00_Int4;
      convVersion : tgg00_ConverterVersion;
      pRec        : tgg00_RecPtr;
      recHead     : tgg00_HeaderRec;
 
BEGIN
WITH nptr, np_ptr^, current, curr_tree_id, curr_trans^  DO
    BEGIN
    trError_gg00 := e_ok;
&   ifdef TRACE
    IF  NOT bd20IsPageExclusiveLocked (np_cbptr)
    THEN
        g01abort (csp3_bd_msg, csp3_n_btree, MSG_NOT_EXCL_LOCKED, nd_id);
&   endif
    (*ENDIF*) 
    target       := nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
    pRec         := @nd_body [target];
    newlength    := b.len;
    oldlength    := Data_GetRecLen(pRec);
&   ifdef TRACE
    t01moveobj (bd, pRec^, 1, Data_GetRecLen(pRec));
    t01moveobj (bd, b, 1, b.len);
&   endif
    convVersion := bd20GetDestinationConverterVersion (trTaskId_gg00, np_cbptr);
    diff        := abs(gg06Align (oldlength, REC_ALIGN_BD00) - gg06Align (newlength, REC_ALIGN_BD00));
    recHead     := b.recHead_gg00;
    IF  NOT (ftsTemp_egg00 in fileType_gg00)
        AND (fileRoot_gg00 <> bd17GetBlobFdirRoot)
    THEN
        bd999UpdateTransHistoryInfo (trTaskId_gg00, pRec, @b, beforeRef, updTrans, trError_gg00);
    (*ENDIF*) 
    IF  oldlength = newlength
    THEN
        BEGIN
        SAPDB_PascalMove ('VBD31 ',   6,    
              sizeof (b), sizeof (np_ptr^),
              @b, 1, @np_ptr^, target, newlength, 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
            b13w_release_node (nptr, current)
        (*ENDIF*) 
        END
    ELSE
        IF  newlength < oldlength
        THEN
            BEGIN
            b35del_space (np_ptr, target, diff, curr_trans);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                SAPDB_PascalMove ('VBD31 ',   7,    
                      sizeof (b), sizeof (np_ptr^),
                      @b, 1, @np_ptr^, target, newlength, trError_gg00);
                IF  trError_gg00 = e_move_error
                THEN
                    BEGIN
                    trError_gg00 := e_data_page_corrupted;
                    b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1);
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                FOR i := FIRST_REC_INDEX_BD00 TO nd_record_cnt - 1 DO
                    BEGIN
                    IF  nd_pointer_list [MAX_POINTERINDEX_BD00 - i] > target
                    THEN
                        nd_pointer_list [MAX_POINTERINDEX_BD00 - i] :=
                              nd_pointer_list [MAX_POINTERINDEX_BD00 - i] - diff
                    (*ENDIF*) 
                    END;
                (*ENDFOR*) 
                IF  ((nd_bottom - BODY_BEG_BD00 + ((nd_record_cnt)*POINTERSIZE_BD00))
                    < HALF_COVERING_BD00)
                    AND (nd_id <> fileRoot_gg00)
                    AND (NOT (ftsDynamic_egg00 IN fileType_gg00))
                THEN
                    BEGIN
                    IF  NOT nd_sorted
                    THEN
                        b31sort_entries (np_ptr, curr_trans);
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        IF  ftsPerm_egg00 in fileType_gg00
                        THEN
                            bd34LeafUnderflow (current, nptr, left)
                        ELSE
                            bd34TempLeafUnderflow (current, nptr, left);
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                ELSE
                    b13w_release_node (nptr, current)
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        ELSE
            (* newlength > oldlength*)
            IF  (nd_bottom + diff) > (MAX_BOTTOM_BD00 - ((nd_record_cnt)*POINTERSIZE_BD00))
            THEN
                BEGIN
                DelSpaceLen := gg06Align(oldlength, REC_ALIGN_BD00);
                b35del_space (np_ptr, target, DelSpaceLen, curr_trans);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    FOR i := FIRST_REC_INDEX_BD00 TO nd_record_cnt - 1 DO
                        BEGIN
                        IF  nd_pointer_list [MAX_POINTERINDEX_BD00 - i] > target
                        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
                    THEN
                        BEGIN
                        cnt        := POINTERSIZE_BD00 * (nd_record_cnt - 1 - index);
                        source_pos := MAX_BOTTOM_BD00 - ((nd_record_cnt)*POINTERSIZE_BD00);
                        SAPDB_PascalOverlappingMove ('VBD31 ',   8,    
                              sizeof (np_ptr^), sizeof (np_ptr^),
                              @np_ptr^, source_pos,
                              @np_ptr^, source_pos+POINTERSIZE_BD00, cnt, trError_gg00);
                        IF  trError_gg00 = e_move_error
                        THEN
                            BEGIN
                            trError_gg00 := e_data_page_corrupted;
                            b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, np_ptr, 1);
                            END
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    nd_record_cnt := nd_record_cnt - 1
                    END;
                (*ENDIF*) 
                IF  NOT nd_sorted
                THEN
                    b31sort_entries (np_ptr, curr_trans);
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    IF  ftsPerm_egg00 in fileType_gg00
                    THEN
                        bd33LeafOverflow (current, b, nptr, index, left)
                    ELSE
                        bd33TempLeafOverflow (current, b, nptr, index, left);
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                b35add_space (np_ptr, target, diff, curr_trans);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    SAPDB_PascalMove ('VBD31 ',   9,    
                          sizeof (b), sizeof (np_ptr^),
                          @b, 1, @np_ptr^, target, newlength, 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
                        FOR i := FIRST_REC_INDEX_BD00 TO nd_record_cnt - 1 DO
                            BEGIN
                            IF  nd_pointer_list [MAX_POINTERINDEX_BD00 - i] > target
                            THEN
                                nd_pointer_list [MAX_POINTERINDEX_BD00 - i] :=
                                      nd_pointer_list [MAX_POINTERINDEX_BD00 - i] + diff
                            (*ENDIF*) 
                            END;
                        (*ENDFOR*) 
                        b13w_release_node (nptr, current)
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
    b.recHead_gg00 := recHead;
    IF  trError_gg00 = e_ok
    THEN
        bd31_ModifyPageAndRecordCount (current, 0, convVersion)
    ELSE
        BEGIN
        IF  np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  ftsConcurrent_egg00 IN fileType_gg00
        THEN
            bd06CorruptedTreeHandling (curr_tree_id,
                  bd31x4TreeUpdateFailed_csp03, trError_gg00);
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b31search_entry (VAR current : tbd_current_tree;
            VAR rk     : tsp00_Key;
            KeyLen     : tsp00_Int4;
            VAR nptr   : tbd_nodeptr;
            VAR index  : tsp00_Int4;
            VAR result : tbd_searchresult);
 
VAR
      searchResult : tsp00_LcompResult;
      pos      : tsp00_Int4;
      maxindex : tsp00_Int4;
      lwb      : tsp00_Int4;
      upb      : tsp00_Int4;
      lpos     : tsp00_Int4;
      count    : tsp00_Int4;
      recLen   : integer;
      pRec     : tgg00_RecPtr;
 
BEGIN
(* Offsets are aligned !*)
WITH current.curr_trans^, nptr^ DO
    BEGIN
    trError_gg00 := e_ok;
    (*  upb <= lwb *)
    upb          := nd_record_cnt - 1;
    lwb          := FIRST_REC_INDEX_BD00;
    maxindex     := upb;
    index        := FIRST_REC_INDEX_BD00;
    result       := nonefound;
    IF  nd_record_cnt <> 0
    THEN
        BEGIN
        REPEAT
            count := upb - lwb + 1;
            IF  count > 2
            THEN
                BEGIN
                lpos := upb - (count DIV 2);
                pos  := nd_pointer_list [ MAX_POINTERINDEX_BD00 - lpos ];
                IF  (pos < BODY_BEG_BD00) OR (pos > nd_bottom)
                THEN
                    trError_gg00 := e_illegal_entrypos;
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    pRec   := @nd_body [pos];
                    recLen := Data_GetRecLen (pRec);
                    IF  (recLen > MAX_RECLEN_GG00 ) OR
                        (recLen < MIN_RECORD_LEN_BD00)
                    THEN
                        trError_gg00 := e_illegal_entrylength
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    s30cmp1 (rk, 1, KeyLen, pRec^.recBody_gg00, 1,
                          Data_GetKeyLen(pRec), searchResult);
                    IF  searchResult = l_equal
                    THEN
                        BEGIN
                        index := lpos;
                        result := thisfound
                        END
                    ELSE
                        IF  searchResult = l_less
                        THEN
                            upb := lpos
                        ELSE
                            lwb := lpos
                        (*ENDIF*) 
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            ELSE
                IF  count = 2
                THEN
                    BEGIN
                    lpos := upb;
                    pos  := nd_pointer_list[ MAX_POINTERINDEX_BD00 - lpos ];
                    IF  (pos < BODY_BEG_BD00) OR (pos > nd_bottom)
                    THEN
                        trError_gg00 := e_illegal_entrypos;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        pRec := @nd_body [pos];
                        recLen := Data_GetRecLen (pRec);
                        IF  (Data_GetRecLen(pRec) > MAX_RECLEN_GG00 ) OR
                            (Data_GetRecLen(pRec) < MIN_RECORD_LEN_BD00)
                        THEN
                            trError_gg00 := e_illegal_entrylength
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        s30cmp1 (rk, 1, KeyLen, pRec^.recBody_gg00, 1,
                              Data_GetKeyLen(pRec), searchResult);
                        IF  searchResult = l_equal
                        THEN
                            BEGIN
                            index  := lpos;
                            result := thisfound
                            END
                        ELSE
                            IF  searchResult = l_less
                            THEN
                                upb := lwb
                            ELSE
                                lwb := upb
                            (*ENDIF*) 
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                ELSE (*  count = 1 *)
                    BEGIN
                    lpos := upb;
                    pos  := nd_pointer_list[ MAX_POINTERINDEX_BD00 - lpos ];
                    IF  (pos < BODY_BEG_BD00) OR (pos > nd_bottom)
                    THEN
                        trError_gg00 := e_illegal_entrypos;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        pRec := @nd_body [pos];
                        IF  (Data_GetRecLen(pRec) > MAX_RECLEN_GG00 ) OR
                            (Data_GetRecLen(pRec) < MIN_RECORD_LEN_BD00)
                        THEN
                            trError_gg00 := e_illegal_entrylength
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        s30cmp1 (rk, 1, KeyLen, pRec^.recBody_gg00, 1,
                              Data_GetKeyLen(pRec), searchResult);
                        IF  searchResult = l_equal
                        THEN
                            BEGIN
                            index  := lpos;
                            result := thisfound
                            END
                        ELSE
                            IF  searchResult = l_less
                            THEN
                                BEGIN
                                index  := lpos;
                                result := nextfound
                                END
                            ELSE
                                BEGIN
                                IF  lpos = maxindex
                                THEN
                                    BEGIN
                                    index  := lpos;
                                    result := lastfound
                                    END
                                ELSE
                                    BEGIN
                                    index  := lpos + 1;
                                    result := nextfound
                                    END
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
            (*ENDIF*) 
        UNTIL
            (result <> nonefound) OR (trError_gg00 <> e_ok);
        (*ENDREPEAT*) 
        IF  trError_gg00 <> e_ok
        THEN
            BEGIN
            IF  trError_gg00 = e_illegal_entrypos
            THEN
                BEGIN
                b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, nptr, 1);
                g01opmsg (sp3p_knldiag, sp3m_error, csp03_b31_5_illegal_entrypos,
                      csp3_n_btree, 'Illegal entry pos       ', pos);
                b06write_filename_and_root (current.curr_tree_id)
                END
            ELSE
                IF  trError_gg00 = e_illegal_entrylength
                THEN
                    BEGIN
                    b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, nd_id, nptr, 1);
                    g01opmsg (sp3p_knldiag, sp3m_error, bd31IllegalEntryLength_csp03,
                          csp3_n_btree, 'Illegal rec len for pos ', pos);
                    b06write_filename_and_root (current.curr_tree_id)
                    END
                (*ENDIF*) 
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b31sort_entries (VAR nptr : tbd_nodeptr;
            t : tgg00_TransContextPtr);
 
VAR
      finish  : boolean;
      pRec    : tgg00_RecPtr;
      index   : integer;
      n_epos  : integer;
      nn_epos : integer;
      nn      : tbd_node;
 
BEGIN
IF  t^.trError_gg00 <> e_data_page_corrupted
THEN
    IF  NOT (nptr^.nd_sorted) AND (BODY_BEG_BD00 < nptr^.nd_bottom)
    THEN
        BEGIN
        nn     := nptr^;
        index  := FIRST_REC_INDEX_BD00;
        n_epos := BODY_BEG_BD00;
        finish := false;
        REPEAT
            nn_epos := nn.nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
            pRec    := @nn.nd_body [nn_epos];
            SAPDB_PascalMove ('VBD31 ',  10,    
                  sizeof (nn), sizeof (nptr^),
                  @nn, nn_epos, @nptr^, n_epos, Data_GetRecLen(pRec), t^.trError_gg00);
            IF  t^.trError_gg00 = e_move_error
            THEN
                BEGIN
                finish := true;
                t^.trError_gg00 := e_data_page_corrupted;
                b06dump_bad_page (t^.trTaskId_gg00, 'd', FILE_EXT_COR_BD00,
                      nn.nd_id, @nn, 1);
                END;
            (*ENDIF*) 
            nptr^.nd_pointer_list[ MAX_POINTERINDEX_BD00 - index ] := n_epos;
            n_epos := n_epos + gg06Align (Data_GetRecLen(pRec), REC_ALIGN_BD00);
            IF  n_epos >= nptr^.nd_bottom
            THEN
                finish := true
            ELSE
                index := index + 1
            (*ENDIF*) 
        UNTIL
            finish;
        (*ENDREPEAT*) 
        nptr^.nd_sorted := true
        END
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b31t_append_to_temp_leaf (
            VAR b        : tgg00_Rec;
            VAR nptr     : tbd_node_ptrs;
            VAR tree_pos : tgg00_FilePos;
            VAR current  : tbd_current_tree);
 
VAR
      target      : tsp00_Int2;
      convVersion : tgg00_ConverterVersion;
      newLeafPage : tsp00_PageNo;
 
BEGIN
WITH nptr, np_ptr^, b, tree_pos, current, curr_tree_id, curr_trans^ DO
    BEGIN
&   ifdef TRACE
    IF  NOT bd20IsPageExclusiveLocked (np_cbptr)
    THEN
        g01abort (csp3_bd_msg, csp3_n_btree, MSG_NOT_EXCL_LOCKED, nd_id);
&   endif
    (*ENDIF*) 
    convVersion := bd20GetDestinationConverterVersion (trTaskId_gg00, np_cbptr);
    IF  (nd_bottom + recLen_gg00) > (MAX_BOTTOM_BD00 - ((nd_record_cnt+1)*POINTERSIZE_BD00))
    THEN
        BEGIN
        BEGIN
        IF  ftsPerm_egg00 in fileType_gg00
        THEN
            bd33AppendNewLeaf (current, b, nptr, tree_pos.tpsIndex_gg00, newLeafPage)
        ELSE
            bd33AppendNewTempLeaf (current, b, nptr, tree_pos.tpsIndex_gg00, newLeafPage);
        (*ENDIF*) 
        END;
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            tree_pos.tpsPno_gg00   := newLeafPage;
            tree_pos.tpsIndex_gg00 := 0
            END
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        tpsIndex_gg00 := tpsIndex_gg00 + 1;
        target        := nd_bottom;
        nd_bottom     := nd_bottom + gg06Align (recLen_gg00, REC_ALIGN_BD00);
        SAPDB_PascalMove ('VBD31 ',  11,    
              sizeof (b), sizeof (np_ptr^),
              @b, 1, @np_ptr^, target, 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, nd_id, np_ptr, 1);
            b06write_filename_and_root (curr_tree_id)
            END
        ELSE
            BEGIN
            nd_pointer_list [MAX_POINTERINDEX_BD00 - tpsIndex_gg00] := target;
            nd_record_cnt := nd_record_cnt + 1;
            nd_sorted     := true;
            b13w_release_node (nptr, current)
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        bd31_ModifyPageAndRecordCount (current, 1, convVersion)
    ELSE
        IF  np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal)
        (*ENDIF*) 
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b31t_prev_temp_search (VAR nptr : tbd_node_ptrs;
            VAR index   : integer;
            VAR current : tbd_current_tree);
 
VAR
      prevLeafPage : tsp00_PageNo;
 
BEGIN
WITH nptr, current, curr_trans^ DO
    BEGIN
    prevLeafPage  := np_ptr^.nd_left;
    IF  NOT (index = FIRST_REC_INDEX_BD00)
    THEN
        index := index - 1
    ELSE
        IF  prevLeafPage = NIL_PAGE_NO_GG00
        THEN
            trError_gg00 := e_no_prev_record
        ELSE
            BEGIN
            b13r_release_node (nptr, current, lru_normal);
            bd13GetNode (current, prevLeafPage, plmLock_ebd00, nr_for_read, nptr);
            IF  trError_gg00 = e_ok
            THEN
                index := np_ptr^.nd_record_cnt - 1
            (*ENDIF*) 
            END
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b31w_next_search (
            VAR nptr    : tbd_node_ptrs;
            VAR index   : integer;
            VAR current : tbd_current_tree);
 
VAR
      bLastRecordOnPage : boolean;
      nextLeafPage      : tsp00_PageNo;
      nextIndexPage     : tsp00_PageNo;
 
BEGIN
WITH nptr, current, curr_trans^ DO
    BEGIN
    nextLeafPage := np_ptr^.nd_right;
    b35next_entry (np_ptr, index, bLastRecordOnPage);
    IF  NOT bLastRecordOnPage
    THEN
        trError_gg00 := e_ok
    ELSE
        IF  nextLeafPage = NIL_PAGE_NO_GG00
        THEN
            trError_gg00 := e_no_next_record
        ELSE
            BEGIN
            IF  (ftsPerm_egg00 IN curr_tree_id.fileType_gg00) AND
                (currRightBound_bd00 = np_ptr^.nd_id        ) AND (* subtree boundary reached *)
                (currIndexNptrs_bd00.np_ptr <> NIL          )
            THEN
                nextIndexPage := currIndexNptrs_bd00.np_ptr^.nd_right
            ELSE
                nextIndexPage := NIL_PAGE_NO_GG00;
            (*ENDIF*) 
            b13w_release_node (nptr, current);
            IF  nextIndexPage <> NIL_PAGE_NO_GG00
            THEN
                BEGIN
                bd30ReleaseSubTree (current);
                bd30GetSubTree (current, nextIndexPage)
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                bd13GetNode (current, nextLeafPage, plmLock_ebd00, nr_for_update, nptr);
                index := FIRST_REC_INDEX_BD00
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd31del_sep (VAR sep : tgg00_Lkey;
            level          : tsp00_Int2;
            VAR current    : tbd_current_tree);
 
VAR
      indexorderlist : tbd00_OrderList;
 
BEGIN
current.curr_lvl_1_pno        := NIL_PAGE_NO_GG00;
indexorderlist.olstCount_bd00 := 0;
b54del_index (@sep.keyVal_gg00, sep.keyLen_gg00, level, indexorderlist);
b54execute_indexorder (indexorderlist, current);
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd31tdel_sep (VAR sep : tgg00_Lkey;
            level          : tsp00_Int2;
            VAR current    : tbd_current_tree);
 
VAR
      pIndexOrderList : tsp00_Addr;
 
BEGIN
current.curr_lvl_1_pno := NIL_PAGE_NO_GG00;
pIndexOrderList        := NIL;
bd999CreateIndexOrderList (current.curr_trans^, pIndexOrderList);
IF  current.curr_trans^.trError_gg00 = e_ok
THEN
    BEGIN
    IF  NOT b54tdel_index (@sep.keyVal_gg00, sep.keyLen_gg00, level,
        pIndexOrderList)
    THEN
        current.curr_trans^.trError_gg00 := e_no_more_memory;
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  current.curr_trans^.trError_gg00 = e_ok
THEN
    b54texecute_indexorder (pIndexOrderList, current);
(*ENDIF*) 
bd999DestroyIndexOrderList (current.curr_trans^, pIndexOrderList);
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd31_ModifyPageAndRecordCount(
            VAR current   : tbd_current_tree;
            recCountDelta : tsp00_Int4;
            convVersion   : tgg00_ConverterVersion);
 
BEGIN
WITH current, curr_trans^, curr_tree_id DO
    BEGIN
    bd998ModifyPageAndRecordCount (curr_trans^, convVersion, fileTabId_gg00,
          currLeafPageCountDelta_bd00, currIndexPageCountDelta_bd00, recCountDelta);
    (* *)
    IF  (trError_gg00 <> e_ok               ) AND
        (ftsPerm_egg00 IN fileType_gg00     ) AND
        (fileRoot_gg00 = bd17GetBlobFdirRoot)
    THEN
        trError_gg00 := e_ok;
    (*ENDIF*) 
    currLeafPageCountDelta_bd00  := 0;
    currIndexPageCountDelta_bd00 := 0;
    END
(*ENDWITH*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
