.bm 8
.fm 4
.bt $Copyright by SAP AG, 2003$$Page %$
.tm 12
.hm 6
.hs 3
.tt 1 $SQL$Project Distributed Database System$VBD30$
.tt 2 $$$
.tt 3 $JuergenP$treehandling$$$$2000-10-04$
***********************************************************
.nf
 
 
    ========== licence begin  GPL
    Copyright (C) 2000 SAP AG
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end
 
.fo
.nf
.sp
Module  : treehandling
=========
.sp
Purpose : - general tree operations
          - tree operations managing primary data
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        PROCEDURE
              b30add_to_tree (VAR rk : tgg00_Lkey;
                    VAR b           : tgg00_Rec;
                    page_fill_limit : integer;
                    VAR current     : tbd_current_tree);
 
        PROCEDURE
              b30add_filestate (VAR current : tbd_current_tree;
                    new_filestate : tbd_file_state_set);
 
        PROCEDURE
              b30append_to_tree (VAR rk : tgg00_Lkey;
                    VAR b        : tgg00_Rec;
                    VAR tree_pos : tgg00_FilePos;
                    VAR current  : tbd_current_tree);
 
        PROCEDURE
              b30bad_file (VAR current : tbd_current_tree;
                    incl_root_upd : boolean;
                    use_lock      : boolean;
                    new_state     : tbd_file_state_set);
 
        PROCEDURE
              b30check_tree (
                    VAR current          : tbd_current_tree;
                    long_col_cnt         : tsp00_Int2;
                    new_long_col_cnt     : tsp00_Int2;
                    check_long_existence : boolean);
 
        PROCEDURE
              b30cget_result_leaf (VAR rk : tgg00_Lkey;
                    get_next        : boolean;
                    prepare_for_upd : boolean;
                    VAR tree_pos    : tgg00_FilePos;
                    VAR nptr        : tbd_node_ptrs;
                    VAR current     : tbd_current_tree);
 
        PROCEDURE
              b30cnext_from_tree (VAR rk : tgg00_Lkey;
                    VAR set_result : tgg00_BdSetResultRecord;
                    VAR tree_pos   : tgg00_FilePos;
                    VAR b          : tsp00_MoveObj;
                    VAR current    : tbd_current_tree);
 
        PROCEDURE
              b30col_next_stringcol (VAR rk : tgg00_Lkey;
                    string_col_cnt    : integer;
                    VAR string_col_no : integer;
                    VAR col_id        : tgg00_FileId;
                    VAR tree_pos      : tgg00_FilePos;
                    VAR current       : tbd_current_tree);
 
        PROCEDURE
              b30cprev_from_tree (VAR rk : tgg00_Lkey;
                    VAR set_result : tgg00_BdSetResultRecord;
                    VAR tree_pos   : tgg00_FilePos;
                    VAR b          : tsp00_MoveObj;
                    VAR current    : tbd_current_tree);
 
        PROCEDURE
              b30current (VAR t : tgg00_TransContext;
                    VAR file_id : tgg00_FileId;
                    m_type      : tgg00_MessType;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b30database_verify (VAR t : tgg00_TransContext;
                    VAR bad_index_cnt : tsp00_Int4;
                    VAR total_bad_cnt : tsp00_Int4;
                    VAR verify_error  : tgg00_BasisError;
                    bWithUpdate       : boolean;
                    bWithIndexes      : boolean;
                    max_server        : integer);
 
        PROCEDURE
              b30del_from_tree (VAR rk : tgg00_Lkey;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b30exists_rec (VAR rk  : tgg00_Lkey;
                    VAR current      : tbd_current_tree);
 
        PROCEDURE
              b30fdir_to_treeid (VAR fi : tbd_fileinfo;
                    VAR file_id : tgg00_FileId);
 
        PROCEDURE
              b30find_leaf (VAR key : tgg00_Lkey;
                    VAR current     : tbd_current_tree);
 
        PROCEDURE
              b30get_from_tree (VAR rk : tgg00_Lkey;
                    VAR b       : tgg00_Rec;
                    VAR current : tbd_current_tree;
                    wanted_mode : tgg00_LockReqMode);
 
        PROCEDURE
              b30init_load (VAR rightmost_leaf : tsp00_PageNo;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b30load_table (VAR lnptr : tbd_node_ptrs;
                    VAR nptr           : tbd_node_ptrs;
                    only_left          : boolean;
                    VAR current        : tbd_current_tree);
 
        PROCEDURE
              b30new_tree (VAR fi : tbd_fileinfo;
                    VAR current   : tbd_current_tree);
 
        PROCEDURE
              b30next_from_tree (VAR rk : tgg00_Lkey;
                    inclusive    : boolean;
                    VAR tree_pos : tgg00_FilePos;
                    VAR b        : tgg00_Rec;
                    VAR current  : tbd_current_tree);
 
        PROCEDURE
              b30prev_from_tree (VAR rk : tgg00_Lkey;
                    inclusive    : boolean;
                    VAR tree_pos : tgg00_FilePos;
                    VAR b        : tgg00_Rec;
                    VAR current  : tbd_current_tree);
 
        PROCEDURE
              b30range_exi_rec (
                    VAR rk_the_one   : tgg00_Lkey;
                    VAR rk_another   : tgg00_Lkey;
                    VAR left___pages : tsp00_Int4;
                    VAR middle_pages : tsp00_Int4;
                    VAR right__pages : tsp00_Int4;
                    VAR current      : tbd_current_tree);
 
        PROCEDURE
              b30release_tree (VAR current : tbd_current_tree;
                    stringcol_cnt  : integer;
                    varcol_cnt_off : integer;
                    only_empty     : boolean);
 
        PROCEDURE
              b30repl_in_tree (VAR rk : tgg00_Lkey;
                    VAR b       : tgg00_Rec;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b30reset_bad_file (VAR current : tbd_current_tree;
                    incl_root_upd : boolean;
                    sub_state     : tbd_file_state_set);
 
        PROCEDURE
              b30save_quick (VAR pno : tsp00_PageNo;
                    VAR nptr    : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b30search_record (
                    VAR RecKey             : tsp00_Key (* ptocSynonym tsp00_KeyPtr *);
                    RecKeyLen              : tsp00_Int4;
                    lock_type              : tbd_treelock;
                    node_req               : tbd_node_request;
                    VAR left_estimation    : tsp00_Int4;
                    VAR rightestimation    : tsp00_Int4;
                    VAR nptr               : tbd_node_ptrs;
                    VAR index              : integer;
                    VAR neighbs            : tbd_neighbors;
                    VAR result             : tbd_searchresult;
                    VAR current            : tbd_current_tree);
 
        PROCEDURE
              b30set_fileversion (VAR current : tbd_current_tree;
                    new_fileversion : tgg91_FileVersion);
 
        PROCEDURE
              b30set_read_only (VAR current : tbd_current_tree);
 
        PROCEDURE
              b30treeleafnodes (VAR current : tbd_current_tree;
                    node_req          : tbd_node_request;
                    VAR old_leafnodes : tsp00_Int4);
 
        PROCEDURE
              b30sub_filestate (VAR current : tbd_current_tree;
                    filestate : tbd_file_state_set);
 
        PROCEDURE
              b30tadd_temp_primary (
                    bCountDuplicates : boolean;
                    VAR Rec          : tgg00_Rec;
                    VAR current      : tbd_current_tree);
 
        PROCEDURE
              b30verify_tree (VAR current : tbd_current_tree;
                    conv_update      : boolean;
                    VAR NumPages     : tsp00_Int4);
 
        PROCEDURE
              bd30AddToTree (
                    VAR recKey  : tgg00_Lkey;
                    VAR rec     : tgg00_Rec;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30CreateBeforeImageForDelete (
                    VAR m          : tgg00_MessBlock;
                    pDeleteCmd     : tsp00_Addr;
                    VAR rk         : tgg00_Lkey;
                    VAR old_recbuf : tgg00_Rec;
                    granted_lock   : tgg00_LockReqMode;
                    VAR current    : tbd_current_tree);
 
        PROCEDURE
              bd30CreateBeforeImageForInsert (
                    VAR rk              : tgg00_Lkey;
                    VAR b               : tgg00_Rec;
                    VAR m               : tgg00_MessBlock;
                    pInsertCmd          : tsp00_Addr;
                    granted_lock        : tgg00_LockReqMode;
                    VAR current         : tbd_current_tree);
 
        PROCEDURE
              bd30CreateBeforeImageForUpdate (
                    VAR m              : tgg00_MessBlock;
                    pUpdateCmd         : tsp00_Addr;
                    VAR rk             : tgg00_Lkey;
                    VAR old_recbuf     : tgg00_Rec;
                    VAR new_recbuf     : tgg00_Rec;
                    granted_lock       : tgg00_LockReqMode;
                    VAR current        : tbd_current_tree);
 
        PROCEDURE
              bd30CreateCoordinator (VAR t : tgg00_TransContext;
                    VAR FileId : tgg00_FileId;
                    MessType   : tgg00_MessType);
 
        PROCEDURE
              bd30GetTree (
                    VAR trans      : tgg00_TransContext;
                    VAR fileId     : tgg00_FileId;
                    VAR current    : tbd_current_tree;
                    bTreeExclusive : boolean;
                    messType       : tgg00_MessType);
 
        PROCEDURE
              bd30ReleaseTree (
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30OmsReadAheadCoordinator (VAR t : tgg00_TransContext;
                    ReadAheadServer : integer);
              (* ptocExport hbd30_1.h *)
 
        PROCEDURE
              bd30ObjFileCoordinator (VAR t : tgg00_TransContext;
                    mtype           : tgg_message_type;    (* PTS 1113635 FF *)
                    NumRepairServer : integer);
 
        PROCEDURE
              b30cinit_current (VAR t : tgg00_TransContext;
                    VAR current : tbd_current_tree);
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
        FROM
              filesysteminterface_1 : VBD01;
 
        VAR
              b01downfilesystem : boolean;
              b01niltree_id     : tgg00_FileId;
              b01fullkey        : tsp00_Key;
 
        PROCEDURE
              b01pverify_participant (VAR t : tgg00_TransContext;
                    VAR file_id : tgg00_FileId;
                    is_cold     : boolean);
 
        PROCEDURE
              bd01SetToNilCurrent(
                    VAR current : tbd_current_tree );
 
      ------------------------------ 
 
        FROM
              filesysteminterface_4 : VBD04;
 
        PROCEDURE
              bd04OmsReadAheadParticipant (VAR t : tgg00_TransContext;
                    VAR FileId : tgg00_FileId);
 
      ------------------------------ 
 
        FROM
              error_text_handling : VBD06;
 
        PROCEDURE
              b06file_opmsg (
                    msg_no      : tsp00_Int4;
                    VAR current : tbd_current_tree);
 
        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
              bd06IllegalRootAccess (
                    VAR trans  : tgg00_TransContext;
                    VAR fileId : tgg00_FileId);
 
      ------------------------------ 
 
        FROM
              Trace : VBD120;
 
        PROCEDURE
              b120InsertTrace (VAR t   : tgg00_TransContext;
                    trace_layer  : tgg00_Debug;
                    trace_object : tgg00_VtraceType;
                    body_len     : tsp00_Int2;
                    trace_body   : tgg11_VtraceBodyPtr);
 
      ------------------------------ 
 
        FROM
              nodehandling : VBD13;
 
        PROCEDURE
              bd13GetNode (VAR Current : tbd_current_tree;
                    Pno          : tsp00_PageNo;
                    PageLockMode : tbd00_PageLockMode;
                    NodeReq      : tbd_node_request;
                    VAR Nptrs    : tbd_node_ptrs);
 
        PROCEDURE
              b13init_default_data_page (
                    VAR Trans   : tgg00_TransContext;
                    VAR FileId  : tgg00_FileId;
                    Level       : tsp00_Int2;
                    NewPno      : tsp00_PageNo;
                    VAR Nptrs   : tbd_node_ptrs);
 
        PROCEDURE
              b13new_root (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b13pfree_pno (pno : tsp00_PageNo;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b13r_release_node (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree;
                    lru_info    : tbd_lru_info);
 
        PROCEDURE
              b13w_release_node (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              filedirectory : VBD17;
 
        VAR
              b17permfdir_current   : tbd_current_tree;
              b17strcolfdir_current : tbd_current_tree;
 
        PROCEDURE
              b17fadd_file_state (VAR current : tbd_current_tree;
                    new_state : tbd_file_state_set);
 
        PROCEDURE
              b17fsub_file_state (VAR current : tbd_current_tree;
                    sub_state : tbd_file_state_set);
 
        PROCEDURE
              b17get_fdir (VAR fn   : tgg00_Filename;
                    VAR fi          : tbd_fileinfo;
                    concurrent_file : boolean;
                    VAR t           : tgg00_TransContext);
 
        PROCEDURE
              b17state_fdir (VAR fn : tgg00_Filename;
                    VAR fi          : tbd_fileinfo;
                    concurrent_file : boolean;
                    VAR t           : tgg00_TransContext);
 
        PROCEDURE
              b17succ_fdir (VAR fn  : tgg00_Filename;
                    VAR next_fn     : tgg00_Filename;
                    VAR fi          : tbd_fileinfo;
                    shared_file     : boolean;
                    VAR t           : tgg00_TransContext;
                    include_strcols : boolean);
 
        FUNCTION
              bd17GetFdirRoot : tsp00_PageNo;
 
        FUNCTION
              bd17GetLongFdirRoot : tsp00_PageNo;
 
      ------------------------------ 
 
        FROM
              systembufferinterface : VBD20;
 
        FUNCTION
              bd20IsPageLocked (
                    pCBlock : tbd_nodeptr) : boolean;
 
      ------------------------------ 
 
        FROM
              leafhandling : VBD31;
 
        PROCEDURE
              b31add_to_leaf (VAR b : tgg00_Rec;
                    VAR nptr    : tbd_node_ptrs;
                    index       : integer;
                    left        : tsp00_PageNo;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b31append_to_leaf (VAR b : tgg00_Rec;
                    VAR nptr           : tbd_node_ptrs;
                    index              : integer;
                    page_fill_limit    : integer;
                    left               : tsp00_PageNo;
                    VAR current        : tbd_current_tree);
 
        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
              b31get_key_from_leaf (VAR nptr : tbd_node_ptrs;
                    index        : integer;
                    VAR reckey   : tgg00_Lkey;
                    VAR current  : tbd_current_tree);
 
        PROCEDURE
              b31next_search (release_frame : boolean;
                    VAR nptr    : tbd_node_ptrs;
                    VAR index   : integer;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b31nfill_recordbuffer (VAR nptr : tbd_node_ptrs;
                    VAR test_key   : tgg00_Lkey;
                    VAR tree_pos   : tgg00_FilePos;
                    VAR set_result : tgg00_BdSetResultRecord;
                    VAR b          : 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 b          : tsp00_MoveObj;
                    VAR current    : tbd_current_tree);
 
        PROCEDURE
              b31prev_search (VAR reckey : tsp00_Key;
                    KeyLen        : tsp00_Int4;
                    VAR nptr      : tbd_node_ptrs;
                    VAR index     : integer;
                    VAR prev_leaf : tsp00_PageNo;
                    VAR current   : tbd_current_tree);
 
        PROCEDURE
              b31repl_in_leaf (VAR b : tgg00_Rec;
                    VAR nptr    : tbd_node_ptrs;
                    index       : integer;
                    left        : tsp00_PageNo;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b31search_entry (VAR current : tbd_current_tree;
                    VAR rk     : tsp00_Key;
                    KeyLen     : tsp00_Int4;
                    VAR nptr   : tbd_nodeptr;
                    VAR index  : tsp00_Int4;
                    VAR result : tbd_searchresult);
 
        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);
 
      ------------------------------ 
 
        FROM
              indexhandling : VBD50;
 
        PROCEDURE
              b50check_subtree (
                    root                 : tsp00_PageNo;
                    right                : tsp00_PageNo;
                    long_col_cnt         : tsp00_Int2;
                    new_long_col_cnt     : tsp00_Int2;
                    VAR dump_page        : boolean;
                    VAR bad_long         : boolean;
                    VAR current          : tbd_current_tree;
                    check_long_existence : boolean);
 
        PROCEDURE
              b50find_leaf (
                    VAR sepkey          : tsp00_Key;
                    KeyLen              : tsp00_Int4;
                    lock_type           : tbd_treelock;
                    node_req            : tbd_node_request;
                    VAR subtree_info    : tbd_subtree_info;
                    VAR left_estimation : tsp00_Int4;
                    VAR rightestimation : tsp00_Int4;
                    VAR index_pno       : tsp00_PageNo;
                    VAR nptr            : tbd_node_ptrs;
                    VAR neighbs         : tbd_neighbors;
                    VAR current         : tbd_current_tree);
 
        PROCEDURE
              b50first_leaf (VAR firstleaf : tsp00_PageNo;
                    lock_type              : tbd_treelock;
                    VAR single             : boolean;
                    VAR current            : tbd_current_tree);
 
        PROCEDURE
              b50release_subtree (root : tsp00_PageNo;
                    stringcol_cnt  : integer;
                    varcol_cnt_off : integer;
                    only_empty     : boolean;
                    VAR current    : tbd_current_tree);
 
        PROCEDURE
              b50verify_subtree (root : tsp00_PageNo;
                    right         : tsp00_PageNo;
                    conv_update   : boolean;
                    VAR dump_page : boolean;
                    VAR current   : tbd_current_tree;
                    VAR NumPages  : tsp00_Int4);
 
        PROCEDURE
              bd50DetermineLeafNode (
                    VAR current  : tbd_current_tree;
                    pSepKey      : tsp00_KeyAddr;
                    keyLen       : tsp00_Int4;
                    nptr         : tbd_nodeptr;
                    VAR recIndex : tsp00_Int4;
                    VAR leaf     : tsp00_PageNo);
 
        PROCEDURE
              bd50FindLeaf (
                    VAR sepKey  : tsp00_Key;
                    keyLen      : tsp00_Int4;
                    VAR nptrs   : tbd_node_ptrs;
                    VAR neighbs : tbd_neighbors;
                    VAR current : tbd_current_tree);
 
        FUNCTION
              bd50IndexNodeIsSaveForInsert (
                    VAR current : tbd_current_tree;
                    recIndex    : tsp00_Int4) : boolean;
 
      ------------------------------ 
 
        FROM
              indexing : VBD53;
 
        PROCEDURE
              bd53NewLeafIndex (VAR Nptr : tbd_nodeptr;
                    VAR Nnptr        : tbd_nodeptr;
                    VAR NewSeparator : tgg00_Lkey;
                    t                : tgg00_TransContextPtr);
 
      ------------------------------ 
 
        FROM
              indexupdateorders : VBD54;
 
        PROCEDURE
              b54add_index (pSep       : tsp00_KeyAddr;
                    SepLen             : tsp00_Int4;
                    n_id               : tsp00_PageNo;
                    n_level            : tsp00_Int2;
                    VAR indexorderlist : tbd00_OrderList);
 
        PROCEDURE
              b54execute_indexorder (
                    VAR indexorderlist : tbd00_OrderList;
                    VAR current        : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              ref_statistic : VBD73;
 
        PROCEDURE
              b73cmd_count (statement_kind : tgg00_RefInfoIndex);
 
      ------------------------------ 
 
        FROM
              concurrency : VBD75;
 
        PROCEDURE
              b75ilread_lock_index (VAR current : tbd_current_tree;
                    indexnode      : tsp00_PageNo;
                    suspend_reason : tsp00_Int2);
 
        PROCEDURE
              b75llread_lock_leaf (VAR current : tbd_current_tree;
                    leaf           : tsp00_PageNo;
                    suspend_reason : tsp00_Int2);
 
        PROCEDURE
              b75ilwrite_lock_index (VAR current : tbd_current_tree;
                    leaf            : tsp00_PageNo;
                    indexnode       : tsp00_PageNo;
                    VAR lock_return : tbd_lock_returncode;
                    suspend_reason  : tsp00_Int2);
 
        PROCEDURE
              b75iuread_unlock_index (VAR current : tbd_current_tree;
                    indexnode : tsp00_PageNo);
 
        PROCEDURE
              b75iuwrite_unlock_index (VAR current : tbd_current_tree;
                    indexnode : tsp00_PageNo);
 
        PROCEDURE
              b75luread_unlock_leaf (VAR current : tbd_current_tree;
                    leaf : tsp00_PageNo);
 
        PROCEDURE
              b75luwrite_unlock_leaf (VAR current : tbd_current_tree;
                    leaf : tsp00_PageNo);
 
        PROCEDURE
              b75reset_lock (VAR current : tbd_current_tree;
                    leaf : tsp00_PageNo);
 
        PROCEDURE
              b75tldelete_lock_tree (VAR current : tbd_current_tree;
                    ignore_svp     : boolean;
                    suspend_reason : tsp00_Int2);
 
        PROCEDURE
              b75tlread_lock_tree (VAR current : tbd_current_tree;
                    suspend_reason : tsp00_Int2);
 
        PROCEDURE
              b75tlwrite_lock_tree (VAR current : tbd_current_tree;
                    leaf            : tsp00_PageNo;
                    VAR lock_return : tbd_lock_returncode;
                    suspend_reason  : tsp00_Int2);
 
        PROCEDURE
              b75tlselect_lock_tree (VAR current : tbd_current_tree;
                    suspend_reason : tsp00_Int2);
 
        PROCEDURE
              b75tudelete_unlock_tree (VAR current : tbd_current_tree);
 
        PROCEDURE
              b75turead_unlock_tree (VAR current : tbd_current_tree);
 
        PROCEDURE
              b75tuselect_unlock_tree (VAR current : tbd_current_tree);
 
        PROCEDURE
              b75tuwrite_unlock_tree (VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              InvHandling : VBD300;
 
        PROCEDURE
              bd300FileIdRootCheck (VAR FileId  : tgg00_FileId;
                    VAR TrError : tgg00_BasisError);
 
        PROCEDURE
              bd300SetRootCheck (VAR FileId  : tgg00_FileId);
 
      ------------------------------ 
 
        FROM
              RTE_kernel : VEN101;
 
        PROCEDURE
              vmessage (prio     : tsp3_priority;
                    msg_type     : tsp3_msg_type;
                    msg_no       : tsp_int4;
                    msg_label    : tsp_c8;
                    VAR msg_line : tsp_c40);
 
        PROCEDURE
              vsleep (pid : tsp_process_id;
                    limit : tsp_int2);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01glob          : tgg_kernel_globals;
              g01restart_local : boolean;
              g01vtrace        : tgg_vtrace_state;
 
        PROCEDURE
              g01abort (msg_no : tsp_int4;
                    msg_label : tsp_c8;
                    msg_text  : tsp_c24;
                    bad_value : tsp_int4);
 
        PROCEDURE
              g01mblock_init (VAR source_trans : tgg00_TransContext;
                    mess_type  : tgg_message_type;
                    mess2_type : tgg_message2_type;
                    VAR mblock : tgg_mess_block);
 
        PROCEDURE
              g01opmsg (msg_prio : tsp3_priority;
                    msg_type  : tsp3_msg_type;
                    msg_no    : tsp_int4;
                    msg_label : tsp_c8;
                    msg_text  : tsp_c24;
                    msg_value : tsp_int4);
 
        PROCEDURE
              g01optextmsg (msg_prio : tsp3_priority;
                    msg_type  : tsp3_msg_type;
                    msg_no    : tsp_int4;
                    msg_label : tsp_c8;
                    msg_text  : tsp_c40);
 
      ------------------------------ 
 
        FROM
              Select_Help_Procedures : VGG04;
 
        FUNCTION
              g04inv_tfn (tfn : tgg00_Tfn) : boolean;
 
        PROCEDURE
              g04locate_col (VAR st : tgg_stack_entry;
                    rec_buf        : tgg00_RecPtr;
                    VAR varcol_pos : tgg_varcol_pos_list;
                    VAR col_pos    : integer;
                    VAR col_len    : integer);
 
      ------------------------------ 
 
        FROM
              GG_cpp_auxiliary_functions : VGG06;
 
        FUNCTION
              gg06TransGetInt4 (VAR TransNo : tgg91_TransNo): tsp00_Int4;
 
        FUNCTION
              gg06Min (
                    value1 : tsp00_Int4;
                    value2 : tsp00_Int4 ) : tsp00_Int4;
 
        FUNCTION
              gg06PnoGet (VAR Cint4 : tgg90_Cint4): tsp00_Int4;
 
        PROCEDURE
              gg06PnoPut (VAR Cint4 : tgg90_Cint4; int4 : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG10;
 
        PROCEDURE
              g10fil  (mod_id      : tsp_c6;
                    mod_intern_num : tsp_int4;
                    source_upb     : tsp_int4;
                    VAR source     : tgg00_RecBody;
                    source_pos     : tsp_int4;
                    length         : tsp_int4;
                    fill_char      : char;
                    VAR e          : tgg_basis_error);
 
        PROCEDURE
              g10mv1  (mod_id      : tsp_c6;
                    mod_intern_num : tsp_int4;
                    source_upb     : tsp_int4;       destin_upb : tsp_int4;
                    VAR source     : tbd_node;       source_pos : tsp_int4;
                    VAR destin     : tgg00_Filename; destin_pos : tsp_int4;
                    length         : tsp_int4;
                    VAR e          : tgg_basis_error);
 
        PROCEDURE
              g10mv2  (mod_id      : tsp_c6;
                    mod_intern_num : tsp_int4;
                    source_upb     : tsp_int4;    destin_upb : tsp_int4;
                    VAR source     : tbd_node;    source_pos : tsp_int4;
                    VAR destin     : tgg00_Rec;   destin_pos : tsp_int4;
                    length         : tsp_int4;
                    VAR e          : tgg_basis_error);
 
        PROCEDURE
              g10mv3  (mod_id      : tsp_c6;
                    mod_intern_num : tsp_int4;
                    source_upb     : tsp_int4;   destin_upb : tsp_int4;
                    VAR source     : tbd_node;   source_pos : tsp_int4;
                    VAR destin     : tsp00_Key;  destin_pos : tsp_int4;
                    length         : tsp_int4;
                    VAR e          : tgg_basis_error);
 
        PROCEDURE
              g10mv4  (mod_id      : tsp_c6;
                    mod_intern_num : tsp_int4;
                    source_upb     : tsp_int4;        destin_upb : tsp_int4;
                    VAR source     : tsp00_Key;       source_pos : tsp_int4;
                    VAR destin     : tgg00_VtraceKey; destin_pos : tsp_int4;
                    length         : tsp_int4;
                    VAR e          : tgg_basis_error);
 
      ------------------------------ 
 
        FROM
              GG_edit_routines : VGG17;
 
        PROCEDURE
              g17hexto_line (c : char;
                    VAR ln_len : integer;
                    VAR ln     : tsp00_C40);
 
        PROCEDURE
              g17nameto_line (n : tsp00_Name;
                    VAR ln_len  : integer;
                    VAR ln      : tsp00_C40);
 
        PROCEDURE
              g17trimint4_to_line (int : tsp00_Int4;
                    VAR ln_len : integer;
                    VAR ln     : tsp_c40);
 
      ------------------------------ 
 
        FROM
              KB_transaction : VKB53;
 
        PROCEDURE
              k53child_trans_build (MessType : tgg00_MessType;
                    TransCnt       : tsp00_Int4;
                    VAR ChildTrans : tgg00_TransChild);
 
      ------------------------------ 
 
        FROM
              KB_ins_del_upd : VKB61;
 
        PROCEDURE
              k61bd_del (VAR m     : tgg00_MessBlock;
                    pDeleteCmd     : tsp00_Addr;
                    VAR old_recbuf : tgg00_Rec;
                    granted_lock   : tgg00_LockReqMode);
 
        PROCEDURE
              k61bd_ins (VAR m   : tgg00_MessBlock;
                    pInsertCmd   : tsp00_Addr;
                    VAR b        : tgg00_Rec;
                    granted_lock : tgg00_LockReqMode);
 
      ------------------------------ 
 
        FROM
              KB_update : VKB63;
 
        PROCEDURE
              k63bd_upd (VAR m     : tgg00_MessBlock;
                    pUpdateCmd     : tsp00_Addr;
                    VAR old_recbuf : tgg00_Rec;
                    VAR new_recbuf : tgg00_Rec;
                    granted_lock   : tgg00_LockReqMode);
 
      ------------------------------ 
 
        FROM
              KB_sender_receiver : VKB90;
 
        PROCEDURE
              k90rcv_child (VAR mblock : tgg00_MessBlock;
                    VAR child_trans    : tgg00_TransChild);
 
        PROCEDURE
              k90send (VAR mblock    : tgg00_MessBlock;
                    VAR remote_trans : tgg00_TransChild);
 
      ------------------------------ 
 
        FROM
              RTE-Extension-30 : VSP30;
 
        PROCEDURE
              s30cmp (VAR buf1   : tsp_moveobj;
                    fieldpos1    : tsp_int4;
                    fieldlength1 : tsp_int4;
                    VAR buf2     : tsp00_Buf;
                    fieldpos2    : tsp_int4;
                    fieldlength2 : tsp_int4;
                    VAR l_result : tsp_lcomp_result);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01basis_error (layer : tgg00_Debug;
                    nam   : tsp00_Sname;
                    b_err : tgg00_BasisError);
 
        PROCEDURE
              t01buf (debug  : tgg00_Debug;
                    VAR buf  : tgg00_Rec;
                    startpos : integer;
                    endpos   : integer);
 
        PROCEDURE
              t01int4 (debug : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int4     : tsp00_Int4);
 
        PROCEDURE
              t01page (debug : tgg00_Debug;
                    VAR buf  : tbd_node;
                    startpos : tsp00_Int4;
                    endpos   : tsp00_Int4);
 
        PROCEDURE
              t01p2int4 (debug : tgg00_Debug;
                    nam_1 : tsp00_Sname;
                    int_1 : tsp00_Int4;
                    nam_2 : tsp00_Sname;
                    int_2 : tsp00_Int4);
 
        PROCEDURE
              t01key (
                    debug   : tgg00_Debug;
                    nam     : tsp00_Sname;
                    VAR k   : tgg00_Lkey);
&       endif
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
        PROCEDURE
              b06dump_bad_page;
 
              tbd_univ_ptr tbd_nodeptr
 
        FUNCTION
              bd20IsPageLocked;
 
              tbd02_pDataCBlock tbd_nodeptr
 
        PROCEDURE
              g17hexto_line;
 
              tsp00_Line tsp00_C40
 
        PROCEDURE
              g17nameto_line;
 
              tsp00_Line tsp00_C40
 
        PROCEDURE
              g17trimint4_to_line;
 
              tsp00_Line tsp_c40
 
        PROCEDURE
              g10fil;
 
              tsp_moveobj tgg00_RecBody
 
        PROCEDURE
              g10mv1;
 
              tsp_moveobj tbd_node
              tsp_moveobj tgg00_Filename
 
        PROCEDURE
              g10mv2;
 
              tsp_moveobj tbd_node
              tsp_moveobj tgg00_Rec
 
        PROCEDURE
              g10mv3;
 
              tsp_moveobj tbd_node
              tsp_moveobj tsp00_Key
 
        PROCEDURE
              g10mv4;
 
              tsp_moveobj tsp00_Key
              tsp_moveobj tgg00_VtraceKey
 
        PROCEDURE
              s30cmp;
 
              tsp_moveobj tsp00_Buf
 
        PROCEDURE
              t01buf;
 
              tsp00_Buf tgg00_Rec
 
        PROCEDURE
              t01page;
 
              tsp00_Page tbd_node
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : JuergenP
.sp
.cp 3
Created : 1979-11-09
.sp
.cp 3
.sp
.cp 3
Release :      Date : 2000-10-04
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
 
Every (nonempty) file of the base file system is managed via
a B* tree.  B* trees are special storage and access structures
for the index sequential organization of dynamically changeable
files.  They feature
.sp ;.of 2
- rapid access during optional and sequential processing,
.sp ;.in ;.of 2
- efficient utilization of the secondary storage area and
.sp ;.in ;.of 2
- dynamic reorganization of the storage and access structure.
.sp ;.in
For the file management system described here, a B* tree variant is
used that is specially suited to managing files with the
following characteristics:
.sp
.of 2
- the length of file entries and entry keys can vary within
very wide margins
.sp ;.in ;.of 2
- the files change frequently (insertion, replacement and
deletion of records).
.sp 2;.cp 4
.in
In an indexed sequential file that is organized via a B* tree, the
data entries and the index are accomodated in blocks of a fixed
length, called pages or page frames.  The pages form the units that
are transferred between the main memory and the secondary storage.
At the same time, these units form the nodes of a tree structure.
The way in which this tree is dynamically structured and reorganized
is successively described in a series of modules, with each
module solving individual problem aspects.
The following is intended merely to provide a terminological framework
for the specification of the routines concerned.
.sp 2
A
.oc _/1;B* tree
B is a finite set whose elements are called
.oc _/1;nodes.
It is either empty (
.oc _/1;empty_tree
) or it contains a designated node W, known as the
.oc _/1;root,
and the remaining nodes (B(W)) are subdivided into
g(W) >= 0
.oc _/1;subtrees;
each subtree is itself a B* tree.
Under certain circumstances, the entire B* tree can also be referred
to as a subtree.  The subtrees can be graphically depicted as branches
from the root; g(W) is therefore called the
.oc _/1;branching_degree
of the node W.
The nodes of a B* tree have a variable branching degree!
.sp
A root is referred to as a
.oc _/1;parent_node
with relation to the roots of its subtrees and, inversely, the
subtree nodes are the
.oc _/1;offspring_nodes
of the parent node.
The offspring nodes of a root are always ordered;
nodes that directly follow one another are called
.oc _/1;neighbor nodes,
as are the last and first offspring of two adjacent
parent nodes.
In this case, the preceeding node in the sequence
(or last offspring node) is the
.oc _/1;left_neighbor_node
and the suceeding node (or first offspring node) is the
.oc _/1;right_neighbor_node.
.sp
A node is a
.oc _/1;leaf
if it has a branching degree of zero; otherwise it is a
.oc _/1;branch_node.
B* trees are characterized by the fact that each node that is
neighbor to a leaf is also a leaf.
This means that each node can be assigned a
.oc _/1;level_number
according to the following principle:
neighbor nodes have the same level number,
parent nodes have a level number that is one greater
than that of their offspring nodes and all leaves have the same
level number of zero.
.sp
Since each node is implemented via a page in the secondary
storage (see pagestore), the nodes are unambiguously identified by
.oc _/1;page_numbers
and B* trees are identified by the page numbers of their roots.
Unless otherwise indicated, the routines always process the
.oc _/1;current_B*_tree,
as determined by the last call of the routine b30adjust_tree
since the last system startup (or since system generation).
.sp 3;.cp 7
   b30new_tree(fi,current,e)
.sp
This routine generates a new B* tree for a file with
file information fi.
The new B* tree consists only of a root, whose page number
is entered in fi.root.
'current' contains additional information on the tree.
Some possible acknowledgements in e:
   - e_ok
   - b_no_more_space
   - b_disk_not_accessible
.sp 2;.cp 7
   b30adjust_tree (fi,t,current)
.sp
The file with file information fi becomes the current
B* tree.  File-specific information is made available in 'current'
by calling b30adjust_tree.
.sp 2;.cp 7
   b30release_tree(current,stringcol_cnt,only_empty,e)
.sp
This routine re-releases all pages being used by the current
B* tree (current contains the necessary information).
.br
However, if 'only_empty' is assigned, the root of the tree is not
released but instead is re-initialized.
In this way, the contents of a file can be deleted without
the file having to be removed from the database.
.br
Otherwise ('only_empty' = FALSE), in order to ensure that no other
process with an invalid tree_id can access this tree, the root,
before it is released, is written to the secondary storage with a
deleted treeroot entry in the header. The parameter stringcol_cnt
contains the number of string fields in the RECORD representation
that belongs to this tree.  The B* trees that are referred to in
these fields are also deleted.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
.sp 2;.cp 7
   b30verify_tree (current,e)
.sp
The tree identified by 'current' is verified, i.e. the entire tree
is traversed and every node in the tree is labelled as used
in the previously deleted free storage manager.  In this manner,
pages that do not belong to any tree but were labelled as used
are again released.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
.sp 2;.cp 7
   current
.sp
The following is some of the information on the current B* tree
that is held in this variable:
.sp ;.of 2
- the page number 'root' of the root of the tree,
.br ;.in ;.of 2
- the file type ft that manages the tree,
(see filesysteminterface)
.br ;.in ;.of 2
- the buffer type bt, depending on whether a temporary file, the
system file or another permanent file is involved (see
systembufferinterface).
.sp 2;.cp 7
   indexorderlist
.sp
In this list, information is managed for a possible index
update or an index reorganization.
(see VBD54, indexupdateorders !).
.sp ;.in
.sp 3;.cp 6
.oc _/1
Operations_Involving_Trees_that_Manage_Primary_Files
.sp 2
Primary file entries are records with unambiguous record keys.
The way in which records and keys are transferred to a record or
key buffer is described in bufferhandling.
.sp 2;.cp 4
   b30add_filestate (current, new_filestate)
.sp
.sp 2;.cp 4
   b30add_to_tree (rk, b, page_fill_limit, current)
.sp
Inserts in the current B* tree the record contained in the record
buffer b with the key rk, if no record with this key is already
present and if enough space is available. If a page is written to the secondary
storage during a tree operation, all log pages whose page numbers
are lower than or the same as that of the current log page are also
written to the secondary storage, making the change restart-capable.
In addition, the current log information must be entered in the
data cache when the page to be changed is allocated so that,
if this page is ever displaced from the data cache, the writing
of the log pages with lower or identical page numbers to the
secondary storage can be initiated.
.br
The set bd_use_info indicates whether act_logpos must be used
- bd_valid_logpos - and whether the pages are written through to
the secondary storage unbuffered - bd_unbuffered -.  In the case
of a temporary file, this set is always empty.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_duplicate_key
   - b_no_more_space
   - b_no_more_temp_space
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
.sp 2;.cp 4
   b30append_to_tree (rk, b, tree_pos, current)
.sp 2;.cp 4
   b30cnext_from_tree(rk,set_result,tree_pos,b,current,e)
.sp
Copies cnt records from the current B* tree that follow the record
with key rk (with the records arranged in ascending order by
keys).  If no record with a key greater than rk is contained in
the tree, 'b_no_next_record' is sent to e and cnt is set to
zero.  Otherwise, as many (complete) records are transferred
to buffer b as it can receive or they are transferred for as long as
records with greater keys are still present.  When it has been
determined that no other record is present, b_no_next_record
is sent to e.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_buffer_limit
   - b_no_next_record
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
.sp 2;.cp 4
  b30cprev_from_tree (rk, set_result, tree_pos, b, current)
.sp
Copies cnt records from the current B* tree that preceed the record
with key rk (with the records arranged in descending order by
keys).  If no record with a key smaller than rk is contained in
the tree, 'b_no_prev_record' is sent to e and cnt is set to
zero.  Otherwise, as many (complete) records are transferred
to buffer b as it can receive or they are transferred for as long as
records with smaller keys are still present.  When it has been
determined that no other record is present, b_no_prev_record
is sent to e.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_buffer_limitn
   - b_no_prev_record
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accesible
.sp 2;.cp 4
   b30del_from_tree (rk, current)
.sp
Deletes the record with the key rk from the current B* tree,
if such a record is present.
.br
Some possible acknowledgements in current.curr_trans^.trError_gg00:
   - e_key_not_found
and acknowledgements from:
   + b13get_node,
   + b13release_node,
   + b30search_record,
   + b31del_from_leaf
   + b31search_entry
   + b75luwrite_unlock_leaf
   + b75tlwrite_lock_tree
   + b75tuwrite_unlock_tree
like
   - e_ok
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
.sp 2;.cp 4
   b30exists_rec(rk,current)
.sp
Carries out a search for a record with the key rk in
the current B* tree.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_key_not_found
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
????????????????????????
   - e_no_next_record
   - e_no_prev_record
   - b_file_not_found
.sp 2;.cp 4
   b30fdir_to_treeid (fi, file_id)
.sp 2;.cp 4
   b30get_from_tree (rk, b, current, wanted_mode)
.sp
Copies the record with the key rk, if such a record is present,
from the current B* tree to the record buffer b.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_key_not_found
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
.sp 2;.cp 4
  b30init_load (rightmost_leaf, current)
.sp 2;.cp 4
  bd30CreateBeforeImageForDelete
       (m, rk, old_recbuf, granted_lock, current)
 
.sp 2;.cp 4
  bd30CreateBeforeImageForInsert
        (rk, b, m, granted_lock, page_fill_limit, current)
.sp
.sp 2;.cp 4
  bd30CreateBeforeImageForUpdate (m, rk, old_recbuf, new_recbuf,
        granted_lock, current)
.sp
.sp 2;.cp 4
  b30load_table (lnptr, nptr, tbd_node_ptrs, only_left,
        sep, indexorderlist, tbd_order_list current)
.sp
.sp 2;.cp 4
  b30new_tree (fi, current);
.sp
.sp 2;.cp 4
   b30next_from_tree (rk, inclusive, tree_pos, b, current)
.sp
If the parameter is set to 'inclusive' and the record
with record key rk is found, this record is copied to record buffer b.
.br
Otherwise, the record that follows the record with key rk (with
the records arranged in ascending order by keys) is copied to b.
If no record with a key greater than rk is contained in the tree,
b_no_next_record is sent to e.  If the record with key rk is not
present, b_key_not_found is sent to e but the record is retrieved
that would have followed rk if it had been present.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_key_not_found
   - b_no_next_record
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
.sp 2;.cp 4
  b30prev_from_tree(rk,inclusive,tree_pos,b,current,e)
.sp
If the parameter is set to 'inclusive' and the record
with the record key rk is found, this record is copied to the
record buffer b.
.br
Otherwise, the record that preceeds the record with key rk (with
the records arranged in descending order by keys) is copied to b.
If no record with a key smaller than rk is contained in the tree,
b_no_prev_record is sent to e.  If the record with key rk is not
present, b_key_not_found is sent to e but the record is retrieved
that would have preceeded rk if it had been present.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_key_not_found
   - b_no_prev_record
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accesible
.sp 3;.cp 7
   b30range_exi_rec (rk_the_one, rk_another, left___pages, middle_pages,
            right__pages, current)
.sp
Carries out a search in the current B* tree satisfying the following
procedure condition:
.nf
    In the B* tree exists a record with key rk      AND
   ((      rk_the_one <= rk <  rk_another      ) OR
    (      rk_the_one <  rk <= rk_another      ) OR
    (rk >= rk_the_one    >=    rk_another      ) OR
    (      rk_the_one    >=    rk_another >= rk)   )
.br;.fo
If rk_the_one < rk <= rk_another, rk_the_one is overwritten with the
first key rk.
.br;.cp 20
The current implementation works correct for three cases:
.sp;.nf
1.  @(rk_the_one)= @(rk_another)
  The above procedure condition is equivalent to
    In the B* tree exists a record with key rk      AND
           rk_the_one  = rk
                                  condition true  -> e_ok
                                  condition false -> e_key_not_found
  Parameters left___pages, right__pages, rsp., yield estimations for the
  numbers of pages with key < rk_the_one, rk_the_one < key, rsp.
  Parameter middle-pages is neither used nor set.
  The sum, left___pages + right__pages + 1, is an
  estimation for all leaf pages of the tree.
 
2. (@(rk_the_one)<>@(rk_another)) AND
   (rk_the_one.len     = 0                  ) AND
   (rk_another.len     = MAX_KEYLEN_GG00     ) AND
   (rk_another.k       = b01fullkey         )
  The above procedure condition is equivalent to
    In the B* tree exists a record with key rk      AND
           rk_the_one <= rk
                                  condition true  -> e_ok
                                  condition false -> e_no_next_record
  Parameters left___pages, right__pages, rsp., yield estimations for the
  numbers of pages with key < rk_the_one, rk_the_one < key, rsp.
  Parameter middle-pages is neither used nor set.
  The sum, left___pages + right__pages + 1, is an
  estimation for all leaf pages of the tree.
 
3. (@(rk_the_one)<>@(rk_another)  ) AND
   ((rk_the_one.len    <> 0               ) OR
    (rk_another.len    <> MAX_KEYLEN_GG00  ) OR
    (rk_another.k      <> b01fullkey      )   ) AND
   ( rk_the_one        >  rk_another          )
  The above procedure condition is equivalent to
    In the B* tree exists a record with key rk      AND
   ((rk >= rk_the_one    >     rk_another      ) OR
    (      rk_the_one    >     rk_another >= rk)   )
                                  condition true  -> e_ok
                                  condition false -> e_no_prev_record
  Parameters left___pages, middle_pages, right__pages, rsp., yield
  estimations for the numbers of pages with key < rk_the_one,
  rk_the_one < key < rk_the_other, rk_the_other < key, rsp.
  The sum, left___pages + middle_pages + right__pages + 1, is an
  estimation for all leaf pages of the tree.
.sp;.fo;.cp 10
The current implementation does not work correct for one case:
.sp;.nf
4. (@(rk_the_one)<>@(rk_another)  ) AND
   ((rk_the_one.len    <> 0               ) OR
    (rk_another.len    <> MAX_KEYLEN_GG00  ) OR
    (rk_another.k      <> b01fullkey      )   ) AND
   ( rk_the_one        <= rk_another          )
  The above procedure condition is equivalent to
    In the B* tree exists a record with key rk      AND
    (      rk_the_one <= rk <= rk_another      )
.sp;.fo
One of the following messages, among others, is sent to
current.curr_trans^.trError_gg00:
.nf
   - e_ok
   - e_key_not_found
   - e_no_next_record
   - e_no_prev_record
   - b_file_not_found
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_disk_not_accessible
   - b_invalid_index_structure
   - b_invalid_leaves_structure
.sp 2;.cp 4
   b30repl_in_tree(rk,b,bd_use_info, current,e)
.sp
Replaces the record with the key rk in the current B* tree, if
such a record is present, with the new record contained in the
record buffer b.  The new record must also have the record key rk
and, if it is longer than the old record, will be substituted only
if sufficient space is available.
.br
Some possible acknowledgements in e:
   - e_ok
   - b_key_not_found
   - b_no_more_space
   - b_no_more_temp_space
   - b_illegal_entrypos
   - b_invalid_entrypos
   - b_invalid_index_structure
   - b_invalid_leaves_structure
   - b_disk_not_accessible
.fo
.CM *-END-* specification -------------------------------
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
 
The branch nodes of a B* tree form its
.oc _/1;B*_index
and the leaves form its
.oc _/1;B*_file.
For the management of a primary file, the records are stored
in the B* file, whereas the B* index represents a generally
multilevel index for the B* file.
.sp
For each primary file record, the B* file contains a record
entry that begins in a specific leaf (n) in a specific
position (pos).  This position can be accessed via an index
(pointer_list) that is located at the end of each leaf.  The
sorting of record entries is defined by the index.  Normally,
the record is inserted by appending it to the existing records
and maintaining the index.  This means that the sorting of all
the record entries in a leaf only becomes necessary if the leaf
takes part in a tree balancing operation.
The position of a record
entry is not fixed but changes along with the dynamic setup and
dismantling of the tree.
.sp
.cp 17
.nf
                      Structure of a node
                      ===================
 
            +-------<---------<---------+
            |    +--------<--------<----|---+
            |    |                      |   |
            |    |                      |   |
+---+------+|---+|-----+----+----+----+-|-+-|-+---+---+---+-+
|   |  s1  | s5 |  s4  | s2 | s3 |    |P5 |P4 |P3 |P2 |P1 | |
+-|-+|-----+----+------+|---+|---+----+---+---+-|-+-|-+-|-+-+
  |  |                  |    |                  |   |   |
  |  |                  |    |                  |   |   |
  |  |                  |    +----------<-------+   |   |
  |  |                  +----------<----------<-----+   |
  |  +-------<-------------<-------------<--------------+
  |
  +--> header
.fo
.sp2
The function of the B* index is to provide quick access to a
record entry with a preset key (b50find_leaf).
.br
In order to support the sequential processing (b30next_from_tree),
each leaf has a pointer to its right neighbor leaf
(see nodehandling) and an additional
.oc _/1;short-term_memory
(see keymemory) is maintained.
.sp
Each time a record entry is found and transferred to a
record buffer (get/next_from_tree), the 'address' of the record
entry is recorded in the memory.  The routines that process the
leaves are responsible for ensuring that the memory is not rendered
inconsistent by the insertion, deletion or replacement of record
entries.  When a search for a record entry is being carried out
(b30search_record), first of all an attempt is made to find the
page number of the 'leaf' and, if possible, even the position
(pos, when dirty = FALSE) of the record entry via the short-term
memory.  If no corresponding entry is found in the memory, a
descent via the index occurs (b50find_leaf).  The position
within a leaf is found via b31search_entry and 'result'
delivers one of the following acknowledgements:
.sp ;.of 2
- nonefound, if no record entry begins in that leaf,
.br ;.in ;.of 2
- thisfound, if the record entry being searched for was found,
.br ;.in ;.of 2
- nextfound, if the record entry being searched for does not begin
in that leaf and the next record entry was found,
.br ;.in ;.of 2
- lastfound, if the last record entry beginning in the leaf was
found and has a key that is smaller than that of the record
for which the search was run.
.sp ;.in
Changes in the leaves may result in the need for minor
modifications to the B* index.  These modifications are
executed with b54execute_indexorder
at the end.  For a more detailed description, see
indexupdateorders.
.sp
When an entire B* tree is deleted (b30release_tree), all
nodes are recursively deleted.  If the tree is made up of a
single node only (single), it is handled separately since this is
often the case with temporary files and should then take place very
quickly, whereas the large, permanent files are seldom deleted
and are also likely to require more time.
.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    :
 
 
TYPE
 
      int4_map_c4  = RECORD
            CASE boolean OF
                true  :
                    (map_c4 : tsp00_C4);
                false :
                    (map_i4 : tsp00_Int4)
                END;
            (*ENDCASE*) 
 
 
CONST
      MSG_ROOT_IS_LEAF  = 'Root is leaf            ';
      (* *)
      c_ignore_svp      = true; (* PTS 1106058 TS 2000-03-28 *)
      c_incl_root_upd   = true;
      c_include_strcols = true;
      c_use_lock        = true;
      (* *)
      c_max_retries     = 10;
      (* *)
      MSG_START_CHECK_TABLE = 'Start check tables                      ';
      MSG_START_CHECK_BLOB  = 'Start check blobs                       ';
 
 
(*------------------------------*) 
 
PROCEDURE
      b30add_filestate (VAR current : tbd_current_tree;
            new_filestate : tbd_file_state_set);
 
VAR
      nptr : tbd_node_ptrs;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00, nr_for_update, nptr);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        nptr.np_ptr^.nd_file_state := nptr.np_ptr^.nd_file_state +
              new_filestate;
        b13w_release_node (nptr, current)
        END
    ELSE
        IF  nptr.np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal)
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30add_to_tree (VAR rk : tgg00_Lkey;
            VAR b           : tgg00_Rec;
            page_fill_limit : integer;
            VAR current     : tbd_current_tree);
 
VAR
      result           : tbd_searchresult;
      lock_return      : tbd_lock_returncode;
      lock_type        : tbd_treelock;
      index            : integer;
      leaf             : tsp00_PageNo;
      nptr             : tbd_node_ptrs;
      neighbs          : tbd_neighbors;
      subtree_info     : tbd_subtree_info;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr, subtree_info DO
    BEGIN
    np_ptr        := NIL;
    np_cbptr      := NIL;
    lock_return   := lock_okay;
    lock_type     := w_lock_leaf;
    sti_is_del_op := false;
    REPEAT
        bd30rsearch_record (rk, lock_type, nr_for_update,
              subtree_info, nptr, index, neighbs, result, current);
        IF  trError_gg00 = e_ok
        THEN
            IF  result = thisfound
            THEN
                trError_gg00 := e_duplicate_key;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  (trError_gg00 <> e_ok              ) OR
            (curr_lockstate = no_bd_lock ) OR
            (curr_lockstate = w_lock_tree)
        THEN
            lock_return := lock_okay
        ELSE
            BEGIN
            IF    (
                np_ptr^.nd_bottom + b.len <=
                MAX_BOTTOM_BD00 - ((np_ptr^.nd_record_cnt+1)*POINTERSIZE_BD00)
                )
                AND
                (
                (np_ptr^.nd_bottom < page_fill_limit) OR
                (result <> lastfound                ) OR
                (np_ptr^.nd_right <> NIL_PAGE_NO_GG00)
                )
            THEN
                lock_return := lock_okay
            ELSE
                BEGIN
                (* *)
                (* OVERFLOW *)
                (* *)
                leaf := np_ptr^.nd_id;
                b13r_release_node (nptr, current, lru_normal);
                IF  (ftsDynamic_egg00 IN fileType_gg00) AND
                    NOT sti_index_overflow    AND
                    NOT sti_boundary          AND
                    g01glob.bd_subtree
                THEN
                    BEGIN
                    (* w_lock_leaf  -> w_lock_index *)
                    (* w_lock_index -> w_lock_index *)
                    IF  lock_type = w_lock_index
                    THEN
                        lock_return := lock_okay
                    ELSE
                        b75ilwrite_lock_index (current, leaf,
                              curr_lvl_1_locked, lock_return, 74)
                    (*ENDIF*) 
                    END
                ELSE
                    (* w_lock_leaf  -> w_lock_tree *)
                    (* w_lock_index -> w_lock_tree *)
                    b75tlwrite_lock_tree (current, leaf, lock_return, 73);
                (*ENDIF*) 
                lock_type := curr_lockstate;
                IF  lock_return = lock_okay
                THEN
                    BEGIN
                    IF  (sti_boundary                 ) AND
                        (curr_lockstate  = w_lock_tree) AND
                        (curr_left_bound = leaf       )
                    THEN
                        BEGIN
                        (* NOTE: neighbors are undefined!!    *)
                        (*       determine left neighbor      *)
                        (*       filetype is ftsDynamic_egg00 *)
                        lock_return := lock_dirty
                        END
                    ELSE
                        bd13GetNode (current, leaf, plmNoLock_ebd00, nr_for_update, nptr);
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN (* lock_dirty or lock_failed *)
                    IF  (lock_return = lock_dirty      ) AND
                        (
                        (curr_lockstate = w_lock_index ) OR
                        ((curr_lockstate = w_lock_tree ) AND
                        (NOT (ftsDynamic_egg00 IN fileType_gg00)))
                        )
                    THEN
                        BEGIN
                        bd13GetNode (current, leaf, plmNoLock_ebd00, nr_for_update, nptr);
                        IF  trError_gg00 = e_ok
                        THEN
                            b31search_entry (current, rk.keyVal_gg00, rk.keyLen_gg00,
                                  np_ptr, index, result);
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            IF  result = thisfound
                            THEN
                                trError_gg00 := e_duplicate_key;
                            (*ENDIF*) 
                        (*ENDIF*) 
                        lock_return := lock_okay
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
    UNTIL
        (lock_return = lock_okay) OR
        (trError_gg00 <> e_ok         );
    (*ENDREPEAT*) 
    IF  trError_gg00 = e_ok
    THEN
        CASE result OF
            nonefound :
                b31add_to_leaf (b, nptr, FIRST_REC_INDEX_BD00,
                      neighbs.ln, current);
            nextfound :
                b31add_to_leaf (b, nptr, index, neighbs.ln, current);
            lastfound :
                b31append_to_leaf (b, nptr, index, page_fill_limit,
                      neighbs.ln, current)
            END;
        (*ENDCASE*) 
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    CASE curr_lockstate OF
        w_lock_tree :
            b75tuwrite_unlock_tree (current);
        w_lock_leaf :
            b75luwrite_unlock_leaf (current, curr_node_locked);
        w_lock_index :
            b75iuwrite_unlock_index (current, curr_lvl_1_locked);
        r_lock_index :
            b75iuread_unlock_index (current, curr_lvl_1_locked);
        OTHERWISE
            ;
        END
    (*ENDCASE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30append_to_tree (VAR rk : tgg00_Lkey;
            VAR b        : tgg00_Rec;
            VAR tree_pos : tgg00_FilePos;
            VAR current  : tbd_current_tree);
 
VAR
      result      : tbd_searchresult;
      index       : integer;
      nptr        : tbd_node_ptrs;
      neighbs     : tbd_neighbors;
      dumm_estimation : tsp00_Int4;
 
BEGIN
WITH current, curr_trans^, nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL;
    IF  tree_pos.tpsPno_gg00 = NIL_PAGE_NO_GG00
    THEN
        BEGIN
        b30search_record (rk.keyVal_gg00, rk.keyLen_gg00, w_lock_leaf, nr_for_update,
              dumm_estimation, dumm_estimation, nptr, index,
              neighbs, result, current);
        IF  trError_gg00 = e_ok
        THEN
            IF  result = thisfound
            THEN
                trError_gg00 := e_duplicate_key
            ELSE
                IF  (result = nextfound) OR
                    (np_ptr^.nd_right <> NIL_PAGE_NO_GG00)
                THEN
                    trError_gg00 := e_append_not_allowed
                ELSE
                    BEGIN
                    tree_pos.tpsPno_gg00   := np_ptr^.nd_id;
                    IF  result = nonefound
                    THEN
                        tree_pos.tpsIndex_gg00 := index - 1
                    ELSE
                        tree_pos.tpsIndex_gg00 := index
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDIF*) 
        END
    ELSE
        bd13GetNode (current, tree_pos.tpsPno_gg00, plmNoLock_ebd00, nr_for_update, nptr);
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        b31t_append_to_temp_leaf (b, nptr, tree_pos, current);
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30bad_file (VAR current : tbd_current_tree;
            incl_root_upd : boolean;
            use_lock      : boolean;
            new_state     : tbd_file_state_set);
 
VAR
      aux_error : tgg00_BasisError;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    IF  (fileName_gg00 <> cgg_zero_fn) AND (fileRoot_gg00 <> NIL_PAGE_NO_GG00)
    THEN
        BEGIN
        aux_error    := trError_gg00;
        trError_gg00 := e_ok;
        IF  g04inv_tfn (fileTfn_gg00)
        THEN
            BEGIN
            IF  g01restart_local
            THEN
                b06file_opmsg (csp3_index_not_restored, current)
            ELSE
                b06file_opmsg (csp3_bad_index, current)
            (*ENDIF*) 
            END
        ELSE
            IF  (ftsByteStr_egg00 IN fileType_gg00)
            THEN
                b06file_opmsg (csp3_bad_long, current)
            ELSE
                b06file_opmsg (csp3_bad_file, current);
            (*ENDIF*) 
        (*ENDIF*) 
        IF  (ftsConcurrent_egg00 IN curr_tree_id.fileType_gg00) AND
            (curr_lockstate = no_bd_lock)                       AND
            use_lock
        THEN
            b75tldelete_lock_tree (current, c_ignore_svp, 162); (* PTS 1106058 TS 2000-03-28 *)
        (*ENDIF*) 
        IF  incl_root_upd AND NOT g04inv_tfn (current.curr_tree_id.fileTfn_gg00)
        THEN
            b30add_filestate (current, new_state);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b17fadd_file_state (current, new_state);
        (*ENDIF*) 
        IF  (curr_lockstate = d_lock_tree) AND use_lock
        THEN
            b75tudelete_unlock_tree (current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            trError_gg00 := aux_error
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(* PTS 1109905 E.Z. *)
(*------------------------------*) 
 
PROCEDURE
      b30check_tree (
            VAR current          : tbd_current_tree;
            long_col_cnt         : tsp00_Int2;
            new_long_col_cnt     : tsp00_Int2;
            check_long_existence : boolean);
 
VAR
      bad_long    : boolean;
      dump_page   : boolean;
      bFileWasBad : boolean;
      bSetRootBad : boolean;
      nptrs       : tbd_node_ptrs;
 
BEGIN
WITH current, curr_trans^, curr_tree_id  DO
    BEGIN
    trError_gg00   := e_ok;
    bad_long       := false;
    dump_page      := false;
    bFileWasBad    := false;
    bSetRootBad    := false;
    nptrs.np_ptr   := NIL;
    nptrs.np_cbptr := NIL;
    IF  (fileRoot_gg00 <> b17permfdir_current.curr_tree_id.fileRoot_gg00)
        AND
        (fileRoot_gg00 <> b17strcolfdir_current.curr_tree_id.fileRoot_gg00)
    THEN
        b06file_opmsg (csp3_check_file, current);
    (*ENDIF*) 
    IF  curr_lockstate = r_lock_tree
    THEN
        b75tlselect_lock_tree (current, 163);
    (* PTS 1109905 E.Z. *)
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00, nr_for_read, nptrs);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            bSetRootBad := true;
            bFileWasBad := (f_bad IN nptrs.np_ptr^.nd_file_state);
            END;
        (*ENDIF*) 
        IF  nptrs.np_ptr <> NIL
        THEN
            b13r_release_node (nptrs, current, lru_normal);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b50check_subtree (fileRoot_gg00, NIL_PAGE_NO_GG00, long_col_cnt,
                  new_long_col_cnt, dump_page, bad_long, current, check_long_existence);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  curr_lockstate = s_lock_tree
    THEN
        b75tuselect_unlock_tree (current);
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND bFileWasBad
    THEN
        b30reset_bad_file (current, c_incl_root_upd, [f_bad])
    ELSE
        IF  e_bad_datapage = trError_gg00
        THEN
            b30bad_file (current, bSetRootBad, c_use_lock, [f_bad])
        ELSE
            IF  (trError_gg00 <> e_ok                 ) AND
                (trError_gg00 <> e_disk_not_accessible) AND
                (trError_gg00 <> e_cancelled          ) AND
                (trError_gg00 <> e_shutdown           )
            THEN
                b06file_opmsg (csp3_bad_file, current);
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND bad_long
    THEN
        trError_gg00 := e_bad_file
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30cget_result_leaf (VAR rk : tgg00_Lkey;
            get_next        : boolean;
            prepare_for_upd : boolean;
            VAR tree_pos    : tgg00_FilePos;
            VAR nptr        : tbd_node_ptrs;
            VAR current     : tbd_current_tree);
 
VAR
      result          : tbd_searchresult;
      node_req        : tbd_node_request;
      index           : integer;
      right_neighbor  : tsp00_PageNo;
      neighbs         : tbd_neighbors;
      dumm_estimation : tsp00_Int4;
 
BEGIN
WITH current, curr_trans^, nptr DO
    BEGIN
    IF  prepare_for_upd
    THEN
        node_req := nr_for_update
    ELSE
        node_req := nr_for_read;
    (*ENDIF*) 
    IF  np_ptr <> NIL
    THEN
        BEGIN
        IF  get_next
        THEN
            right_neighbor := np_ptr^.nd_right
        ELSE
            right_neighbor := tree_pos.tpsPno_gg00;
        (*ENDIF*) 
        IF  prepare_for_upd
        THEN
            b13w_release_node (nptr, current)
        ELSE
            b13r_release_node (nptr, current, lru_normal)
        (*ENDIF*) 
        END
    ELSE
        IF  get_next
        THEN
            right_neighbor := NIL_PAGE_NO_GG00
        ELSE
            right_neighbor := tree_pos.tpsPno_gg00;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  tree_pos.tpsPno_gg00 = NIL_PAGE_NO_GG00
    THEN
        BEGIN
        b30search_record (rk.keyVal_gg00, rk.keyLen_gg00, no_bd_lock, node_req,
              dumm_estimation,
              dumm_estimation, nptr, index, neighbs, result, current);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  result = nonefound
            THEN
                trError_gg00 := e_no_next_record
            ELSE
                IF  (result = lastfound) OR
                    (result = thisfound)
                THEN
                    IF  prepare_for_upd
                    THEN
                        b31w_next_search (nptr, index, current)
                    ELSE
                        b31next_search (RELEASE_FRAME_BD00, nptr, index,
                              current);
                    (*ENDIF*) 
                (*might return b_no_next_record*)
                (*ENDIF*) 
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                tree_pos.tpsPno_gg00   := np_ptr^.nd_id;
                tree_pos.tpsIndex_gg00 := index
                END
            ELSE
                tree_pos.tpsPno_gg00 := NIL_PAGE_NO_GG00
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  right_neighbor <> NIL_PAGE_NO_GG00
        THEN
            BEGIN
            bd13GetNode (current, right_neighbor, plmNoLock_ebd00, node_req, nptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                tree_pos.tpsPno_gg00   := np_ptr^.nd_id;
                tree_pos.tpsIndex_gg00 := FIRST_REC_INDEX_BD00
                END
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            trError_gg00         := e_no_next_record;
            tree_pos.tpsPno_gg00 := NIL_PAGE_NO_GG00
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30cinit_current (VAR t : tgg00_TransContext;
            VAR current : tbd_current_tree);
 
BEGIN
bd01SetToNilCurrent (current);
current.curr_trans := @t;
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30cnext_from_tree (VAR rk : tgg00_Lkey;
            VAR set_result : tgg00_BdSetResultRecord;
            VAR tree_pos   : tgg00_FilePos;
            VAR b          : tsp00_MoveObj;
            VAR current    : tbd_current_tree);
 
VAR
      result      : tbd_searchresult;
      index       : integer;
      nptr        : tbd_node_ptrs;
      neighbs     : tbd_neighbors;
      dumm_estimation : tsp00_Int4;
 
BEGIN
WITH current, curr_trans^, nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL;
    IF  tree_pos.tpsPno_gg00 = NIL_PAGE_NO_GG00
    THEN
        BEGIN
        b30search_record (rk.keyVal_gg00, rk.keyLen_gg00, r_lock_leaf, nr_for_read,
              dumm_estimation,
              dumm_estimation, nptr, index, neighbs, result, current);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  result = nonefound
            THEN
                trError_gg00 := e_no_next_record
            ELSE
                IF  (result = lastfound) OR
                    ((result = thisfound) AND set_result.bd_next)
                THEN
                    b31next_search (RELEASE_FRAME_BD00, nptr, index,
                          current);
                (*might return b_no_next_record*)
                (*ENDIF*) 
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                tree_pos.tpsPno_gg00   := np_ptr^.nd_id;
                tree_pos.tpsIndex_gg00 := index
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        result := thisfound;
        bd13GetNode (current, tree_pos.tpsPno_gg00, plmNoLock_ebd00, nr_for_read, nptr);
        IF  set_result.bd_next AND (trError_gg00 = e_ok)
        THEN
            BEGIN
            index := tree_pos.tpsIndex_gg00;
            b31next_search (RELEASE_FRAME_BD00, nptr, index, current);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                tree_pos.tpsPno_gg00   := np_ptr^.nd_id;
                tree_pos.tpsIndex_gg00 := index
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        b31nfill_recordbuffer (nptr, rk, tree_pos, set_result, b,
              current);
    (*ENDIF*) 
    IF  (result <> thisfound) AND (trError_gg00 = e_ok)
    THEN
        trError_gg00 := e_key_not_found;
    (*ENDIF*) 
    IF  np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30col_next_stringcol (VAR rk : tgg00_Lkey;
            string_col_cnt    : integer;
            VAR string_col_no : integer;
            VAR col_id        : tgg00_FileId;
            VAR tree_pos      : tgg00_FilePos;
            VAR current       : tbd_current_tree);
 
VAR
      found       : boolean;
      result      : tbd_searchresult;
      klen        : ^tsp00_Int2;
      rec_pos     : integer;
      strcol_pos  : integer;
      index       : integer;
      leaf        : tsp00_PageNo;
      nptr        : tbd_node_ptrs;
      col_fi      : tbd_fileinfo;
      neighbs     : tbd_neighbors;
      dumm_estimation : tsp00_Int4;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL;
    found         := false;
    IF  tree_pos.tpsPno_gg00 = NIL_PAGE_NO_GG00
    THEN
        BEGIN
        b30search_record (rk.keyVal_gg00, rk.keyLen_gg00, no_bd_lock, nr_for_read,
              dumm_estimation,
              dumm_estimation, nptr, index, neighbs, result, current);
        IF  (trError_gg00 = e_ok) AND (result = nonefound)
        THEN
            trError_gg00 := e_no_next_record
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        bd13GetNode (current, tree_pos.tpsPno_gg00, plmNoLock_ebd00, nr_for_read, nptr);
        index  := tree_pos.tpsIndex_gg00;
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        REPEAT
            WHILE (index < np_ptr^.nd_record_cnt) AND
                  (NOT found) DO
                WITH np_ptr^ DO
                    BEGIN
                    rec_pos    := nd_pointer_list [ MAX_POINTERINDEX_BD00 - index ];
                    klen       := @nd_body[ rec_pos + 2 ];
                    strcol_pos := rec_pos + cgg_rec_key_offset + klen^;
                    strcol_pos       := strcol_pos + string_col_no *
                          cgg_col_fd_size;
                    string_col_no    := string_col_no + 1;
                    WHILE (string_col_no <= string_col_cnt) AND
                          (NOT found) DO
                        BEGIN
                        IF  nd_body[strcol_pos] <> csp_undef_byte
                        THEN
                            BEGIN
                            col_id              := b01niltree_id;
                            col_id.fileTfn_gg00 := tfnColumn_egg00;
                            col_id.fileType_gg00     := [ftsByteStr_egg00, ftsConcurrent_egg00];
                            g10mv1 ('VBD30 ',   1,    
                                  sizeof (np_ptr^), sizeof (col_id.fileName_gg00),
                                  np_ptr^, strcol_pos + 1,
                                  col_id.fileName_gg00, 3, SURROGATE_MXGG00, 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
                                b17state_fdir (col_id.fileName_gg00, col_fi,
                                      ftsShared_egg00 in col_id.fileType_gg00,
                                      curr_trans^);
                            (*ENDIF*) 
                            IF  trError_gg00 = e_ok
                            THEN
                                found := true
                            ELSE
                                BEGIN
                                IF  trError_gg00 = e_file_not_found
                                THEN
                                    trError_gg00 := e_ok;
                                (*ENDIF*) 
                                strcol_pos    := strcol_pos +
                                      cgg_col_fd_size;
                                string_col_no := string_col_no + 1
                                END
                            (*ENDIF*) 
                            END
                        ELSE
                            BEGIN
                            strcol_pos    := strcol_pos +
                                  cgg_col_fd_size;
                            string_col_no := string_col_no + 1
                            END
                        (*ENDIF*) 
                        END;
                    (*ENDWHILE*) 
                    IF  found AND (trError_gg00 = e_ok)
                    THEN
                        BEGIN
                        tree_pos.tpsIndex_gg00 := index;
                        tree_pos.tpsPno_gg00   := nd_id;
                        rk.len                 := klen^;
                        g10mv3 ('VBD30 ',   2,    
                              sizeof (np_ptr^), sizeof (rk.k),
                              np_ptr^, rec_pos + cgg_rec_key_offset,
                              rk.k, 1, rk.len, 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
                    ELSE
                        BEGIN
                        string_col_no := 0;
                        index         := index + 1
                        END
                    (*ENDIF*) 
                    END;
                (*ENDWITH*) 
            (*ENDWHILE*) 
            IF  (NOT found) AND (trError_gg00 = e_ok)
            THEN
                BEGIN
                leaf := np_ptr^.nd_right;
                b13r_release_node (nptr, current, lru_last);
                IF  leaf <> NIL_PAGE_NO_GG00
                THEN
                    bd13GetNode (current, leaf, plmNoLock_ebd00, nr_for_read, nptr)
                ELSE
                    trError_gg00 := e_no_next_record;
                (*ENDIF*) 
                index := FIRST_REC_INDEX_BD00
                END
            (*ENDIF*) 
        UNTIL
            (trError_gg00 <> e_ok) OR
            found;
        (*ENDREPEAT*) 
    (*ENDIF*) 
    IF  np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30cprev_from_tree (VAR rk : tgg00_Lkey;
            VAR set_result : tgg00_BdSetResultRecord;
            VAR tree_pos   : tgg00_FilePos;
            VAR b          : tsp00_MoveObj;
            VAR current    : tbd_current_tree);
 
VAR
      result      : tbd_searchresult;
      index       : integer;
      nptr        : tbd_node_ptrs;
      neighbs     : tbd_neighbors;
      dumm_estimation : tsp00_Int4;
 
BEGIN
WITH current, curr_trans^, nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL;
    IF  tree_pos.tpsPno_gg00 = NIL_PAGE_NO_GG00
    THEN
        BEGIN
        b30search_record (rk.keyVal_gg00, rk.keyLen_gg00, r_lock_leaf, nr_for_read,
              dumm_estimation,
              dumm_estimation, nptr, index, neighbs, result, current);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  result = nonefound
            THEN
                trError_gg00 := e_no_prev_record
            ELSE
                IF  (result = nextfound) OR
                    ((result = thisfound) AND set_result.bd_next)
                THEN
                    b31t_prev_temp_search (nptr, index, current);
                (*ENDIF*) 
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                tree_pos.tpsPno_gg00   := np_ptr^.nd_id;
                tree_pos.tpsIndex_gg00 := index
                END;
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        result := thisfound;
        bd13GetNode (current, tree_pos.tpsPno_gg00, plmNoLock_ebd00, nr_for_read, nptr);
        IF  set_result.bd_next AND (trError_gg00 = e_ok)
        THEN
            BEGIN
            index := tree_pos.tpsIndex_gg00;
            b31t_prev_temp_search (nptr, index, current);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                tree_pos.tpsPno_gg00   := np_ptr^.nd_id;
                tree_pos.tpsIndex_gg00 := index
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        b31pfill_recordbuffer (nptr, rk, tree_pos, set_result, b,
              current);
    (*ENDIF*) 
    IF  (result <> thisfound) AND (trError_gg00 = e_ok)
    THEN
        trError_gg00 := e_key_not_found;
    (*ENDIF*) 
    IF  np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30current (VAR t : tgg00_TransContext;
            VAR file_id : tgg00_FileId;
            m_type      : tgg00_MessType;
            VAR current : tbd_current_tree);
 
VAR
      fi          : tbd_fileinfo;
 
BEGIN
b30cinit_current (t, current);
WITH current, t DO
    BEGIN
    curr_action := m_type;
    IF  file_id.fileRoot_gg00 <> NIL_PAGE_NO_GG00
    THEN
        BEGIN
        IF  (file_id.fileRoot_gg00 = bd17GetFdirRoot    ) OR
            (file_id.fileRoot_gg00 = bd17GetLongFdirRoot)
        THEN
            trError_gg00 := e_do_not_access_fdir
        ELSE
            IF  file_id.fileRootCheck_gg00 <> ROOT_CHECK_GG00
            THEN
                bd300FileIdRootCheck (file_id, trError_gg00);
            (*ENDIF*) 
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            curr_tree_id := file_id;
            IF  ftsConcurrent_egg00 in file_id.fileType_gg00
            THEN
                b75tlread_lock_tree (current, 60)
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        b17get_fdir (file_id.fileName_gg00, fi, ftsShared_egg00 in file_id.fileType_gg00, t);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            b30fdir_to_treeid (fi, file_id);
            curr_tree_id := file_id;
            IF  ftsConcurrent_egg00 in fi.fi_type
            THEN
                BEGIN
                b75tlread_lock_tree (current, 61);
                IF  (file_id.fileVersion_gg00          <> fi.fi_vers            ) AND
                    (file_id.fileVersion_gg00.ci2_gg00 <> cgg_dummy_file_version)
                THEN
                    trError_gg00 := e_old_fileversion
                ELSE
                    IF  (f_not_accessible IN fi.fi_state             ) AND
                        NOT (bd_release_acc IN file_id.fileBdUse_gg00)
                    THEN
                        trError_gg00 := e_file_not_accessible
                    ELSE
                        IF  bd_write_acc IN curr_tree_id.fileBdUse_gg00
                        THEN
                            IF  f_bad IN fi.fi_state
                            THEN
                                BEGIN
                                trError_gg00 := e_bad_file;
                                b06file_opmsg (csp3_bad_file, current);
                                END
                            ELSE
                                IF  (f_write_off IN fi.fi_state)
                                    OR
                                    (
                                    (f_read_only IN fi.fi_state) AND
                                    (NOT (bd_load_nolog IN curr_tree_id.fileBdUse_gg00)) AND
                                    (NOT (hsNoLog_egg00 IN  curr_tree_id.fileHandling_gg00))
                                    )
                                THEN
                                    trError_gg00 := e_file_read_only
                                ELSE
                                    IF  (hsNoLog_egg00 IN file_id.fileHandling_gg00)
                                        AND
                                        (NOT (hsIgnoreReadOnly_egg00 IN file_id.fileHandling_gg00))
                                        AND
                                        (NOT(f_read_only IN fi.fi_state))
                                    THEN
                                        trError_gg00 :=  e_file_must_be_read_only
                                    (*ENDIF*) 
                                (*ENDIF*) 
                            (*ENDIF*) 
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_file_must_be_read_only
        THEN
            BEGIN
            IF  curr_lockstate = r_lock_tree
            THEN
                b75turead_unlock_tree (current);
            (*ENDIF*) 
            b30set_read_only (current);
            IF  (trError_gg00 = e_ok) AND
                (ftsConcurrent_egg00 IN file_id.fileType_gg00)
            THEN
                b75tlread_lock_tree (current, 62)
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30database_verify (
            VAR t             : tgg00_TransContext;
            VAR bad_index_cnt : tsp00_Int4;
            VAR total_bad_cnt : tsp00_Int4;
            VAR verify_error  : tgg00_BasisError;
            bWithUpdate       : boolean;
            bWithIndexes      : boolean;
            max_server        : integer);
 
VAR
      finish           : boolean;
      handle_error     : boolean;
      startBlobVerify  : boolean;
      bSearchNext      : boolean;
      retry_cnt        : integer;
      send_cnt         : integer;
      ErrorRoot        : tsp00_PageNo;
      fi               : tbd_fileinfo;
      file_id          : tgg00_FileId;
      current          : tbd_current_tree;
 
BEGIN
finish          := false;
handle_error    := false;
startBlobVerify := false;
bSearchNext     := false;
retry_cnt       := 0;
send_cnt        := 0;
ErrorRoot       := NIL_PAGE_NO_GG00;
file_id         := b01niltree_id;
IF  bWithUpdate
THEN
    bWithIndexes := true;
(*ENDIF*) 
WITH t DO
    BEGIN
    g01optextmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
          csp3_n_check, MSG_START_CHECK_TABLE);
    WHILE (
          (trError_gg00 = e_ok) AND
          (NOT finish         )
          )
          OR
          (
          (trError_gg00 = e_too_many_net_requests) AND
          (retry_cnt < c_max_retries             )
          )
          DO
        BEGIN
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            REPEAT
                b30cinit_current (t, current);
                b17succ_fdir (file_id.fileName_gg00, file_id.fileName_gg00, fi,
                      ftsShared_egg00 IN file_id.fileType_gg00, t, c_include_strcols);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    b30fdir_to_treeid (fi, file_id);
                    current.curr_tree_id := file_id;
                    IF  (NOT startBlobVerify AND (ftsByteStr_egg00 IN file_id.fileType_gg00))
                    THEN
                        BEGIN
                        startBlobVerify := true;
                        g01optextmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
                              csp3_n_check, MSG_START_CHECK_BLOB)
                        END;
                    (*ENDIF*) 
                    bSearchNext := (fi.fi_root = NIL_PAGE_NO_GG00) OR
                          ((NOT bWithIndexes) AND (g04inv_tfn (file_id.fileTfn_gg00)))
                    END;
                (*ENDIF*) 
            UNTIL
                (trError_gg00 <> e_ok) OR (NOT bSearchNext);
            (*ENDREPEAT*) 
            IF  trError_gg00 = e_file_not_found
            THEN
                BEGIN
                finish       := true;
                trError_gg00 := e_ok
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  (
            (trError_gg00 = e_ok                   ) OR
            (trError_gg00 = e_too_many_net_requests)
            )
            AND
            (
            (fi.fi_root <> NIL_PAGE_NO_GG00)
            )
            AND
            (NOT finish                    )
        THEN
            bd30_SendFileId (t, file_id, retry_cnt, send_cnt, m_verify);
        (*ENDIF*) 
        IF  (
            (trError_gg00 = e_ok             ) AND
            (send_cnt = max_server           )
            )
            OR
            (
            (finish                          ) AND
            (send_cnt > 0                    )
            )
            OR
            (
            (trError_gg00 = e_too_many_net_requests) AND
            (send_cnt > 0                    )
            )
        THEN
            BEGIN
            bd30wait_for_reply (t, send_cnt, ErrorRoot, max_server, finish);
            handle_error := (trError_gg00 <> e_ok)
            END;
        (*ENDIF*) 
        IF  (fi.fi_root <> NIL_PAGE_NO_GG00   )
            AND
            (NOT finish                      )
            AND
            (
            (trError_gg00 = e_too_many_net_requests) AND
            (send_cnt = 0                    ) AND
            (retry_cnt >= c_max_retries      )
            )
        THEN
            BEGIN
            (* no server available *)
            trError_gg00 := e_ok;
            retry_cnt    := 0;
            b01pverify_participant (t, file_id, bWithUpdate);
            (* PTS 1105359 TS 2000-01-17 *)
            IF   (trError_gg00 <> e_ok)
            THEN
                BEGIN
                handle_error := true;
                ErrorRoot    := file_id.fileRoot_gg00;
                END
            ELSE
                handle_error := false;
            (*ENDIF*) 
            (* PTS 1105359 *)
            END;
        (*ENDIF*) 
        IF  (handle_error                           ) AND
            (trError_gg00 <> e_too_many_net_requests) AND
            (trError_gg00 <> e_shutdown             ) AND
            (trError_gg00 <> e_disk_not_accessible  ) AND
            (trError_gg00 <> e_cancelled            )
        THEN
            BEGIN
            handle_error  := false;
            total_bad_cnt := succ (total_bad_cnt);
            IF  trError_gg00 = e_file_not_accessible
            THEN
                bad_index_cnt := succ (bad_index_cnt)
            ELSE
                IF  verify_error = e_ok
                THEN
                    verify_error := trError_gg00;
                (* PTS 1105359 TS 2000-01-17 *)
                (*ENDIF*) 
            (*ENDIF*) 
            bd30_PnoCheckOpmsg (ErrorRoot, -1, csp3_verify_check, trError_gg00);
            (* PTS 1105359 *)
            (* *)
            trError_gg00 := e_ok;
            END;
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (trRteCommPtr_gg00^.to_cancel)
        THEN
            trError_gg00 := e_cancelled
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  trError_gg00 <> e_ok
    THEN
        bd30discard_task (t, send_cnt);
    (*ENDIF*) 
    IF  (finish) AND (trError_gg00 = e_ok)
    THEN
        trError_gg00 := e_file_not_found
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30del_from_tree (VAR rk : tgg00_Lkey;
            VAR current : tbd_current_tree);
 
VAR
      underflow        : boolean;
      result           : tbd_searchresult;
      lock_return      : tbd_lock_returncode;
      lock_type        : tbd_treelock;
      pos, index       : integer;
      el               : ^tsp00_Int2;
      subtree_info     : tbd_subtree_info;
      leaf             : tsp00_PageNo;
      nptr             : tbd_node_ptrs;
      neighbs          : tbd_neighbors;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr, subtree_info DO
    BEGIN
    np_ptr        := NIL;
    np_cbptr      := NIL;
    lock_return   := lock_okay;
    lock_type     := w_lock_leaf;
    sti_is_del_op := true;
    underflow     := false;
    REPEAT
        bd30rsearch_record (rk, lock_type, nr_for_update,
              subtree_info, nptr, index, neighbs, result, current);
        IF  trError_gg00 = e_ok
        THEN
            IF  result <> thisfound
            THEN
                trError_gg00 := e_key_not_found;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  (trError_gg00 <> e_ok              ) OR
            (curr_lockstate = no_bd_lock ) OR
            (curr_lockstate = w_lock_tree)
        THEN
            lock_return := lock_okay
        ELSE
            BEGIN
            WITH np_ptr^ DO
                BEGIN
                pos := nd_pointer_list[ MAX_POINTERINDEX_BD00 - index ];
                el  := @nd_body [ pos ]
                END;
            (*ENDWITH*) 
            IF  ftsDynamic_egg00 IN fileType_gg00
            THEN
                underflow :=
                      (
                      np_ptr^.nd_record_cnt = 1
                      )
                      AND
                      (np_ptr^.nd_id <> fileRoot_gg00)
            ELSE
                underflow :=
                      (
                      (np_ptr^.nd_bottom - el^ - BODY_BEG_BD00 +
                      ((np_ptr^.nd_record_cnt-1)*POINTERSIZE_BD00))
                      < HALF_COVERING_BD00
                      )
                      AND
                      (np_ptr^.nd_id <> fileRoot_gg00);
            (*ENDIF*) 
            IF  NOT underflow
            THEN
                lock_return := lock_okay
            ELSE
                BEGIN
                (* *)
                (* UNDERFLOW *)
                (* *)
                leaf := np_ptr^.nd_id;
                b13r_release_node (nptr, current, lru_normal);
                IF  (ftsDynamic_egg00 IN fileType_gg00) AND
                    NOT sti_index_underflow   AND
                    NOT sti_boundary          AND
                    g01glob.bd_subtree
                THEN
                    BEGIN
                    (* w_lock_leaf  -> w_lock_index *)
                    (* w_lock_index -> w_lock_index *)
                    IF  lock_type = w_lock_index
                    THEN
                        lock_return := lock_okay
                    ELSE
                        b75ilwrite_lock_index (current, leaf,
                              curr_lvl_1_locked, lock_return, 64)
                    (*ENDIF*) 
                    END
                ELSE
                    (* w_lock_leaf  -> w_lock_tree *)
                    (* w_lock_index -> w_lock_tree *)
                    b75tlwrite_lock_tree (current, leaf, lock_return, 63);
                (*ENDIF*) 
                lock_type := curr_lockstate;
                IF  lock_return = lock_okay
                THEN
                    BEGIN
                    IF  (sti_boundary                 ) AND
                        (curr_lockstate  = w_lock_tree) AND
                        (curr_left_bound = leaf       )
                    THEN
                        BEGIN
                        (* NOTE: neighbors are undefined!!    *)
                        (*       determine left neighbor      *)
                        (*       filetype is ftsDynamic_egg00 *)
                        lock_return := lock_dirty
                        END
                    ELSE
                        bd13GetNode (current, leaf, plmNoLock_ebd00, nr_for_update, nptr);
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN (* lock_dirty or lock_failed *)
                    IF  (lock_return = lock_dirty      ) AND
                        (
                        (curr_lockstate = w_lock_index           ) OR
                        ((curr_lockstate = w_lock_tree           ) AND
                        (NOT (ftsDynamic_egg00 IN fileType_gg00)))
                        )
                    THEN
                        BEGIN
                        bd13GetNode (current, leaf, plmNoLock_ebd00, nr_for_update, nptr);
                        IF  trError_gg00 = e_ok
                        THEN
                            b31search_entry (current, rk.keyVal_gg00, rk.keyLen_gg00,
                                  np_ptr, index, result);
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            IF  result <> thisfound
                            THEN
                                trError_gg00 := e_key_not_found;
                            (*ENDIF*) 
                        (*ENDIF*) 
                        lock_return := lock_okay
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
    UNTIL
        (lock_return = lock_okay) OR
        (trError_gg00 <> e_ok         );
    (*ENDREPEAT*) 
    IF  trError_gg00 = e_ok
    THEN
        b31del_from_leaf (nptr, index, neighbs.ln, current);
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    CASE curr_lockstate OF
        w_lock_tree :
            b75tuwrite_unlock_tree (current);
        w_lock_leaf :
            b75luwrite_unlock_leaf (current, curr_node_locked);
        w_lock_index :
            b75iuwrite_unlock_index (current, curr_lvl_1_locked);
        r_lock_index :
            b75iuread_unlock_index (current, curr_lvl_1_locked);
        OTHERWISE
            ;
        END
    (*ENDCASE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30exists_rec (VAR rk : tgg00_Lkey;
            VAR current     : tbd_current_tree);
 
VAR
      result     : tbd_searchresult;
      index      : integer;
      nptr       : tbd_node_ptrs;
      neighbs    : tbd_neighbors;
      dumm_estimation : tsp00_Int4;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL;
    b30search_record
          (rk.keyVal_gg00, rk.keyLen_gg00, r_lock_leaf, nr_for_read, dumm_estimation,
          dumm_estimation, nptr, index, neighbs, result, current);
    IF  (trError_gg00 = e_ok) AND (result <> thisfound)
    THEN
        trError_gg00 := e_key_not_found;
    (*ENDIF*) 
    IF  np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    CASE curr_lockstate OF
        r_lock_leaf  :
            b75luread_unlock_leaf (current, curr_node_locked);
        r_lock_index :
            b75iuread_unlock_index (current, curr_lvl_1_locked);
        OTHERWISE
            ;
        END
    (*ENDCASE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30fdir_to_treeid (VAR fi : tbd_fileinfo;
            VAR file_id : tgg00_FileId);
 
BEGIN
WITH file_id DO
    BEGIN
    fileRoot_gg00     := fi.fi_root;
    fileType_gg00 := fi.fi_type;
    IF  fileRoot_gg00 = NIL_PAGE_NO_GG00
    THEN
        fileRootCheck_gg00 := ROOT_CHECK_GG00
    ELSE
        bd300SetRootCheck (file_id);
    (*ENDIF*) 
&   ifdef trace
    t01int4 (bi, '30n_root_che', fileRootCheck_gg00);
&   endif
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30find_leaf (VAR key : tgg00_Lkey;
            VAR current : tbd_current_tree);
 
VAR
      nptr              : tbd_node_ptrs;
      neighbs           : tbd_neighbors;
      sub_info          : tbd_subtree_info;
      dummy_left_estim  : tsp00_Int4;
      dummy_right_estim : tsp00_Int4;
      index_pno         : tsp00_PageNo;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL;
    sub_info.sti_is_del_op := false;
    IF  trError_gg00 = e_ok
    THEN
        b50find_leaf (key.keyVal_gg00, key.keyLen_gg00, r_lock_leaf, nr_for_read,
              sub_info, dummy_left_estim, dummy_right_estim, index_pno,
              nptr, neighbs, current);
    (*ENDIF*) 
    IF  np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    CASE curr_lockstate OF
        r_lock_leaf  :
            b75luread_unlock_leaf (current, curr_node_locked);
        r_lock_index :
            b75iuread_unlock_index (current, curr_lvl_1_locked);
        OTHERWISE
            ;
        END
    (*ENDCASE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30get_from_tree (VAR rk : tgg00_Lkey;
            VAR b       : tgg00_Rec;
            VAR current : tbd_current_tree;
            wanted_mode : tgg00_LockReqMode);
 
VAR
      result      : tbd_searchresult;
      index       : integer;
      nptr        : tbd_node_ptrs;
      neighbs     : tbd_neighbors;
      dumm_estimation : tsp00_Int4;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL;
    b30search_record (rk.keyVal_gg00, rk.keyLen_gg00, r_lock_leaf, nr_for_read,
          dumm_estimation,
          dumm_estimation, nptr, index, neighbs, result, current);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  result <> thisfound
        THEN
            BEGIN
            trError_gg00 := e_key_not_found;
            b13r_release_node (nptr, current, lru_normal);
            IF  curr_lockstate = r_lock_leaf
            THEN
                b75luread_unlock_leaf (current, curr_node_locked);
            (*ENDIF*) 
            END
        ELSE
            b31get_from_leaf (nptr, index, wanted_mode <> lckFree_egg00,
                  b, current)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    CASE curr_lockstate OF
        r_lock_leaf  :
            b75luread_unlock_leaf (current, curr_node_locked);
        r_lock_index :
            b75iuread_unlock_index (current, curr_lvl_1_locked);
        OTHERWISE
            ;
        END
    (*ENDCASE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30init_load (VAR rightmost_leaf : tsp00_PageNo;
            VAR current : tbd_current_tree);
 
VAR
      nptr            : tbd_node_ptrs;
      neighbs         : tbd_neighbors;
      fullkey         : tgg00_Lkey;
      dumm_estimation : tsp00_Int4;
      dummy_subtree   : tbd_subtree_info;
      index_pno       : tsp00_PageNo;
 
BEGIN
nptr.np_ptr         := NIL;
nptr.np_cbptr       := NIL;
rightmost_leaf      := NIL_PAGE_NO_GG00;
fullkey.keyLen_gg00 := MAX_KEYLEN_GG00;
fullkey.keyVal_gg00 := b01fullkey;
WITH current DO
    BEGIN
    b50find_leaf (fullkey.keyVal_gg00, fullkey.keyLen_gg00, w_lock_tree, nr_for_read, dummy_subtree,
          dumm_estimation,
          dumm_estimation, index_pno, nptr, neighbs, current);
    IF  curr_trans^.trError_gg00 = e_ok
    THEN
        BEGIN
        rightmost_leaf := nptr.np_ptr^.nd_id;
        b13r_release_node (nptr, current, lru_normal)
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30load_table (VAR lnptr : tbd_node_ptrs;
            VAR nptr           : tbd_node_ptrs;
            only_left          : boolean;
            VAR current        : tbd_current_tree);
 
VAR
      rightmost_leaf : tsp00_PageNo;
      sep            : tgg00_Lkey;
      indexorderlist : tbd00_OrderList;
      save_bottom    : tgg00_PagePos;
      save_list_top  : tsp00_Int4;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    (* only one page is given via sql packet *)
    IF  only_left
    THEN
        lnptr.np_ptr^.nd_right := NIL_PAGE_NO_GG00
    ELSE
        BEGIN
        curr_lvl_1_pno := NIL_PAGE_NO_GG00;
        indexorderlist.olstCount_bd00 := 0;
        WITH nptr.np_ptr^ DO
            BEGIN
            (* h.b. 19.02.99                          *)
            (* changed initialisation for FASTLOAD:   *)
            (* list_top and bottom are already filled *)
            (* by FASTLOAD                            *)
            save_bottom      := nd_bottom;
            save_list_top    := nd_record_cnt;
            b13init_default_data_page (curr_trans^, curr_tree_id, LEAF_LEVEL_BD00, nd_id, nptr);
            nd_bottom        := save_bottom;
            nd_record_cnt    := save_list_top;
            IF  ftsTemp_egg00 in fileType_gg00
            THEN
                nd_left  := lnptr.np_ptr^.nd_id;
            (*ENDIF*) 
            IF  (nd_id = fileRoot_gg00)
            THEN
                nd_file_version := fileVersion_gg00;
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
        lnptr.np_ptr^.nd_right := nptr.np_ptr^.nd_id;
        sep.keyLen_gg00 := 0; (* sep.lksep.len := 0; *)
        bd53NewLeafIndex (lnptr.np_ptr, nptr.np_ptr, sep, curr_trans);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            b54add_index (@sep.keyVal_gg00, sep.keyLen_gg00, nptr.np_ptr^.nd_id,
                  LEAF_LEVEL_BD00, indexorderlist);
            b13w_release_node (lnptr, current);
            (* *)
            (* PTS XXXX TS 2000-12-27 *)
            (* release pages to avoid illegal request in data cache *)
            rightmost_leaf := nptr.np_ptr^.nd_id;
            b13w_release_node (nptr, current);
            (* *)
            b54execute_indexorder (indexorderlist, current);
            IF  trError_gg00 = e_ok
            THEN
                bd13GetNode (current, rightmost_leaf, plmNoLock_ebd00, nr_for_update, lnptr);
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30new_tree (VAR fi : tbd_fileinfo;
            VAR current   : tbd_current_tree);
 
VAR
      nptr       : tbd_node_ptrs;
      aux_error  : tgg00_BasisError;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL;
    b13new_root (nptr, current);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        fi.fi_root    := np_ptr^.nd_id;
        fileRoot_gg00 := np_ptr^.nd_id;
        IF  (fileTabId_gg00 = cgg_sys1_catalog_id) OR
            (fileTabId_gg00 = cgg_sys2_catalog_id)
        THEN
            BEGIN
            np_ptr^.nd_pmode   := np_ptr^.nd_pmode + [pmCatalog_egg00];
            np_ptr^.nd_trailer := np_ptr^.nd_header
            END;
        (*ENDIF*) 
        np_ptr^.nd_file_state := fi.fi_state;
        bd300SetRootCheck (curr_tree_id);
&       ifdef trace
        t01int4 (bi, '30n_root_che', fileRootCheck_gg00);
&       endif
        (* PTS 115274 TS 2000-01-03 *)
        (* IF  g04inv_tfn (fileTfn_gg00)  PTS 1104446 TS 1999-11-10  *)
        (* THEN *)
        (*    b13r_release_node (nptr, current, lru_normal) *)
        (* ELSE *)
        IF  (trError_gg00 <> e_ok) AND (ftsObject_egg00 IN fileType_gg00)
        THEN
            BEGIN
            aux_error    := trError_gg00;
            trError_gg00 := e_ok;
            b13pfree_pno (fileRoot_gg00, current);
            IF  trError_gg00 = e_ok
            THEN
                trError_gg00 := aux_error
            (*ENDIF*) 
            END
        ELSE
            b13w_release_node (nptr, current)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30next_from_tree (VAR rk : tgg00_Lkey;
            inclusive    : boolean;
            VAR tree_pos : tgg00_FilePos;
            VAR b        : tgg00_Rec;
            VAR current  : tbd_current_tree);
 
VAR
      result          : tbd_searchresult;
      index           : integer;
      leaf            : tsp00_PageNo;
      nptr            : tbd_node_ptrs;
      neighbs         : tbd_neighbors;
      dumm_estimation : tsp00_Int4;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL;
    IF  tree_pos.tpsPno_gg00 = NIL_PAGE_NO_GG00
    THEN
        BEGIN
        b30search_record (rk.keyVal_gg00, rk.keyLen_gg00, r_lock_leaf, nr_for_read,
              dumm_estimation,
              dumm_estimation, nptr, index, neighbs, result, current);
        IF  (trError_gg00 = e_ok) AND (result = nonefound)
        THEN
            trError_gg00 := e_no_next_record
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        bd13GetNode (current, tree_pos.tpsPno_gg00, plmNoLock_ebd00, nr_for_read, nptr);
        index  := tree_pos.tpsIndex_gg00;
        result := thisfound
        END;
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok      ) AND
        (result <> nextfound) AND
        (NOT inclusive OR (result = lastfound))
    THEN
        b31next_search (RELEASE_FRAME_BD00, nptr, index, current);
    (*might return b_no_next_record*)
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        leaf := np_ptr^.nd_id;
        b31get_from_leaf (nptr, index, fileTabId_gg00 = cgg_sys1_catalog_id, b, current)
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  ftsTemp_egg00 in fileType_gg00
        THEN
            WITH tree_pos DO
                BEGIN
                tpsIndex_gg00 := index;
                tpsPno_gg00   := leaf
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
        IF  result <> thisfound
        THEN
            trError_gg00 := e_key_not_found
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    CASE curr_lockstate OF
        r_lock_leaf  :
            b75luread_unlock_leaf (current, curr_node_locked);
        r_lock_index :
            b75iuread_unlock_index (current, curr_lvl_1_locked);
        OTHERWISE
            ;
        END
    (*ENDCASE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30prev_from_tree (VAR rk : tgg00_Lkey;
            inclusive    : boolean;
            VAR tree_pos : tgg00_FilePos;
            VAR b        : tgg00_Rec;
            VAR current  : tbd_current_tree);
 
VAR
      result          : tbd_searchresult;
      index           : integer;
      leaf            : tsp00_PageNo;
      nptr            : tbd_node_ptrs;
      neighbs         : tbd_neighbors;
      dumm_estimation : tsp00_Int4;
      dummy_leaf      : tsp00_PageNo;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL;
    IF  tree_pos.tpsPno_gg00 = NIL_PAGE_NO_GG00
    THEN
        BEGIN
        b30search_record (rk.keyVal_gg00, rk.keyLen_gg00, r_lock_leaf, nr_for_read,
              dumm_estimation,
              dumm_estimation, nptr, index, neighbs, result, current);
        IF  (trError_gg00 = e_ok) AND (result = nonefound)
        THEN
            trError_gg00 := e_no_prev_record
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        bd13GetNode (current, tree_pos.tpsPno_gg00, plmNoLock_ebd00, nr_for_read, nptr);
        index  := tree_pos.tpsIndex_gg00;
        result := thisfound
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  (result <> lastfound) AND
            (NOT inclusive OR (result <> thisfound))
        THEN
            IF  ftsTemp_egg00 in fileType_gg00
            THEN
                b31t_prev_temp_search (nptr, index, current)
            ELSE
                b31prev_search (rk.keyVal_gg00, rk.keyLen_gg00, nptr, index, dummy_leaf, current);
            (*ENDIF*) 
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            leaf := np_ptr^.nd_id;
            b31get_from_leaf (nptr, index, fileTabId_gg00 = cgg_sys1_catalog_id,
                  b, current)
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  ftsTemp_egg00 in fileType_gg00
            THEN
                WITH tree_pos DO
                    BEGIN
                    tpsIndex_gg00 := index;
                    tpsPno_gg00   := leaf
                    END;
                (*ENDWITH*) 
            (*ENDIF*) 
            IF  (result <> thisfound) AND (trError_gg00 = e_ok)
            THEN
                trError_gg00 := e_key_not_found
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    IF  curr_lockstate = r_lock_leaf
    THEN
        b75luread_unlock_leaf(current, curr_node_locked)
    ELSE
        IF  curr_lockstate = r_lock_index
        THEN
            b75iuread_unlock_index (current, curr_lvl_1_locked)
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30range_exi_rec (
            VAR rk_the_one : tgg00_Lkey;
            VAR rk_another : tgg00_Lkey;
            VAR left___pages : tsp00_Int4;
            VAR middle_pages : tsp00_Int4;
            VAR right__pages : tsp00_Int4;
            VAR current    : tbd_current_tree);
 
VAR
      result     : tbd_searchresult;
      index      : integer;
      nptr       : tbd_node_ptrs;
      neighbs    : tbd_neighbors;
      left_other : tsp00_Int4;
      rightother : tsp00_Int4;
      dummy_leaf : tsp00_PageNo;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL;
    b30search_record
          (rk_the_one.keyVal_gg00, rk_the_one.keyLen_gg00, r_lock_leaf, nr_for_read,
          left___pages,
          right__pages, nptr, index, neighbs, result, current);
    middle_pages := -1;
&   ifdef TRACE
    t01int4 (bi, 'B30RANGE_EX1', ord(result));
&   endif
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  @rk_the_one = @rk_another
        THEN
            BEGIN
            IF  result <> thisfound
            THEN
                trError_gg00 := e_key_not_found
            (*ENDIF*) 
            END
        ELSE
            CASE result OF
                nonefound:
                    trError_gg00 := e_no_next_record;
                lastfound:
                    BEGIN
                    IF  np_ptr^.nd_right = NIL_PAGE_NO_GG00
                    THEN
                        trError_gg00 := e_no_next_record;
                    (*ENDIF*) 
                    IF  ((rk_the_one.len <> 0               ) OR
                        ( rk_another.len <> MAX_KEYLEN_GG00  ) OR
                        ( rk_another.k   <> b01fullkey      )   )
                    THEN
                        b31get_key_from_leaf (nptr, index,
                              rk_the_one, current);
                    (*ENDIF*) 
                    END;
                thisfound:
                    b31next_search (RELEASE_FRAME_BD00, nptr, index,
                          current)
                          (*might return e_no_next_record*);
                nextfound:
                    IF  (index - 1 >= 0) AND
                        ((rk_the_one.len <> 0               ) OR
                        ( rk_another.len <> MAX_KEYLEN_GG00  ) OR
                        ( rk_another.k   <> b01fullkey      )   )
                    THEN
                        b31get_key_from_leaf (nptr, index - 1,
                              rk_the_one, current);
                    (*ENDIF*) 
                OTHERWISE
                END;
            (*ENDCASE*) 
        (*ENDIF*) 
        IF  nptr.np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  (@rk_the_one <> @rk_another)
            AND
            (trError_gg00 = e_no_next_record)
            AND
            ((rk_the_one.len <> 0               ) OR
            ( rk_another.len <> MAX_KEYLEN_GG00  ) OR
            ( rk_another.k   <> b01fullkey      )   )
        THEN
            BEGIN
            trError_gg00 := e_ok;
            IF  curr_lockstate = r_lock_leaf
            THEN
                b75reset_lock (current, curr_node_locked);
            (*ENDIF*) 
            left_other := left___pages;
            b30search_record (rk_another.keyVal_gg00, rk_another.keyLen_gg00, r_lock_leaf,
                  nr_for_read,
                  left___pages, rightother, nptr, index,
                  neighbs, result, current);
            middle_pages := (rightother - right__pages
                  +          left_other - left___pages) DIV 2;
&           ifdef TRACE
            t01int4 (bi, 'B30RANGE_EX2', ord(result));
&           endif
            IF  trError_gg00 = e_ok
            THEN
                IF  (result = nextfound) OR (result = thisfound)
                THEN
                    IF  ftsTemp_egg00 in fileType_gg00
                    THEN
                        b31t_prev_temp_search (nptr, index, current)
                    ELSE
                        b31prev_search (rk_another.keyVal_gg00, rk_another.keyLen_gg00,
                              nptr, index, dummy_leaf, current)
                    (*ENDIF*) 
                ELSE
                    IF  result = nonefound
                    THEN
                        trError_gg00 := e_no_prev_record;
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDIF*) 
            IF  np_ptr <> NIL
            THEN
                b13r_release_node (nptr, current, lru_normal)
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END
    ELSE
        IF  np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
    (*ENDIF*) 
    CASE curr_lockstate OF
        r_lock_leaf  :
            b75luread_unlock_leaf (current, curr_node_locked);
        r_lock_index :
            b75iuread_unlock_index (current, curr_lvl_1_locked);
        OTHERWISE
            ;
        END
    (*ENDCASE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30release_tree (VAR current : tbd_current_tree;
            stringcol_cnt  : integer;
            varcol_cnt_off : integer;
            only_empty     : boolean);
 
VAR
      nptr : tbd_node_ptrs;
 
BEGIN
(*current.fileRoot_gg00 <> nil_page_no*)
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    np_ptr         := NIL;
    np_cbptr       := NIL;
    fileBdUse_gg00 := fileBdUse_gg00 + [bd_release_acc];
    IF  (fileRoot_gg00 = bd17GetFdirRoot) OR (fileRoot_gg00 = bd17GetLongFdirRoot)
    THEN
        trError_gg00 := e_do_not_drop_fdir;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        b50release_subtree (fileRoot_gg00, stringcol_cnt, varcol_cnt_off,
              only_empty, current);
    (*ENDIF*) 
    fileBdUse_gg00 := fileBdUse_gg00 - [bd_release_acc];
    IF  (trError_gg00 <> e_disk_not_accessible) AND
        (trError_gg00 <> e_do_not_drop_fdir   )
    THEN
        trError_gg00 := e_ok
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30repl_in_tree (VAR rk : tgg00_Lkey;
            VAR b       : tgg00_Rec;
            VAR current : tbd_current_tree);
 
VAR
      is_repl_save    : boolean;
      result          : tbd_searchresult;
      lock_return     : tbd_lock_returncode;
      lock_type       : tbd_treelock;
      old_len         : ^tsp00_Int2;
      new_len         : tsp00_Int2;
      diff            : tsp00_Int2;
      pos             : integer;
      index           : integer;
      leaf            : tsp00_PageNo;
      nptr            : tbd_node_ptrs;
      neighbs         : tbd_neighbors;
      subtree_info    : tbd_subtree_info;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr, subtree_info DO
    BEGIN
    np_ptr        := NIL;
    np_cbptr      := NIL;
    lock_return   := lock_okay;
    lock_type     := w_lock_leaf;
    is_repl_save  := true;
    sti_is_del_op := false;
    REPEAT
        bd30rsearch_record (rk, lock_type, nr_for_update,
              subtree_info, nptr, index, neighbs, result, current);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  result <> thisfound
            THEN
                trError_gg00 := e_key_not_found;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  (trError_gg00 <> e_ok              ) OR
            (curr_lockstate = no_bd_lock ) OR
            (curr_lockstate = w_lock_tree)
        THEN
            lock_return := lock_okay
        ELSE
            BEGIN
            WITH np_ptr^ DO
                BEGIN
                pos     := nd_pointer_list [MAX_POINTERINDEX_BD00 - index];
                old_len := @nd_body [pos];
                new_len := b.len;
                diff    := abs (old_len^ - new_len);
                IF  old_len^ <= new_len
                THEN
                    is_repl_save :=
                          ((nd_bottom + diff) <= MAX_BOTTOM_BD00 - (nd_record_cnt*POINTERSIZE_BD00))
                ELSE
                    is_repl_save :=
                          (
                          (nd_bottom - diff - BODY_BEG_BD00 +
                          ((nd_record_cnt)*POINTERSIZE_BD00))
                          >= HALF_COVERING_BD00
                          )
                          OR
                          (np_ptr^.nd_id = fileRoot_gg00)
                          OR
                          (ftsDynamic_egg00 IN fileType_gg00)
                (*ENDIF*) 
                END;
            (*ENDWITH*) 
            IF  is_repl_save
            THEN
                lock_return := lock_okay
            ELSE
                BEGIN
                (* *)
                (* OVERFLOW *)
                (* *)
                leaf := np_ptr^.nd_id;
                b13r_release_node (nptr, current, lru_normal);
                IF  (ftsDynamic_egg00 IN fileType_gg00) AND
                    NOT sti_index_overflow    AND
                    NOT sti_boundary          AND
                    g01glob.bd_subtree
                THEN
                    BEGIN
                    (* w_lock_leaf  -> w_lock_index *)
                    (* w_lock_index -> w_lock_index *)
                    IF  lock_type = w_lock_index
                    THEN
                        lock_return := lock_okay
                    ELSE
                        b75ilwrite_lock_index (current, leaf,
                              curr_lvl_1_locked, lock_return, 72)
                    (*ENDIF*) 
                    END
                ELSE
                    (* w_lock_leaf  -> w_lock_tree *)
                    (* w_lock_index -> w_lock_tree *)
                    b75tlwrite_lock_tree (current, leaf, lock_return, 71);
                (*ENDIF*) 
                lock_type := curr_lockstate;
                IF  lock_return = lock_okay
                THEN
                    BEGIN
                    IF  (sti_boundary                 ) AND
                        (curr_lockstate  = w_lock_tree) AND
                        (curr_left_bound = leaf       )
                    THEN
                        BEGIN
                        (* NOTE: neighbors are undefined!!    *)
                        (*       determine left neighbor      *)
                        (*       filetype is ftsDynamic_egg00 *)
                        lock_return := lock_dirty
                        END
                    ELSE
                        bd13GetNode (current, leaf, plmNoLock_ebd00, nr_for_update, nptr);
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN (* lock_dirty or lock_failed *)
                    IF  (lock_return = lock_dirty                ) AND
                        (
                        (curr_lockstate = w_lock_index           ) OR
                        ((curr_lockstate = w_lock_tree           ) AND
                        (NOT (ftsDynamic_egg00 IN fileType_gg00)))
                        )
                    THEN
                        BEGIN
                        bd13GetNode (current, leaf, plmNoLock_ebd00, nr_for_update, nptr);
                        IF  trError_gg00 = e_ok
                        THEN
                            b31search_entry (current, rk.keyVal_gg00, rk.keyLen_gg00, np_ptr,
                                  index, result);
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            IF  result <> thisfound
                            THEN
                                trError_gg00 := e_key_not_found;
                            (*ENDIF*) 
                        (*ENDIF*) 
                        lock_return := lock_okay
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
    UNTIL
        (lock_return = lock_okay) OR
        (trError_gg00 <> e_ok         );
    (*ENDREPEAT*) 
    IF  trError_gg00 = e_ok
    THEN
        b31repl_in_leaf (b, nptr, index, neighbs.ln, current);
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    CASE curr_lockstate OF
        w_lock_tree :
            b75tuwrite_unlock_tree (current);
        w_lock_leaf :
            b75luwrite_unlock_leaf (current, curr_node_locked);
        w_lock_index :
            b75iuwrite_unlock_index (current, curr_lvl_1_locked);
        r_lock_index :
            b75iuread_unlock_index (current, curr_lvl_1_locked);
        OTHERWISE
            ;
        END
    (*ENDCASE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30reset_bad_file (VAR current : tbd_current_tree;
            incl_root_upd : boolean;
            sub_state     : tbd_file_state_set);
 
VAR
      lock_return : tbd_lock_returncode;
 
BEGIN
lock_return := lock_okay;
WITH current, curr_trans^ DO
    BEGIN
    IF  (ftsConcurrent_egg00 in curr_tree_id.fileType_gg00) AND
        (curr_lockstate = no_bd_lock)
    THEN
        b75tldelete_lock_tree (current, c_ignore_svp, 160); (* PTS 1106058 TS 2000-03-28 *)
    (*ENDIF*) 
    IF  incl_root_upd
    THEN
        b30sub_filestate (current, sub_state);
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        b17fsub_file_state (current, sub_state);
    (*ENDIF*) 
    IF  curr_lockstate = d_lock_tree
    THEN
        b75tudelete_unlock_tree (current);
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg, csp3_n_btree,
              'RESET BAD FLAG FOR ROOT ', curr_tree_id.fileRoot_gg00);
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30save_quick (VAR pno : tsp00_PageNo;
            VAR nptr    : tbd_node_ptrs;
            VAR current : tbd_current_tree);
 
VAR
      single : boolean;
 
BEGIN
WITH current, curr_trans^, nptr DO
    BEGIN
    IF  pno = curr_tree_id.fileRoot_gg00
    THEN
        BEGIN
        b50first_leaf (pno, r_lock_tree, single, current);
        IF  trError_gg00 = e_ok
        THEN
            bd13GetNode (current, pno, plmNoLock_ebd00, nr_for_read, nptr);
&       ifdef trace
        (*ENDIF*) 
        t01int4 (bi, 'act_pno=    ', pno);
        IF  np_ptr <> NIL
        THEN
            t01page (bi, np_ptr^, 1, 300);
&       endif
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  np_ptr = NIL
        THEN
            BEGIN
            IF  pno <> NIL_PAGE_NO_GG00
            THEN
                bd13GetNode (current, pno, plmNoLock_ebd00, nr_for_read, nptr);
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            b13r_release_node (nptr, current, lru_last);
            IF  pno <> NIL_PAGE_NO_GG00
            THEN
                bd13GetNode (current, pno, plmNoLock_ebd00, nr_for_read, nptr);
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  np_ptr <> NIL
    THEN
        IF  trError_gg00 = e_ok
        THEN
            pno := np_ptr^.nd_right
        ELSE
            b13r_release_node (nptr, current, lru_normal)
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30search_record (
            VAR RecKey          : tsp00_Key;
            RecKeyLen           : tsp00_Int4;
            lock_type           : tbd_treelock;
            node_req            : tbd_node_request;
            VAR left_estimation : tsp00_Int4;
            VAR rightestimation : tsp00_Int4;
            VAR nptr            : tbd_node_ptrs;
            VAR index           : integer;
            VAR neighbs         : tbd_neighbors;
            VAR result          : tbd_searchresult;
            VAR current         : tbd_current_tree);
 
VAR
      l_type    : tbd_treelock;
      index_pno : tsp00_PageNo;
      sub_info  : tbd_subtree_info;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    IF  curr_lockstate = no_bd_lock
    THEN
        l_type := no_bd_lock
    ELSE
        l_type := lock_type;
    (*ENDIF*) 
    sub_info.sti_is_del_op := false;
    b50find_leaf (RecKey, RecKeyLen, l_type, node_req, sub_info, left_estimation,
          rightestimation, index_pno, nptr, neighbs, current);
    IF  trError_gg00 = e_ok
    THEN
        b31search_entry (current, RecKey, RecKeyLen, nptr.np_ptr, index, result)
    (*ENDIF*) 
    END;
(*ENDWITH*) 
&ifdef TRACE
t01int4 (bd_index, 'index       ', index);
t01int4 (bd_index, 'result      ', ord(result));
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30rsearch_record (VAR reckey : tgg00_Lkey;
            lock_type        : tbd_treelock;
            node_req         : tbd_node_request;
            VAR subtree_info : tbd_subtree_info;
            VAR nptr         : tbd_node_ptrs;
            VAR index        : integer;
            VAR neighbs      : tbd_neighbors;
            VAR result       : tbd_searchresult;
            VAR current      : tbd_current_tree);
 
VAR
      l_type    : tbd_treelock;
      index_pno : tsp00_PageNo;
      dummy     : tsp00_Int4;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    IF  curr_lockstate = no_bd_lock
    THEN
        l_type := no_bd_lock
    ELSE
        l_type := lock_type;
    (*ENDIF*) 
    b50find_leaf (reckey.keyVal_gg00, reckey.keyLen_gg00, l_type, node_req, subtree_info,
          dummy, dummy, index_pno, nptr, neighbs, current);
    IF  trError_gg00 = e_ok
    THEN
        b31search_entry (current, reckey.keyVal_gg00, reckey.keyLen_gg00, nptr.np_ptr,
              index, result)
    (*ENDIF*) 
    END;
(*ENDWITH*) 
&ifdef TRACE
t01p2int4 (bd_index, 'index       ', index,
      'result      ', ord(result));
t01p2int4 (bd_index, 'left_neighbo', neighbs.ln,
      'right_neighb', neighbs.rn);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30set_fileversion (VAR current : tbd_current_tree;
            new_fileversion : tgg91_FileVersion);
 
VAR
      nptr : tbd_node_ptrs;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00, nr_for_update, nptr);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        np_ptr^.nd_file_version := new_fileversion;
        b13w_release_node (nptr, current)
        END
    ELSE
        IF  nptr.np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal)
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30set_read_only (VAR current : tbd_current_tree);
 
VAR
      len     : integer;
      id_pos  : integer;
      n       : tsp00_Name;
      msg     : tsp00_C40;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    trError_gg00 := e_ok;
    IF  (ftsConcurrent_egg00 in curr_tree_id.fileType_gg00) AND
        (curr_lockstate = no_bd_lock            )
    THEN
        b75tldelete_lock_tree (current, c_ignore_svp, 83); (* PTS 1106058 TS 2000-03-28 *)
    (*ENDIF*) 
    b17fadd_file_state (current, [f_read_only]);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        curr_tree_id.fileBdUse_gg00 := curr_tree_id.fileBdUse_gg00 - [bd_write_acc];
        b30add_filestate (current, [f_read_only]);
        curr_tree_id.fileBdUse_gg00 := curr_tree_id.fileBdUse_gg00 + [bd_write_acc];
        n   := 'SET READ ONLY:    ';
        msg := bsp_c40;
        len := 0;
        g17nameto_line (n, len, msg);
        len := len + 1;
        FOR id_pos := 1 TO 10 DO
            BEGIN
            g17hexto_line (curr_tree_id.fileName_gg00 [id_pos], len, msg);
            IF  id_pos = 2
            THEN
                len := len + 1;
            (*ENDIF*) 
            END;
        (*ENDFOR*) 
        vmessage (sp3p_knldiag, sp3m_info, csp3_b30_1_set_read_only,
              csp3_n_btree, msg)
        END;
    (*ENDIF*) 
    IF  current.curr_lockstate = d_lock_tree
    THEN
        b75tudelete_unlock_tree (current)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30treeleafnodes (VAR current : tbd_current_tree;
            node_req          : tbd_node_request;
            VAR old_leafnodes : tsp00_Int4);
 
VAR
      lock_return   : tbd_lock_returncode;
      new_leafnodes : tsp00_Int4;
      nptr          : tbd_node_ptrs;
 
BEGIN
WITH current, curr_tree_id DO
    IF  node_req = nr_for_update
    THEN
        BEGIN
        new_leafnodes      := fileLeafNodes_gg00;
        fileLeafNodes_gg00 := cgg_nil_leafnodes;
        bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00, nr_for_update, nptr);
        END
    ELSE
        IF  curr_lockstate = r_lock_tree
        THEN
            IF  (ftsDynamic_egg00 IN fileType_gg00) AND
                (NOT g04inv_tfn (fileTfn_gg00)    ) AND
                g01glob.bd_subtree
            THEN
                bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00,
                      nr_ret_if_leaf_or_first_index, nptr)
            ELSE
                bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00,
                      nr_return_if_leaf, nptr)
            (*ENDIF*) 
        ELSE
            bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00, nr_for_read, nptr);
        (*ENDIF*) 
    (*ENDIF*) 
(*ENDWITH*) 
IF  (current.curr_trans^.trError_gg00 = e_root_is_leaf       ) OR
    (current.curr_trans^.trError_gg00 = e_root_is_first_index)
THEN
    WITH current, curr_tree_id, curr_trans^ DO
        BEGIN
        lock_return := lock_okay;
        IF  (ftsDynamic_egg00 IN current.curr_tree_id.fileType_gg00) AND
            (NOT g04inv_tfn (fileTfn_gg00)                         ) AND
            g01glob.bd_subtree
        THEN
            b75ilread_lock_index (current, fileRoot_gg00, 85);
        (*ENDIF*) 
        IF  trError_gg00 = e_root_is_leaf
        THEN
            b75llread_lock_leaf (current, fileRoot_gg00, 84);
        (*ENDIF*) 
        trError_gg00 := e_ok;
        bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00, nr_for_read, nptr);
        END;
    (*ENDWITH*) 
(*ENDIF*) 
IF  current.curr_trans^.trError_gg00 = e_ok
THEN
    BEGIN
    old_leafnodes := nptr.np_ptr^.ndTreeLeaves_bd00;
    IF  node_req = nr_for_update
    THEN
        BEGIN
&       ifdef TRACE
        t01int4 (bi, 'new treeleaf', new_leafnodes);
&       endif
        nptr.np_ptr^.ndTreeLeaves_bd00 := new_leafnodes;
        b13w_release_node (nptr, current)
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  nptr.np_ptr <> NIL
THEN
    b13r_release_node (nptr, current, lru_normal);
(*ENDIF*) 
IF  current.curr_lockstate = r_lock_index
THEN
    b75iuread_unlock_index (current, current.curr_lvl_1_locked)
ELSE
    IF  current.curr_lockstate = r_lock_leaf
    THEN
        b75luread_unlock_leaf (current, current.curr_node_locked);
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30sub_filestate (VAR current : tbd_current_tree;
            filestate : tbd_file_state_set);
 
VAR
      nptr : tbd_node_ptrs;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00, nr_for_update, nptr);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        np_ptr^.nd_file_state := np_ptr^.nd_file_state - filestate;
        b13w_release_node (nptr, current)
        END
    ELSE
        IF  nptr.np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal)
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30tadd_temp_primary (
            bCountDuplicates : boolean;
            VAR Rec          : tgg00_Rec;
            VAR current      : tbd_current_tree);
 
VAR
      result          : tbd_searchresult;
      index           : integer;
      DuplicateCnt    : tsp00_Int4;
      pRec            : tgg00_RecPtr;
      nptr            : tbd_node_ptrs;
      neighbs         : tbd_neighbors;
      dumm_estimation : tsp00_Int4;
 
BEGIN
WITH current, curr_trans^, nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL;
&   ifdef TRACE
    IF  bCountDuplicates
    THEN
        t01key( bi, 'TempRecKey  ', Rec.recKey_gg00);
&   endif
    (*ENDIF*) 
    b30search_record (Rec.recKey_gg00.keyVal_gg00, Rec.recKeyLen_gg00,
          no_bd_lock, nr_for_update, dumm_estimation, dumm_estimation, nptr,
          index, neighbs, result, current);
    IF  trError_gg00 = e_ok
    THEN
        WITH neighbs DO
            CASE result OF
                thisfound :
                    BEGIN
                    IF  bCountDuplicates
                    THEN
                        WITH np_ptr^ DO
                            BEGIN
                            pRec         := @nd_body [nd_pointer_list [MAX_POINTERINDEX_BD00 - index]];
                            DuplicateCnt := gg06PnoGet(pRec^.recPno_gg00);
                            IF  DuplicateCnt < MAX_INT4_SP00 -1
                            THEN
                                BEGIN
                                gg06PnoPut( pRec^.recPno_gg00, DuplicateCnt +1);
                                b13w_release_node (nptr, current);
                                END;
                            (*ENDIF*) 
                            END;
                        (*ENDWITH*) 
                    (*ENDIF*) 
                    trError_gg00 := e_duplicate_key;
                    END;
                nonefound :
                    b31add_to_leaf (Rec, nptr, FIRST_REC_INDEX_BD00, ln,
                          current);
                nextfound :
                    b31add_to_leaf (Rec, nptr, index, ln, current);
                lastfound :
                    b31append_to_leaf (Rec, nptr, index,
                          NINETY_PERCENT_COV_BD00, ln, current)
                END;
            (*ENDCASE*) 
        (*ENDWITH*) 
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b30verify_tree (VAR current : tbd_current_tree;
            conv_update   : boolean;
            VAR NumPages  : tsp00_Int4);
 
VAR
      dump_page   : boolean;
      bFileWasBad : boolean;
      bSetRootBad : boolean;
      nptrs       : tbd_node_ptrs;
 
BEGIN
WITH current, curr_trans^, curr_tree_id DO
    BEGIN
    trError_gg00   := e_ok;
    NumPages       := 0;
    dump_page      := false;
    bFileWasBad    := false;
    bSetRootBad    := false;
    nptrs.np_ptr   := NIL;
    nptrs.np_cbptr := NIL;
    IF  (fileRoot_gg00 <> b17permfdir_current.curr_tree_id.fileRoot_gg00)
        AND
        (fileRoot_gg00 <> b17strcolfdir_current.curr_tree_id.fileRoot_gg00)
    THEN
        b06file_opmsg (csp3_check_file, current);
    (*ENDIF*) 
    IF  curr_lockstate = r_lock_tree
    THEN
        b75tlselect_lock_tree (current, 149);
    (* *)
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00, nr_for_read, nptrs);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            bSetRootBad := true;
            bFileWasBad := (f_bad IN nptrs.np_ptr^.nd_file_state);
            END;
        (*ENDIF*) 
        IF  nptrs.np_ptr <> NIL
        THEN
            b13r_release_node (nptrs, current, lru_normal);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b50verify_subtree (current.curr_tree_id.fileRoot_gg00, NIL_PAGE_NO_GG00,
                  conv_update, dump_page, current, NumPages);
        (*ENDIF*) 
        END;
    (* *)
    (*ENDIF*) 
    IF  curr_lockstate = s_lock_tree
    THEN
        b75tuselect_unlock_tree (current);
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND bFileWasBad
    THEN
        b30reset_bad_file (current, c_incl_root_upd, [f_bad])
    ELSE
        IF  e_bad_datapage = trError_gg00
        THEN
            b30bad_file (current, bSetRootBad, NOT conv_update, [f_bad]);
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30AddToTree (
            VAR recKey  : tgg00_Lkey;
            VAR rec     : tgg00_Rec;
            VAR current : tbd_current_tree);
 
VAR
      bDoLockHandling  : boolean;
      bReadyForInsert  : boolean;
      searchResult     : tbd_searchresult;
      recIndex         : tsp00_Int4;
      leaf             : tsp00_PageNo;
      nptr             : tbd_node_ptrs;
      neighbs          : tbd_neighbors;
 
BEGIN
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    nptr.np_ptr     := NIL;
    nptr.np_cbptr   := NIL;
    bReadyForInsert := false;
    bDoLockHandling := ftsConcurrent_egg00 IN fileType_gg00;
    (* *)
    WHILE (trError_gg00 = e_ok) AND NOT bReadyForInsert DO
        BEGIN
        IF  nptr.np_ptr = NIL
        THEN
            bd50FindLeaf (recKey.keyVal_gg00, recKey.keyLen_gg00,
                  nptr, neighbs, current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            b31search_entry (current, recKey.keyVal_gg00, recKey.keyLen_gg00,
                  nptr.np_ptr, recIndex, searchResult);
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (searchResult = thisfound)
        THEN
            trError_gg00 := e_duplicate_key;
        (*ENDIF*) 
        bReadyForInsert := NOT bDoLockHandling;
        IF  (trError_gg00 = e_ok) AND bDoLockHandling
        THEN
            BEGIN
            IF  (
                nptr.np_ptr^.nd_bottom + rec.recLen_gg00 <=
                MAX_BOTTOM_BD00 - ((nptr.np_ptr^.nd_record_cnt+1)*POINTERSIZE_BD00)
                )
                AND
                (
                (nptr.np_ptr^.nd_bottom < NINETY_PERCENT_COV_BD00) OR
                (searchResult <> lastfound                       ) OR
                (nptr.np_ptr^.nd_right <> NIL_PAGE_NO_GG00       )
                )
            THEN
                bReadyForInsert := true (* local update possible *)
            ELSE
                BEGIN
                bDoLockHandling := false;
                b13r_release_node (nptr, current, lru_normal);
                IF  NOT bd50IndexNodeIsSaveForInsert (current, recIndex)
                THEN
                    bd30_LockTreeExclusive (current)
                ELSE
                    BEGIN (* level > LEAF_LEVEL_BD00 *)
                    bd30_LockSubTreeExclusive (current);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        bd50DetermineLeafNode (current, @recKey.keyVal_gg00,
                              recKey.keyLen_gg00, nptr.np_ptr, recIndex, leaf);
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            IF  bd50IndexNodeIsSaveForInsert (current, recIndex)
                            THEN
                                bd13GetNode (current, leaf, plmNoLock_ebd00, nr_for_update, nptr)
                            ELSE
                                bd30_LockTreeExclusive (current)
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        CASE searchResult OF
            nonefound :
                b31add_to_leaf (rec, nptr, FIRST_REC_INDEX_BD00, neighbs.ln, current);
            nextfound :
                b31add_to_leaf (rec, nptr, recIndex, neighbs.ln, current);
            lastfound :
                b31append_to_leaf (rec, nptr, recIndex, NINETY_PERCENT_COV_BD00,
                      neighbs.ln, current);
            OTHERWISE
                trError_gg00 := e_not_implemented
            END;
        (*ENDCASE*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30CreateBeforeImageForDelete (
            VAR m          : tgg00_MessBlock;
            pDeleteCmd     : tsp00_Addr;
            VAR rk         : tgg00_Lkey;
            VAR old_recbuf : tgg00_Rec;
            granted_lock   : tgg00_LockReqMode;
            VAR current    : tbd_current_tree);
 
VAR
      searchResult    : tbd_searchresult;
      recPos          : tsp00_Int4;
      index           : tsp00_Int4;
      nptr            : tbd_node_ptrs;
      pRec            : tgg00_RecPtr;
      neighbs         : tbd_neighbors;
      dummyEstimation : tsp00_Int4;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL;
    b30search_record (rk.keyVal_gg00, rk.keyLen_gg00, r_lock_leaf, nr_for_read,
          dummyEstimation, dummyEstimation, nptr, index, neighbs, searchResult, current);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  searchResult <> thisfound
        THEN
            trError_gg00 := e_key_not_found
        ELSE
            BEGIN
            recPos := np_ptr^.nd_pointer_list[ MAX_POINTERINDEX_BD00 - index ];
            pRec   := @np_ptr^.nd_body [ recPos ];
            g10mv2 ('VBD30 ',   3,    
                  sizeof (np_ptr^), sizeof (old_recbuf),
                  np_ptr^, recPos, old_recbuf, 1 , pRec^.recLen_gg00, trError_gg00);
            IF  trError_gg00 = e_move_error
            THEN
                BEGIN
                trError_gg00 := e_data_page_corrupted;
                b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, np_ptr^.nd_id, np_ptr,1)
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    CASE curr_lockstate OF
        r_lock_leaf  :
            b75luread_unlock_leaf (current, curr_node_locked);
        r_lock_index :
            b75iuread_unlock_index (current, curr_lvl_1_locked);
        OTHERWISE
            ;
        END;
    (*ENDCASE*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        k61bd_del (m, pDeleteCmd, old_recbuf, granted_lock);
        IF  fileTfn_gg00 = tfnTable_egg00
        THEN
            BEGIN
            b73cmd_count (ideletes_rows_read);
            b73cmd_count (ideletes_rows_del);
            END;
&       ifdef TRACE
        (*ENDIF*) 
        t01buf (bi, old_recbuf, 1, old_recbuf.recLen_gg00);
&       endif
        END;
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30CreateBeforeImageForInsert (
            VAR rk          : tgg00_Lkey;
            VAR b           : tgg00_Rec;
            VAR m           : tgg00_MessBlock;
            pInsertCmd      : tsp00_Addr;
            granted_lock    : tgg00_LockReqMode;
            VAR current     : tbd_current_tree);
 
VAR
      bCreateSysKey   : boolean;
      auxError        : tgg00_BasisError;
      searchResult    : tbd_searchresult;
      index           : tsp00_Int4;
      recPos          : tsp00_Int4;
      nptr            : tbd_node_ptrs;
      pRec            : tsp00_BufAddr;
      neighbs         : tbd_neighbors;
      keyTrace        : tgg11_BdKeyTrace;
      dummyEstimation : tsp00_Int4;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    np_ptr        := NIL;
    np_cbptr      := NIL;
    bCreateSysKey := (m.mb_type2 = mm_nokey) AND (ftsPerm_egg00 in fileType_gg00);
    IF  bCreateSysKey
    THEN
        BEGIN (* prepare search for greatest key *)
        rk.keyLen_gg00      := 1;
        rk.keyVal_gg00[ 1 ] := csp_undef_byte
        END;
    (*ENDIF*) 
    b30search_record (rk.keyVal_gg00, rk.keyLen_gg00, r_lock_leaf, nr_for_read,
          dummyEstimation, dummyEstimation, nptr, index, neighbs, searchResult, current);
    IF  (trError_gg00 = e_ok) AND (searchResult = thisfound)
    THEN
        BEGIN
        IF  m.mb_type2 <> mm_compare_record
        THEN
            trError_gg00 := e_duplicate_key
        ELSE
            BEGIN
            recPos := np_ptr^.nd_pointer_list[ MAX_POINTERINDEX_BD00 - index ];
            pRec   := @np_ptr^.nd_body[ recPos ];
            bd30compare_record (m, pRec, 1)
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND bCreateSysKey
    THEN
        BEGIN
        IF  searchResult = nonefound
        THEN
            BEGIN
            b.recBody_gg00 [1] := csp_defined_byte;
            g10fil ('VBD30 ',   4,    
                  sizeof (tgg00_RecBody), b.recBody_gg00, 2,
                  sizeof (tgg00_Surrogate), chr (0), trError_gg00)
            END
        ELSE
            BEGIN
            recPos := np_ptr^.nd_pointer_list[ MAX_POINTERINDEX_BD00 - index ];
            g10mv2 ('VBD30 ',   5,    
                  sizeof (np_ptr^), sizeof (b), np_ptr^, recPos + cgg_rec_key_offset,
                  b, 1 + cgg_rec_key_offset, sizeof (tgg00_Surrogate) + 1, 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)
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        b.recKeyLen_gg00 := SURROGATE_MXGG00 + 1;
        END;
    (*ENDIF*) 
    IF  np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    CASE curr_lockstate OF
        r_lock_leaf  :
            b75luread_unlock_leaf (current, curr_node_locked);
        r_lock_index :
            b75iuread_unlock_index (current, curr_lvl_1_locked);
        OTHERWISE
            ;
        END;
    (*ENDCASE*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        (* *)
        k61bd_ins (m, pInsertCmd, b, granted_lock);
        (* *)
        IF  fileTfn_gg00 = tfnTable_egg00
        THEN
            b73cmd_count (iinserts_rows);
        (*ENDIF*) 
        IF  bCreateSysKey AND (g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdPrim_gg00)
        THEN
            BEGIN
            auxError                := e_ok;
            keyTrace.bdkTrType_gg11 := bdtrKey_egg11;
            keyTrace.bdkKeyLen_gg11 := b.recKeyLen_gg00;
            g10mv4 ('VBD30 ',   6,    
                  b.recKeyLen_gg00, sizeof (keyTrace.bdkKey_gg11),
                  b.recKey_gg00.keyVal_gg00, 1, keyTrace.bdkKey_gg11, 1,
                  gg06Min( b.recKeyLen_gg00, sizeof( tgg00_VtraceKey )), auxError);
            b120InsertTrace (m.mb_trns^, bd, b02logadd, sizeof (keyTrace), @keyTrace)
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30CreateBeforeImageForUpdate (
            VAR m              : tgg00_MessBlock;
            pUpdateCmd         : tsp00_Addr;
            VAR rk             : tgg00_Lkey;
            VAR old_recbuf     : tgg00_Rec;
            VAR new_recbuf     : tgg00_Rec;
            granted_lock       : tgg00_LockReqMode;
            VAR current        : tbd_current_tree);
 
VAR
      searchResult    : tbd_searchresult;
      recPos          : tsp00_Int4;
      index           : tsp00_Int4;
      pRec            : tgg00_RecPtr;
      nptr            : tbd_node_ptrs;
      neighbs         : tbd_neighbors;
      dummyEstimation : tsp00_Int4;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL;
    b30search_record (rk.keyVal_gg00, rk.keyLen_gg00, r_lock_leaf, nr_for_read,
          dummyEstimation, dummyEstimation, nptr, index, neighbs, searchResult, current);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  searchResult <> thisfound
        THEN
            trError_gg00 := e_key_not_found
        ELSE
            BEGIN
            recPos := np_ptr^.nd_pointer_list[ MAX_POINTERINDEX_BD00 - index ];
            pRec   := @np_ptr^.nd_body[ recPos ];
            g10mv2 ('VBD30 ',   7,    
                  sizeof (np_ptr^), sizeof (old_recbuf),
                  np_ptr^, recPos,  old_recbuf, 1, pRec^.recLen_gg00, trError_gg00);
            IF  trError_gg00 = e_move_error
            THEN
                BEGIN
                trError_gg00 := e_data_page_corrupted;
                b06dump_bad_page (trTaskId_gg00, 'd', FILE_EXT_COR_BD00, np_ptr^.nd_id, np_ptr,1)
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    CASE curr_lockstate OF
        r_lock_leaf  :
            b75luread_unlock_leaf (current, curr_node_locked);
        r_lock_index :
            b75iuread_unlock_index (current, curr_lvl_1_locked);
        OTHERWISE
            ;
        END;
    (*ENDCASE*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        k63bd_upd (m, pUpdateCmd, old_recbuf, new_recbuf, granted_lock);
        IF  fileTfn_gg00 = tfnTable_egg00
        THEN
            BEGIN
            b73cmd_count (iupdates_rows_read);
            b73cmd_count (iupdates_rows_upd)
            END;
&       ifdef TRACE
        (*ENDIF*) 
        t01buf (bi, old_recbuf, 1, old_recbuf.len);
        t01buf (bi, new_recbuf, 1, new_recbuf.len);
&       endif
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30CreateCoordinator (VAR t : tgg00_TransContext;
            VAR FileId : tgg00_FileId;
            MessType   : tgg00_MessType);
 
VAR
      SendMBlock : tgg00_MessBlock;
      SendTrans  : tgg00_TransChild;
 
BEGIN
(* *)
(* MessType = m_column     => Read Ahead For Blobs     *)
(* MessType = m_get_object => Read Ahead For OMS Pages *)
(* *)
k53child_trans_build (MessType, t.trTaskId_gg00, SendTrans);
g01mblock_init (t, MessType, mm_coordinator, SendMBlock);
WITH SendMBlock DO
    BEGIN
    CASE MessType OF
        m_column :
            BEGIN
            mb_struct    := mbs_buf;
            mb_qual      := @FileId;
            mb_qual_size := sizeof (FileId);
            mb_qual_len  := sizeof (FileId)
            END;
        OTHERWISE :
            ;
        END;
    (*ENDCASE*) 
    mb_reply := false
    END;
(*ENDWITH*) 
(*-=-=-=-=-=-=-=-=-=-=-=-=-=-*)
k90send (SendMBlock, SendTrans);
(*-=-=-=-=-=-=-=-=-=-=-=-=-=-*)
IF  t.trError_gg00 = e_too_many_net_requests
THEN
    t.trError_gg00 := e_ok
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30GetTree (
            VAR trans      : tgg00_TransContext;
            VAR fileId     : tgg00_FileId;
            VAR current    : tbd_current_tree;
            bTreeExclusive : boolean;
            messType       : tgg00_MessType);
 
VAR
      bStopLoop  : boolean;
      bForDrop   : boolean;
      bForUpdate : boolean;
      fileInfo   : tbd_fileinfo;
 
BEGIN
bStopLoop           := false;
bForDrop            := bd_release_acc IN fileId.fileBdUse_gg00;
bForUpdate          := bd_write_acc IN fileId.fileBdUse_gg00;
bd01SetToNilCurrent (current);
current.curr_trans  := @trans;
current.curr_action := messType;
WITH trans DO
    BEGIN
    IF  fileId.fileRoot_gg00 <> NIL_PAGE_NO_GG00
    THEN
        BEGIN
&       if $KIND = SLOW or $KIND = QUICK
        IF  (fileId.fileRoot_gg00 = bd17GetFdirRoot    ) OR
            (fileId.fileRoot_gg00 = bd17GetLongFdirRoot)
        THEN
            trError_gg00 := e_do_not_access_fdir;
&       endif
        (*ENDIF*) 
        IF  fileId.fileRootCheck_gg00 <> ROOT_CHECK_GG00
        THEN
            bd300FileIdRootCheck (fileId, trError_gg00)
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        b17get_fdir (fileId.fileName_gg00, fileInfo,
              ftsShared_egg00 IN fileId.fileType_gg00, trans);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            b30fdir_to_treeid (fileInfo, fileId);
            IF  ftsConcurrent_egg00 IN fileInfo.fi_type
            THEN
                BEGIN
                IF  (fileId.fileVersion_gg00          <> fileInfo.fi_vers      ) AND
                    (fileId.fileVersion_gg00.ci2_gg00 <> cgg_dummy_file_version)
                THEN
                    trError_gg00 := e_old_fileversion
                ELSE
                    IF  bForUpdate
                    THEN
                        IF  f_bad IN fileInfo.fi_state
                        THEN
                            trError_gg00 := e_bad_file
                        ELSE
                            IF  (f_write_off IN fileInfo.fi_state)
                                OR
                                (
                                (f_read_only IN fileInfo.fi_state               ) AND
                                (NOT (bd_load_nolog IN fileId.fileBdUse_gg00   )) AND
                                (NOT (hsNoLog_egg00 IN fileId.fileHandling_gg00))
                                )
                            THEN
                                trError_gg00 := e_file_read_only
                            ELSE
                                IF  (hsNoLog_egg00 IN fileId.fileHandling_gg00               ) AND
                                    (NOT (hsIgnoreReadOnly_egg00 IN fileId.fileHandling_gg00)) AND
                                    (NOT(f_read_only IN fileInfo.fi_state))
                                THEN
                                    b30set_read_only (current)
                                (*ENDIF*) 
                            (*ENDIF*) 
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    WHILE  (trError_gg00 = e_ok) AND NOT bStopLoop DO
        WITH current DO
            BEGIN
            curr_tree_id := fileId;
            IF  bTreeExclusive
            THEN
                IF  (ftsConcurrent_egg00 IN fileInfo.fi_type) AND NOT bForDrop
                THEN
                    bd13GetNode (current, fileId.fileRoot_gg00, plmLockForSplit_ebd00,
                          nr_for_update, currRootNptrs_bd00)
                ELSE
                    bd13GetNode (current, fileId.fileRoot_gg00, plmLock_ebd00,
                          nr_for_update, currRootNptrs_bd00)
                (*ENDIF*) 
            ELSE
                BEGIN
                bd13GetNode (current, fileId.fileRoot_gg00, plmLock_ebd00,
                      nr_for_read, currRootNptrs_bd00);
                IF  (trError_gg00 = e_ok) AND bForUpdate AND
                    (LEAF_LEVEL_BD00 = currRootNptrs_bd00.np_ptr^.nd_level)
                THEN
                    BEGIN
                    bd30ReleaseTree (current);
                    bd13GetNode (current, fileId.fileRoot_gg00, plmLock_ebd00,
                          nr_for_update, currRootNptrs_bd00)
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_file_must_be_read_only
            THEN
                BEGIN
                trError_gg00 := e_ok;
                bd30ReleaseTree (current);
                b30set_read_only (current)
                END
            ELSE
                bStopLoop := true; (* common case *)
            (*ENDIF*) 
            END
        (*ENDWITH*) 
    (*ENDWHILE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30ReleaseTree (
            VAR current : tbd_current_tree); (* bTreeIsRemoved TODO *)
 
VAR
      auxRootNptrs : tbd_node_ptrs;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    bd30_ReleaseSubTree (current);
    IF  currRootNptrs_bd00.np_ptr <> NIL
    THEN
        BEGIN
        auxRootNptrs                := currRootNptrs_bd00;
        currRootNptrs_bd00.np_ptr   := NIL;
        currRootNptrs_bd00.np_cbptr := NIL;
        IF  (trError_gg00 = e_ok) AND currRootUpdated_bd00
        THEN
            BEGIN
            b13w_release_node (auxRootNptrs, current);
            currRootUpdated_bd00 := false;
            END
        ELSE
            b13r_release_node (auxRootNptrs, current, lru_normal)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 <> e_ok
    THEN
        bd06IllegalRootAccess (curr_trans^, curr_tree_id)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30_ReleaseSubTree(
            VAR current : tbd_current_tree);
 
VAR
      auxNptrs : tbd_node_ptrs;
 
BEGIN
WITH current, curr_trans^ DO
    BEGIN
    IF  currIndexNptrs_bd00.np_ptr <> NIL
    THEN
        BEGIN
        auxNptrs                     := currIndexNptrs_bd00;
        currIndexNptrs_bd00.np_ptr   := NIL;
        currIndexNptrs_bd00.np_cbptr := NIL;
        IF  (trError_gg00 = e_ok) AND currIndexUpdated_bd00
        THEN
            BEGIN
            b13w_release_node (auxNptrs, current);
            currIndexUpdated_bd00 := false;
            END
        ELSE
            b13r_release_node (auxNptrs, current, lru_normal)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30_LockTreeExclusive (
            VAR current : tbd_current_tree);
 
BEGIN
(* ftsConcurrent_egg00 IN fileType_gg00 only *)
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    IF  NOT bd20IsPageLocked (currRootNptrs_bd00.np_cbptr)
    THEN
        BEGIN
        bd30ReleaseTree (current);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  bd_release_acc IN fileBdUse_gg00
            THEN
                bd13GetNode (current, fileRoot_gg00, plmLock_ebd00,
                      nr_for_update, currRootNptrs_bd00)
            ELSE
                bd13GetNode (current, fileRoot_gg00, plmLockForSplit_ebd00,
                      nr_for_update, currRootNptrs_bd00)
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30_LockSubTreeExclusive (
            VAR current : tbd_current_tree);
 
VAR
      level   : tsp00_Int2;
      subRoot : tsp00_PageNo;
 
BEGIN
(* ftsConcurrent_egg00 IN fileType_gg00 only *)
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    level := currRootNptrs_bd00.np_ptr^.nd_level;
    IF  LEAF_LEVEL_BD00 = level
    THEN
        g01abort (csp3_bd_msg, csp3_n_btree, MSG_ROOT_IS_LEAF, fileRoot_gg00);
    (*ENDIF*) 
    IF  FIRST_INDEX_LEVEL_BD00 = level
    THEN
        bd30_LockTreeExclusive (current)
    ELSE
        BEGIN
        subRoot := currIndexNptrs_bd00.np_ptr^.nd_id;
        IF  NOT bd20IsPageLocked (currIndexNptrs_bd00.np_cbptr)
        THEN
            BEGIN
            bd30_ReleaseSubTree (current);
            IF  trError_gg00 = e_ok
            THEN
                bd13GetNode (current, subRoot, plmLock_ebd00,
                      nr_for_update, currRootNptrs_bd00)
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30OmsReadAheadCoordinator (VAR t : tgg00_TransContext;
            ReadAheadServer : integer);
 
VAR
      Finish          : boolean;
      RetryCnt        : integer;
      SendCnt         : integer;
      ErrorRoot       : tsp00_PageNo;
      FileId          : tgg00_FileId;
      FileInfo        : tbd_fileinfo;
 
BEGIN
RetryCnt            := 0;
SendCnt             := 0;
Finish              := false;
FileId              := b01niltree_id;
FileId.fileTfn_gg00 := tfnObj_egg00;
WITH t DO
    BEGIN
    WHILE ((trError_gg00 = e_ok) AND (NOT Finish))
          OR
          ((trError_gg00 = e_too_many_net_requests) AND (RetryCnt < c_max_retries))
          DO
        BEGIN
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            b17succ_fdir (FileId.fileName_gg00, FileId.fileName_gg00,
                  FileInfo, ftsShared_egg00 IN FileId.fileType_gg00, t,
                  NOT c_include_strcols);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  (FileId.fileTfn_gg00 <> tfnObj_egg00) OR  b01downfilesystem
                THEN
                    Finish := true
                ELSE
                    b30fdir_to_treeid (FileInfo, FileId)
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_file_not_found
            THEN
                BEGIN
                Finish       := true;
                trError_gg00 := e_ok
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  ((trError_gg00 = e_ok) OR (trError_gg00 = e_too_many_net_requests))
            AND
            (NOT Finish)
        THEN
            bd30_SendFileId (t, FileId, RetryCnt, SendCnt, m_get_object); (* PTS 1113635 FF *)
        (*ENDIF*) 
        IF  ((trError_gg00 = e_ok) AND (SendCnt = ReadAheadServer))
            OR
            ((Finish) AND (SendCnt > 0))
            OR
            ((trError_gg00 = e_too_many_net_requests) AND (SendCnt > 0))
        THEN
            bd30wait_for_reply (t, SendCnt, ErrorRoot, ReadAheadServer, Finish);
        (*ENDIF*) 
        IF  (NOT Finish) AND
            (
            (trError_gg00 = e_too_many_net_requests) AND
            (SendCnt      = 0                      ) AND
            (RetryCnt    >= c_max_retries          )
            )
        THEN
            BEGIN
            (* no server available *)
            trError_gg00 := e_ok;
            RetryCnt     := 0;
            bd04OmsReadAheadParticipant (t, FileId)
            END;
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (trRteCommPtr_gg00^.to_cancel)
        THEN
            trError_gg00 := e_cancelled
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  trError_gg00 <> e_ok
    THEN
        bd30discard_task (t, SendCnt)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30ObjFileCoordinator (VAR t : tgg00_TransContext;
            mtype           : tgg_message_type;    (* PTS 1113635 FF *)
            NumRepairServer : integer);
 
VAR
      Finish          : boolean;
      RetryCnt        : integer;
      SendCnt         : integer;
      ErrorRoot       : tsp00_PageNo;
      FileId          : tgg00_FileId;
      FileInfo        : tbd_fileinfo;
 
BEGIN
RetryCnt            := 0;
SendCnt             := 0;
Finish              := false;
FileId              := b01niltree_id;
FileId.fileTfn_gg00 := tfnObj_egg00;
WITH t DO
    BEGIN
    WHILE ((trError_gg00 = e_ok) AND (NOT Finish))
          OR
          ((trError_gg00 = e_too_many_net_requests) AND (RetryCnt < c_max_retries))
          DO
        BEGIN
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            b17succ_fdir (FileId.fileName_gg00, FileId.fileName_gg00,
                  FileInfo, ftsShared_egg00 IN FileId.fileType_gg00, t,
                  NOT c_include_strcols);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  (FileId.fileTfn_gg00 <> tfnObj_egg00) OR  b01downfilesystem
                THEN
                    Finish := true
                ELSE
                    b30fdir_to_treeid (FileInfo, FileId)
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_file_not_found
            THEN
                BEGIN
                Finish       := true;
                trError_gg00 := e_ok
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  ((trError_gg00 = e_ok) OR (trError_gg00 = e_too_many_net_requests))
            AND
            (NOT Finish)
        THEN
            bd30_SendFileId (t, FileId, RetryCnt, SendCnt, mtype);
        (*ENDIF*) 
        IF  ((trError_gg00 = e_ok) AND (SendCnt = NumRepairServer))
            OR
            ((Finish) AND (SendCnt > 0))
            OR
            ((trError_gg00 = e_too_many_net_requests) AND (SendCnt > 0))
        THEN
            bd30wait_for_reply (t, SendCnt, ErrorRoot, NumRepairServer, Finish);
        (*ENDIF*) 
        IF  (NOT Finish) AND
            (
            (trError_gg00 = e_too_many_net_requests) AND
            (SendCnt      = 0                      ) AND
            (RetryCnt    >= c_max_retries          )
            )
        THEN
            BEGIN
            (* no server available *)
            trError_gg00 := e_ok;
            RetryCnt     := 0;
            b01pverify_participant (t, FileId, false);
            END;
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (trRteCommPtr_gg00^.to_cancel)
        THEN
            trError_gg00 := e_cancelled
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  trError_gg00 <> e_ok
    THEN
        bd30discard_task (t, SendCnt)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30discard_task (VAR t : tgg00_TransContext;
            VAR send_cnt: integer);
 
VAR
      aux_err      : tgg00_BasisError;
      child_mblock : tgg00_MessBlock;
      child_trans  : tgg00_TransChild;
      child_qual   : tgg00_FileId;
 
BEGIN
&ifdef TRACE
(* fight against usecheck *)
child_qual := b01niltree_id;
&endif
aux_err        := t.trError_gg00;
t.trError_gg00 := e_ok;
WHILE (send_cnt > 0) AND (t.trError_gg00 = e_ok) DO
    BEGIN
    g01mblock_init (t, m_nil, mm_nil, child_mblock);
    WITH child_mblock DO
        BEGIN
        mb_qual      := @child_qual;
        mb_qual_size := sizeof (child_qual);
        mb_qual_len  := sizeof (child_qual)
        END;
    (*ENDWITH*) 
    (*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*)
    k90rcv_child (child_mblock, child_trans);
    (*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*)
    IF  t.trError_gg00 = e_ok
    THEN
        send_cnt := pred (send_cnt)
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
IF  t.trError_gg00 = e_ok
THEN
    t.trError_gg00 := aux_err
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30compare_record (VAR m : tgg00_MessBlock;
            rec_ptr : tsp00_BufAddr;
            pos     : integer);
 
VAR
      comp_result    : tsp00_LcompResult;
      col            : integer;
      col_pos_buf    : integer;
      col_len_buf    : integer;
      col_pos_node   : integer;
      col_len_node   : integer;
      old_varcol_pos : tgg00_VarColPosList;
      new_varcol_pos : tgg00_VarColPosList;
 
BEGIN
WITH m, mb_trns^ DO
    BEGIN
    comp_result              := l_equal;
    col                      := mb_qual^.mupd_pos;
    trError_gg00             := e_duplicate_record;
    old_varcol_pos.vpl_last  := -1;
    new_varcol_pos.vpl_last  := -1;
    WHILE (col < mb_qual^.mupd_pos + mb_qual^.mupd_cnt)
          AND (trError_gg00 = e_duplicate_record) DO
        BEGIN
        g04locate_col (mb_qual^.mst_addr^[ col ], @mb_data^.mbp_rec,
              new_varcol_pos, col_pos_buf, col_len_buf);
        g04locate_col (mb_qual^.mst_addr^[ col ], @rec_ptr^[pos],
              old_varcol_pos, col_pos_node, col_len_node);
        s30cmp (mb_data^.mbp_buf, col_pos_buf, col_len_buf,
              rec_ptr^, col_pos_node, col_len_node, comp_result);
        IF  comp_result <> l_equal
        THEN
            trError_gg00 := e_duplicate_key;
        (*ENDIF*) 
        col := col + 1
        END
    (*ENDWHILE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30wait_for_reply (VAR t : tgg00_TransContext;
            VAR send_cnt  : integer;
            VAR ErrorRoot : tsp00_PageNo;
            max_server    : integer;
            finish        : boolean);
 
VAR
      aux_err      : tgg00_BasisError;
      old_send_cnt : integer;
      child_mblock : tgg00_MessBlock;
      child_trans  : tgg00_TransChild;
      child_qual   : tgg00_FileId;
 
BEGIN
&ifdef TRACE
(* fight against usecheck *)
child_qual := b01niltree_id;
&endif
IF  t.trError_gg00 <> e_ok
THEN
    BEGIN
    (* *)
    (* trError_gg00 = e_too_many_net_requests *)
    (* *)
    aux_err  := t.trError_gg00;
    t.trError_gg00 := e_ok
    END
ELSE
    aux_err := e_ok;
(*ENDIF*) 
old_send_cnt := send_cnt;
WHILE (
      (t.trError_gg00 = e_ok                   ) AND
      ((send_cnt > 0) AND finish               ) OR
      ((send_cnt = max_server) AND (NOT finish))
      )
      OR
      (
      (aux_err = e_too_many_net_requests       ) AND
      (send_cnt = old_send_cnt                 )
      )
      DO
    BEGIN
    g01mblock_init (t, m_nil, mm_nil, child_mblock);
    WITH child_mblock DO
        BEGIN
        mb_qual      := @child_qual;
        mb_qual_size := sizeof (child_qual);
        mb_qual_len  := sizeof (child_qual)
        END;
    (*ENDWITH*) 
    (*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=*)
    k90rcv_child (child_mblock, child_trans);
    (*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=*)
    IF  t.trError_gg00 = e_ok
    THEN
        BEGIN
        send_cnt := pred (send_cnt);
        IF  child_trans.tcdError_gg00 <> e_ok
        THEN
            BEGIN
            t.trError_gg00 := child_trans.tcdError_gg00;
            (* PTS 1105359 TS 2000-01-17 *)
            ErrorRoot      := gg06TransGetInt4 (child_trans.tcdTransId_gg00);
            (* PTS 1105359 *)
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
IF  (t.trError_gg00 = e_ok) AND (aux_err <> e_ok)
THEN
    t.trError_gg00 := aux_err;
&ifdef TRACE
(*ENDIF*) 
t01basis_error (bi, 'bd30wait end', t.trError_gg00);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30_PnoCheckOpmsg (root : tsp00_PageNo;
            pno    : tsp00_PageNo;
            msg_no : tsp00_Int4;
            e      : tgg00_BasisError);
 
VAR
      len : integer;
      n   : tsp00_Name;
      msg : tsp00_C40;
 
BEGIN
msg := bsp_c40;
len := 0;
IF  msg_no = csp3_free_pno_check
THEN
    g17nameto_line ('FREE PNO CHECK:   ', len, msg)
ELSE
    BEGIN
    g17nameto_line ('BASIS_ERROR:      ', len, msg);
    len := len + 1;
    g17trimint4_to_line (e, len, msg);
    END;
(*ENDIF*) 
IF  msg_no = csp3_bd_save_check
THEN
    g01optextmsg (sp3p_console, sp3m_error, msg_no, csp3_n_save, msg)
ELSE
    g01optextmsg (sp3p_console, sp3m_error, msg_no, csp3_n_btree, msg);
(*ENDIF*) 
msg := bsp_c40;
len := 0;
g17trimint4_to_line (pno, len, msg);
len := len + 1;
msg [len] := '/';
g17trimint4_to_line (root, len, msg);
n   := ' (PNO/ROOT)       ';
g17nameto_line (n, len, msg);
IF  msg_no = csp3_bd_save_check
THEN
    g01optextmsg (sp3p_console, sp3m_error, msg_no, csp3_n_save, msg)
ELSE
    g01optextmsg (sp3p_console, sp3m_error, msg_no, csp3_n_btree, msg);
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd30_SendFileId (VAR t : tgg00_TransContext;
            VAR FileId   : tgg00_FileId;
            VAR RetryCnt : integer;
            VAR SendCnt  : integer;
            MessType     : tgg00_MessType);
 
VAR
      AuxError   : tgg00_BasisError;
      SendMBlock : tgg00_MessBlock;
      SendTrans  : tgg00_TransChild;
 
BEGIN
(* MessType = m_migrate_obj_files=> migrate < 7.4.02.03        *)
(* MessType = m_verify           => Warm And Cold Verify       *)
(* MessType = m_get_object       => Read Ahead For OMS Pages   *)
(* *)
WITH t DO
    BEGIN
    (* trError_gg00 = e_too_many_net_requests *)
    AuxError     := trError_gg00;
    trError_gg00 := e_ok;
    k53child_trans_build (MessType, FileId.fileRoot_gg00, SendTrans);
    g01mblock_init (t, MessType, mm_participant, SendMBlock);
    WITH SendMBlock DO
        BEGIN
        mb_struct    := mbs_buf;
        mb_qual      := @FileId;
        mb_qual_size := sizeof (FileId);
        mb_qual_len  := sizeof (FileId)
        END;
    (*ENDWITH*) 
    (*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*)
    k90send (SendMBlock, SendTrans);
    (*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*)
    IF  trError_gg00 = e_ok
    THEN
        SendCnt := succ (SendCnt)
    ELSE
        IF  trError_gg00 = e_too_many_net_requests
        THEN
            BEGIN
            RetryCnt := succ (RetryCnt);
            vsleep (trTaskId_gg00, 1)
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  (trError_gg00 = e_ok) AND (AuxError = e_too_many_net_requests)
    THEN
        BEGIN
        RetryCnt     := 0;
        trError_gg00 := e_ok
        END;
&   ifdef TRACE
    (*ENDIF*) 
    t01basis_error (bi, 'bd30_Send   ', trError_gg00);
&   endif
    END
(*ENDWITH*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
