.ad 8
.bm 8
.fm 4
.bt $Copyright (c) 2000-2004 SAP AG$$Page %$
.tm 12
.hm 6
.hs 3
.TT 1 $SQL$Project Distributed Database System$VBD05$
.tt 2 $$$
.TT 3 $JuergenP$filesysteminterface_5$$2000-10-26$
***********************************************************
.nf
 
 
    ========== licence begin  GPL
    Copyright (c) 2000-2004 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  : filesysteminterface_5
=========
.sp
Purpose : bytestring primitives
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        PROCEDURE
              b05copy_bytestr (VAR t : tgg00_TransContext;
                    VAR source_file : tgg00_FileId;
                    from_pos        : tsp00_Int4;
                    VAR target_file : tgg00_FileId;
                    to_pos          : tsp00_Int4;
                    length          : tsp00_Int4;
                    new_str_version : tsp00_Int4);
 
        PROCEDURE
              b05expand_bytestr (VAR t : tgg00_TransContext;
                    VAR file_id     : tgg00_FileId;
                    length          : tsp00_Int4;
                    fill_char       : char;
                    new_str_version : tsp00_Int4);
 
        PROCEDURE
              b05get_str_version  (VAR t : tgg00_TransContext;
                    VAR file_id     : tgg00_FileId;
                    VAR str_version : tsp00_Int4);
 
        PROCEDURE
              b05length_bytestr (VAR t : tgg00_TransContext;
                    VAR file_id     : tgg00_FileId;
                    VAR filelength  : tsp00_Int4;
                    VAR page_count  : tsp00_Int4;
                    VAR str_version : tsp00_Int4);
 
        PROCEDURE
              b05read_bytestr (VAR t : tgg00_TransContext;
                    VAR file_id : tgg00_FileId;
                    pos         : tsp00_Int4;
                    VAR length  : tsp00_Int4;
                    buf_size    : tsp00_Int4;
                    buf_addr    : tsp00_MoveObjPtr;
                    bufpos      : tsp00_Int4);
 
        PROCEDURE
              b05trunc_bytestr ( VAR t : tgg00_TransContext;
                    VAR file_id     : tgg00_FileId;
                    new_filelength  : tsp00_Int4;
                    new_str_version : tsp00_Int4);
 
        PROCEDURE
              b05write_bytestr(VAR t : tgg00_TransContext;
                    VAR file_id     : tgg00_FileId;
                    pos             : tsp00_Int4;
                    length          : tsp00_Int4;
                    buf_size        : tsp00_Int4;
                    buf_addr        : tsp00_MoveObjPtr     (*ptocSynonym const void**);
                    bufpos          : tsp00_Int4;
                    new_str_version : tsp00_Int4);
 
        PROCEDURE
              bd05Prefetch (
                    VAR trans    : tgg00_TransContext;
                    VAR fileId   : tgg00_FileId;
                    blobPosition : tsp00_Int4);
 
        PROCEDURE
              bd05ExtractBlob (
                    VAR trans        : tgg00_TransContext;
                    root             : tsp00_PageNo;
                    VAR hostFileName : tsp00_VFilename);
 
        PROCEDURE
              b05finish_load (
                    VAR t          : tgg00_TransContext;
                    VAR file_id    : tgg00_FileId;
                    rightmost_leaf : tsp00_PageNo);
 
        PROCEDURE
              b05load_string (VAR lnptr : tbd_node_ptrs;
                    VAR nptr     : tbd_node_ptrs;
                    VAR left_pno : tsp00_PageNo;
                    VAR current  : tbd_current_tree);
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
&       ifdef TRACE
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01int4 (layer : tgg00_Debug;
                    nam : tsp00_Sname;
                    l   : tsp00_Int4);
 
        PROCEDURE
              t01moveobj (layer : tgg00_Debug;
                    VAR b   : tsp00_MoveObj;
                    start_p : tsp00_Int4;
                    stop_p  : tsp00_Int4);
 
        PROCEDURE
              t01name (layer : tgg00_Debug;
                    nam : tsp00_Name);
 
        PROCEDURE
              t01p2int4 (debug : tgg00_Debug;
                    nam_1 : tsp00_Sname;
                    int_1 : tsp00_Int4;
                    nam_2 : tsp00_Sname;
                    int_2 : tsp00_Int4);
 
        PROCEDURE
              t01str30 (layer : tgg00_Debug;
                    str30 : tsp00_C30);
 
        PROCEDURE
              t01treeid (layer : tgg00_Debug;
                    nam        : tsp00_Sname;
                    VAR treeid : tgg00_FileId);
 
        PROCEDURE
              t01basis_error (layer : tgg00_Debug;
                    nam   : tsp00_Sname;
                    b_err : tgg00_BasisError);
&       endif
 
      ------------------------------ 
 
        FROM
              filesysteminterface_1 : VBD01;
 
        VAR
              b01downfilesystem : boolean;
              b01niltree_id     : 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
              b13free_node (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd13GetNode (VAR Current : tbd_current_tree;
                    Pno          : tsp00_PageNo;
                    PageLockMode : tbd00_PageLockMode;
                    NodeReq      : tbd_node_request;
                    VAR Nptrs    : tbd_node_ptrs);
 
        PROCEDURE
              b13init_default_data_page (
                    VAR FileId  : tgg00_FileId;
                    Level       : tsp00_Int2;
                    NewPno      : tsp00_PageNo;
                    VAR Nptrs   : tbd_node_ptrs);
 
        PROCEDURE
              b13r_release_node (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree;
                    lru_info    : tbd_lru_info);
 
        PROCEDURE
              b13w_release_node (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              treehandling : VBD30;
 
        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);
 
      ------------------------------ 
 
        FROM
              bytestring_handling : VBD60;
 
        PROCEDURE
              b60conlput_bstrleaf (VAR nptr : tbd_node_ptrs;
                    pos           : tsp00_Int4;
                    length        : tsp00_Int4;
                    VAR b         : tsp00_Page;
                    VAR firstcall : boolean;
                    extended      : boolean;
                    VAR filelen   : tsp00_Int4;
                    VAR current   : tbd_current_tree);
 
        PROCEDURE
              b60get_bytestr (VAR nptr : tbd_node_ptrs;
                    pos         : tsp00_Int4;
                    length      : tsp00_Int4;
                    buf_size    : tsp00_Int4;
                    buf_addr    : tsp00_MoveObjPtr;
                    bufpos      : tsp00_Int4;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b60extend_bytestr (VAR nptr : tbd_node_ptrs;
                    pos         : tsp00_Int4;
                    length      : tsp00_Int4;
                    use_buf     : boolean;
                    fill_char   : char;
                    buf_size    : tsp00_Int4;
                    buf_addr    : tsp00_MoveObjPtr;
                    bufpos      : tsp00_Int4;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b60lput_bstrleaf (VAR nptr : tbd_node_ptrs;
                    pos         : tsp00_Int4;
                    length      : tsp00_Int4;
                    use_buf     : boolean;
                    fill_char   : char;
                    buf_size    : tsp00_Int4;
                    buf_addr    : tsp00_MoveObjPtr;
                    bufpos      : tsp00_Int4;
                    extended    : boolean;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b60read_bytestr (nptr : tbd_nodeptr;
                    pos      : tsp00_Int4;
                    length   : tsp00_Int4;
                    buf_size : tsp00_Int4;
                    buf_addr : tsp00_MoveObjPtr;
                    buf_pos  : tsp00_Int4;
                    VAR e    : tgg00_BasisError);
 
        PROCEDURE
              b60rext_bstrroot (VAR nptr : tbd_node_ptrs;
                    pos         : tsp00_Int4;
                    length      : tsp00_Int4;
                    use_buf     : boolean;
                    fill_char   : char;
                    buf_size    : tsp00_Int4;
                    buf_addr    : tsp00_MoveObjPtr;
                    bufpos      : tsp00_Int4;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b60rput_bstrroot (VAR nptr : tbd_node_ptrs;
                    pos         : tsp00_Int4;
                    length      : tsp00_Int4;
                    use_buf     : boolean;
                    fill_char   : char;
                    buf_size    : tsp00_Int4;
                    buf_addr    : tsp00_MoveObjPtr;
                    bufpos      : tsp00_Int4;
                    extended    : boolean;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd60ExtractBlob (
                    VAR current      : tbd_current_tree;
                    VAR hostFileName : tsp00_VFilename);
 
      ------------------------------ 
 
        FROM
              bytestring_indexhandling : VBD61;
 
        PROCEDURE
              b61add_bstrindex (VAR act_rootptr : tbd_node_ptrs;
                    act_pno     : tsp00_PageNo;
                    pno_1       : tsp00_PageNo;
                    pno_2       : tsp00_PageNo;
                    ins_level   : tsp00_Int2;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b61first_load_step (VAR leftptr : tbd_node_ptrs;
                    VAR leafptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b61rtrunc_bstrroot (VAR nptr : tbd_node_ptrs;
                    new_flength : tsp00_Int4;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b61search_leaf (VAR nptr : tbd_node_ptrs;
                    pos          : tsp00_Int4;
                    VAR leaf_pos : tsp00_Int4;
                    VAR current  : tbd_current_tree);
 
        PROCEDURE
              b61trunc_bstr (VAR nptr : tbd_node_ptrs;
                    new_flength : tsp00_Int4;
                    destroy     : boolean;
                    VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              ref_statistic : VBD73;
 
        PROCEDURE
              b73cmd_count (statement_kind : tgg00_RefInfoIndex);
 
      ------------------------------ 
 
        FROM
              BD_Wrapper : VBD999;
 
        PROCEDURE
              bd999CheckSpace(
                    VAR Trans         : tgg00_TransContext;
                    NumPagesRequestes : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01vtrace : tgg00_VtraceState;
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              g10mv (
                    mod_id      : tsp00_C6;
                    mod_num     : tsp00_Int4;
                    source_upb  : tsp00_Int4;
                    dest_upb    : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    src_pos     : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    dest_pos    : tsp00_Int4;
                    length      : tsp00_Int4;
                    VAR e       : tgg00_BasisError);
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : JuergenP
.sp
.cp 3
Created : 1984-08-07
.sp
.cp 3
.sp
.cp 3
Release :      Date : 2000-10-26
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
 
 
.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
 
 
.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:
 
.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :
 
 
CONST
      c_use_buffer = true;
 
TYPE
 
      tbd05_bstr_info = RECORD
            b_nptr : tbd_node_ptrs;
            b_fpos : tsp00_Int4;
            b_flen : tsp00_Int4;
            b_curr : tbd_current_tree
      END;
 
 
 
(*------------------------------*) 
 
PROCEDURE
      b05copy_bytestr (VAR t : tgg00_TransContext;
            VAR source_file : tgg00_FileId;
            from_pos        : tsp00_Int4;
            VAR target_file : tgg00_FileId;
            to_pos          : tsp00_Int4;
            length          : tsp00_Int4;
            new_str_version : tsp00_Int4);
 
VAR
      source_nptr    : tbd_node_ptrs;
      dest_nptr      : tbd_node_ptrs;
      source_flength : tsp00_Int4;
      dest_flength   : tsp00_Int4;
      act_maxflen    : tsp00_Int4;
      source_info    : tbd05_bstr_info;
      dest_info      : tbd05_bstr_info;
      source_current : tbd_current_tree;
      dest_current   : tbd_current_tree;
      trace          : tgg11_BdIntTrace;
      root_trace     : tgg11_BdRootTrace;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrRoot_gg11 := NIL_PAGE_NO_GG00;
    trace.bdiTrType_gg11    := bdtrInt_egg11;
    trace.bdiInt_gg11 [0]   := from_pos;
    trace.bdiInt_gg11 [1]   := to_pos;
    trace.bdiInt_gg11 [2]   := length;
    b120InsertTrace (t, bd, b05copy, sizeof (trace), @trace)
    END;
&ifdef TRACE
(*ENDIF*) 
t01str30  (bi, '====> bd copy bytestr         ');
t01treeid (bi, 'source file ', source_file);
t01treeid (bi, 'target file ', target_file);
t01p2int4 (bi, 'from pos    ', from_pos
      ,        'to pos      ', to_pos);
t01p2int4 (bi, 'length      ', length
      ,        'str version ', new_str_version);
&endif
WITH source_info DO
    BEGIN
    b_nptr.np_ptr   := NIL;
    b_nptr.np_cbptr := NIL
    END;
(*ENDWITH*) 
WITH dest_info DO
    BEGIN
    b_nptr.np_ptr   := NIL;
    b_nptr.np_cbptr := NIL
    END;
(*ENDWITH*) 
WITH source_nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL
    END;
(*ENDWITH*) 
WITH dest_nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL
    END;
(*ENDWITH*) 
t.trError_gg00 := e_ok;
WITH t DO
    BEGIN
    IF  b01downfilesystem
    THEN
        trError_gg00 := e_shutdown
    ELSE
        IF  source_file.fileName_gg00 = target_file.fileName_gg00
        THEN
            trError_gg00 := e_not_implemented
        ELSE
            BEGIN
            IF  ((length < 1) OR (length > cbd_cspmaxint4_mxspbuf))
                AND
                (length <> cgg_whole_bytestr)
            THEN
                trError_gg00 := e_file_limit
            ELSE
                IF  (from_pos < 1) OR (from_pos > cbd_cspmaxint4_mxspbuf)
                THEN
                    trError_gg00 := e_file_limit
                ELSE
                    IF  (to_pos <> cgg_eo_bytestr       ) AND
                        (
                        (to_pos < 1                     ) OR
                        (to_pos > cbd_cspmaxint4_mxspbuf)
                        )
                    THEN
                        trError_gg00 := e_file_limit;
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                bd999CheckSpace (t, (length DIV MAX_BSTR_COVERING_BD00) + 1);
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                bd30GetTree (t, source_file, source_current, LOCK_TREE_EXCL_BD00, m_column);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    source_nptr := source_current.currRootNptrs_bd00;
                    target_file.fileBdUse_gg00 := target_file.fileBdUse_gg00 + [bd_write_acc];
                    bd30GetTree (t, target_file, dest_current, LOCK_TREE_EXCL_BD00, m_column);
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        root_trace.bdrRoot_gg11 := dest_current.curr_tree_id.fileRoot_gg00;
                        dest_nptr               := dest_current.currRootNptrs_bd00;
                        source_flength          := source_nptr.np_ptr^.ndStrFileSize_bd00;
                        dest_flength            := dest_nptr.np_ptr^.ndStrFileSize_bd00;
                        IF  length = cgg_whole_bytestr
                        THEN
                            length := source_flength;
                        (*ENDIF*) 
                        from_pos := from_pos - 1;
                        IF  to_pos = cgg_eo_bytestr
                        THEN
                            to_pos := dest_flength
                        ELSE
                            to_pos := to_pos - 1;
                        (*ENDIF*) 
                        IF  (from_pos + length) > source_flength
                        THEN
                            BEGIN
                            length := source_flength - from_pos;
&                           ifdef TRACE
                            t01int4 (bi, 'trunc length', length);
&                           endif
                            END;
                        (*ENDIF*) 
                        IF  (from_pos > source_flength                 ) OR
                            (to_pos > dest_flength                     ) OR
                            (
                            ((to_pos + length) > cbd_cspmaxint4_mxspbuf)
                            )
                        THEN
                            trError_gg00 := e_file_limit
                        ELSE
                            BEGIN
                            act_maxflen := (dest_flength - 1) DIV MAX_BSTR_COVERING_BD00;
                            act_maxflen := (act_maxflen + 1) * MAX_BSTR_COVERING_BD00;
                            WITH source_info DO
                                BEGIN
                                b_nptr := source_nptr;
                                b_flen := source_flength;
                                b_curr := source_current;
                                b_fpos := from_pos
                                END;
                            (*ENDWITH*) 
                            WITH dest_info DO
                                BEGIN
                                b_nptr := dest_nptr;
                                b_flen := dest_flength;
                                b_curr := dest_current;
                                b_fpos := to_pos
                                END;
                            (*ENDWITH*) 
                            IF  new_str_version <> NIL_STR_VERSION_GG00
                            THEN
                                dest_nptr.np_ptr^.ndStrVersion_bd00 := new_str_version;
                            (*ENDIF*) 
                            bd05copy_2 (source_info, dest_info, length, act_maxflen);
                            dest_nptr   := dest_info.b_nptr;
                            source_nptr := source_info.b_nptr
                            END
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  source_nptr.np_ptr <> NIL
                    THEN
                        b13r_release_node (source_nptr, source_current, lru_normal);
                    (*ENDIF*) 
                    IF  dest_nptr.np_ptr <> NIL
                    THEN
                        b13r_release_node (dest_nptr, dest_current, lru_normal);
                    (*ENDIF*) 
                    bd30ReleaseTree (dest_current);
                    END;
                (*ENDIF*) 
                bd30ReleaseTree (source_current);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    source_file := source_current.curr_tree_id;
                    target_file := dest_current.curr_tree_id
                    END;
                (*ENDIF*) 
                target_file.fileBdUse_gg00 := target_file.fileBdUse_gg00 - [bd_write_acc]
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
    (*ENDIF*) 
    END;
(*ENDWITH*) 
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrTrType_gg11 := bdtrRoot_egg11;
    root_trace.bdrError_gg11  := t.trError_gg00;
    b120InsertTrace (t, bd, b05copy, sizeof (root_trace), @root_trace)
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05expand_bytestr (VAR t : tgg00_TransContext;
            VAR file_id     : tgg00_FileId;
            length          : tsp00_Int4;
            fill_char       : char;
            new_str_version : tsp00_Int4);
 
VAR
      extended         : boolean;
      updated_new      : boolean;
      pos              : tsp00_Int4;
      expand_length    : tsp00_Int4;
      part_length      : tsp00_Int4;
      last_page_length : tsp00_Int4;
      nptr             : tbd_node_ptrs;
      flength          : tsp00_Int4;
      trace            : tgg11_BdIntTrace;
      root_trace       : tgg11_BdRootTrace;
      current          : tbd_current_tree;
      DummyBuffer      : tsp00_Buf;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrRoot_gg11 := NIL_PAGE_NO_GG00;
    trace.bdiTrType_gg11    := bdtrInt_egg11;
    trace.bdiInt_gg11 [0]   := length;
    b120InsertTrace (t, bd, b05expand,
          sizeof (trace)
          - sizeof (trace.bdiInt_gg11 [1])
          - sizeof (trace.bdiInt_gg11 [2]), @trace)
    END;
&ifdef TRACE
(*ENDIF*) 
t01str30  (bi, '====> bd expand bytstr        ');
t01treeid (bi, 'treeid      ', file_id);
t01int4   (bi, 'length      ', length);
&endif
nptr.np_ptr    := NIL;
nptr.np_cbptr  := NIL;
t.trError_gg00 := e_ok;
extended       := true;
updated_new    := false;
IF  b01downfilesystem
THEN
    t.trError_gg00 := e_shutdown
ELSE
    WITH  t DO
        BEGIN
        IF  length < 1
        THEN
            trError_gg00 := e_buffer_limit
        ELSE
            bd999CheckSpace (t, (length DIV MAX_BSTR_COVERING_BD00) + 1);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            file_id.fileBdUse_gg00 := file_id.fileBdUse_gg00 + [bd_write_acc];
            bd30GetTree (t, file_id, current, LOCK_TREE_EXCL_BD00, m_column);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                root_trace.bdrRoot_gg11 := current.curr_tree_id.fileRoot_gg00;
                nptr                    := current.currRootNptrs_bd00;
                flength                 := nptr.np_ptr^.ndStrFileSize_bd00;
                pos                     := flength;
&               ifdef TRACE
                t01int4 (bd_byte, 'flength     ', flength);
&               endif
                IF  length <= flength
                THEN
                    b13r_release_node (nptr, current, lru_normal)
                ELSE
                    BEGIN
                    IF  flength <> 0
                    THEN
                        last_page_length := ((flength - 1) MOD MAX_BSTR_COVERING_BD00) + 1
                    ELSE
                        last_page_length := 0;
                    (*ENDIF*) 
                    expand_length := length - flength;
                    IF  expand_length <= MAX_BSTR_COVERING_BD00 - last_page_length
                    THEN
                        part_length := expand_length
                    ELSE
                        BEGIN
                        IF  last_page_length = MAX_BSTR_COVERING_BD00
                        THEN
                            IF  expand_length > MAX_BSTR_COVERING_BD00
                            THEN
                                part_length := MAX_BSTR_COVERING_BD00
                            ELSE
                                part_length := expand_length
                            (*ENDIF*) 
                        ELSE
                            part_length := MAX_BSTR_COVERING_BD00 - last_page_length
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    REPEAT
                        IF  (last_page_length + part_length)
                            <= MAX_BSTR_COVERING_BD00
                        THEN
                            BEGIN
                            IF  new_str_version <> NIL_STR_VERSION_GG00
                            THEN
                                nptr.np_ptr^.ndStrVersion_bd00 := new_str_version;
                            (*ENDIF*) 
                            IF  flength <= MAX_BSTR_COVERING_BD00
                            THEN
                                b60rput_bstrroot (nptr, pos,
                                      part_length, NOT c_use_buffer,
                                      fill_char, sizeof (DummyBuffer), @DummyBuffer, 1,
                                      extended, current)
                            ELSE
                                b60lput_bstrleaf (nptr, pos,
                                      part_length, NOT c_use_buffer,
                                      fill_char, sizeof (DummyBuffer), @DummyBuffer, 1,
                                      extended, current)
                            (*ENDIF*) 
                            END
                        ELSE
                            BEGIN
                            updated_new := true;
                            IF  new_str_version <> NIL_STR_VERSION_GG00
                            THEN
                                nptr.np_ptr^.ndStrVersion_bd00 := new_str_version;
                            (*ENDIF*) 
                            IF  flength <= MAX_BSTR_COVERING_BD00
                            THEN
                                b60rext_bstrroot (nptr, pos,
                                      part_length, NOT c_use_buffer,
                                      fill_char, sizeof (DummyBuffer), @DummyBuffer, 1, current)
                            ELSE
                                b60extend_bytestr (nptr, pos,
                                      part_length, NOT c_use_buffer,
                                      fill_char, sizeof (DummyBuffer), @DummyBuffer, 1, current);
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        pos           := pos + part_length;
                        flength       := flength + part_length;
                        expand_length := expand_length - part_length;
                        IF  expand_length < MAX_BSTR_COVERING_BD00
                        THEN
                            part_length := expand_length
                        ELSE
                            part_length := MAX_BSTR_COVERING_BD00;
                        (*ENDIF*) 
                        last_page_length := MAX_BSTR_COVERING_BD00;
                    UNTIL
                        (trError_gg00 <> e_ok) OR (expand_length = 0);
                    (*ENDREPEAT*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        IF  nptr.np_ptr^.nd_id <> current.curr_tree_id.fileRoot_gg00
                        THEN
                            b13w_release_node (nptr, current);
                        (*ENDIF*) 
                        current.currRootNptrs_bd00.np_ptr^.ndStrFileSize_bd00 := length - expand_length;
                        current.currRootUpdated_bd00                          := true;
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
                THEN
                    b13r_release_node (nptr, current, lru_normal);
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            bd30ReleaseTree (current);
            IF  trError_gg00 = e_ok
            THEN
                file_id := current.curr_tree_id;
            (*ENDIF*) 
            file_id.fileBdUse_gg00 := file_id.fileBdUse_gg00 - [bd_write_acc];
            END;
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
(*ENDIF*) 
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrTrType_gg11 := bdtrRoot_egg11;
    root_trace.bdrError_gg11  := t.trError_gg00;
    b120InsertTrace (t, bd, b05expand, sizeof (root_trace), @root_trace)
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05finish_load (
            VAR t          : tgg00_TransContext;
            VAR file_id    : tgg00_FileId;
            rightmost_leaf : tsp00_PageNo);
 
VAR
      nptr    : tbd_node_ptrs;
      current : tbd_current_tree;
 
BEGIN
nptr.np_ptr   := NIL;
nptr.np_cbptr := NIL;
WITH t DO
    BEGIN
    file_id.fileBdUse_gg00 := file_id.fileBdUse_gg00 + [bd_write_acc];
    bd30GetTree (t, file_id, current, LOCK_TREE_EXCL_BD00, m_column);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        bd13GetNode (current, rightmost_leaf, plmLock_ebd00, nr_for_read, nptr);
        IF  trError_gg00 = e_ok
        THEN
            WITH current, currRootNptrs_bd00, np_ptr^ DO
                BEGIN
                ndStrFileSize_bd00   := nptr.np_ptr^.ndStrFileSize_bd00;
                ndStrVersion_bd00    := NIL_STR_VERSION_GG00;
                currRootUpdated_bd00 := true
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
        IF  nptr.np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    bd30ReleaseTree (current);
    file_id.fileBdUse_gg00 := file_id.fileBdUse_gg00 - [bd_write_acc];
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05get_str_version  (VAR t : tgg00_TransContext;
            VAR file_id     : tgg00_FileId;
            VAR str_version : tsp00_Int4);
 
VAR
      current    : tbd_current_tree;
      root_trace : tgg11_BdRootTrace;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrRoot_gg11 := NIL_PAGE_NO_GG00;
    b120InsertTrace (t, bd, b05getset, 0, @root_trace);
    END;
&ifdef TRACE
(*ENDIF*) 
t01name   (bi, 'bd bytestr get ver');
t01treeid (bi, 'treeid      ', file_id);
&endif
WITH t DO
    BEGIN
    IF  b01downfilesystem
    THEN
        trError_gg00 := e_shutdown
    ELSE
        BEGIN
        trError_gg00 := e_ok;
        bd30GetTree (t, file_id, current, NOT LOCK_TREE_EXCL_BD00, m_column);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            root_trace.bdrRoot_gg11 := current.curr_tree_id.fileRoot_gg00;
            str_version             := current.currRootNptrs_bd00.np_ptr^.ndStrVersion_bd00;
            file_id                 := current.curr_tree_id
            END;
        (*ENDIF*) 
        bd30ReleaseTree (current)
        END;
    (*ENDIF*) 
&   ifdef TRACE
    t01int4        (bi, 'str version ', str_version);
&   endif
    IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
    THEN
        BEGIN
        root_trace.bdrTrType_gg11 := bdtrRoot_egg11;
        root_trace.bdrError_gg11  := t.trError_gg00;
        b120InsertTrace (t, bd, b05getset, sizeof (root_trace), @root_trace)
        END;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05length_bytestr (VAR t : tgg00_TransContext;
            VAR file_id     : tgg00_FileId;
            VAR filelength  : tsp00_Int4;
            VAR page_count  : tsp00_Int4;
            VAR str_version : tsp00_Int4);
 
VAR
      current    : tbd_current_tree;
      root_trace : tgg11_BdRootTrace;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrRoot_gg11 := NIL_PAGE_NO_GG00;
    b120InsertTrace (t, bd, b05length, 0, @root_trace);
    END;
&ifdef TRACE
(*ENDIF*) 
t01name   (bi, 'bd bytestr length ');
t01treeid (bi, 'treeid      ', file_id);
&endif
WITH t DO
    BEGIN
    IF  b01downfilesystem
    THEN
        trError_gg00 := e_shutdown
    ELSE
        BEGIN
        trError_gg00 := e_ok;
        bd30GetTree (t, file_id, current, NOT LOCK_TREE_EXCL_BD00, m_column);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            root_trace.bdrRoot_gg11 := current.curr_tree_id.fileRoot_gg00;
            WITH current.currRootNptrs_bd00, np_ptr^ DO
                BEGIN
                filelength  := ndStrFileSize_bd00;
                str_version := ndStrVersion_bd00;
                file_id     := current.curr_tree_id;
                page_count  := 1 + (* root page *)
                      nd_level +
                      (filelength DIV (PNOS_PER_PAGE_BD00 * MAX_BSTR_COVERING_BD00)) +
                      (filelength DIV MAX_BSTR_COVERING_BD00 )
                END
            (*ENDWITH*) 
            END;
        (*ENDIF*) 
        bd30ReleaseTree (current)
        END;
    (*ENDIF*) 
&   ifdef TRACE
    t01p2int4      (bi, 'filelength  ', filelength
          ,             'str version ', str_version);
&   endif
    IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
    THEN
        BEGIN
        root_trace.bdrTrType_gg11 := bdtrRoot_egg11;
        root_trace.bdrError_gg11  := t.trError_gg00;
        b120InsertTrace (t, bd, b05length, sizeof (root_trace), @root_trace)
        END;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05load_string (VAR lnptr : tbd_node_ptrs;
            VAR nptr     : tbd_node_ptrs;
            VAR left_pno : tsp00_PageNo;
            VAR current  : tbd_current_tree);
 
VAR
      save_bottom : tgg00_PagePos;
      rootptr     : tbd_node_ptrs;
      act_pno     : tsp00_PageNo;
 
BEGIN
rootptr.np_ptr   := NIL;
rootptr.np_cbptr := NIL;
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    IF  lnptr.np_ptr^.nd_id = fileRoot_gg00
    THEN
        BEGIN
        b61first_load_step (lnptr, nptr, current);
        left_pno := NIL_PAGE_NO_GG00
        END
    ELSE
        BEGIN
        IF  nptr.np_ptr <> NIL
        THEN
            IF  nptr.np_ptr^.nd_bottom > BODY_BEG_BD00
            THEN
                BEGIN
                WITH nptr.np_ptr^ DO
                    BEGIN
                    save_bottom        := nd_bottom;
                    b13init_default_data_page (curr_tree_id, LEAF_LEVEL_BD00, nd_id, nptr);
                    nd_bottom          := save_bottom;
                    nd_left            := lnptr.np_ptr^.nd_id;
                    ndStrFileSize_bd00 := lnptr.np_ptr^.ndStrFileSize_bd00 + nd_bottom - BODY_BEG_BD00;
                    act_pno            := nd_id
                    END;
                (*ENDWITH*) 
                lnptr.np_ptr^.nd_right := nptr.np_ptr^.nd_id
                END
            ELSE
                act_pno := NIL_PAGE_NO_GG00
            (*ENDIF*) 
        ELSE
            act_pno := NIL_PAGE_NO_GG00;
        (*ENDIF*) 
        IF  left_pno = NIL_PAGE_NO_GG00
        THEN
            left_pno := nptr.np_ptr^.nd_id
        ELSE
            BEGIN
            bd13GetNode (current, fileRoot_gg00, plmLock_ebd00, nr_for_update, rootptr);
            IF  trError_gg00 = e_ok
            THEN
                b61add_bstrindex (rootptr, fileRoot_gg00, left_pno, act_pno,
                      succ(LEAF_LEVEL_BD00), current);
            (*ENDIF*) 
            left_pno := NIL_PAGE_NO_GG00
            END;
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (nptr.np_ptr <> NIL)
        THEN
            IF  nptr.np_ptr^.nd_bottom > BODY_BEG_BD00
            THEN
                BEGIN
                b13w_release_node (lnptr, current);
                lnptr         := nptr;
                nptr.np_ptr   := NIL;
                nptr.np_cbptr := NIL
                END
            ELSE
                b13free_node (nptr, current)
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 <> e_ok
    THEN
        BEGIN
        IF  nptr.np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  lnptr.np_ptr <> NIL
        THEN
            b13r_release_node (lnptr, current, lru_normal);
        (*ENDIF*) 
        IF  rootptr.np_ptr <> NIL
        THEN
            b13r_release_node (rootptr, current, lru_normal)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05read_bytestr (VAR t : tgg00_TransContext;
            VAR file_id : tgg00_FileId;
            pos         : tsp00_Int4;
            VAR length  : tsp00_Int4;
            buf_size    : tsp00_Int4;
            buf_addr    : tsp00_MoveObjPtr;
            bufpos      : tsp00_Int4);
 
VAR
      leaf_pos   : tsp00_Int4;
      flength    : tsp00_Int4;
      nptr       : tbd_node_ptrs;
      trace      : tgg11_BdIntTrace;
      root_trace : tgg11_BdRootTrace;
      current    : tbd_current_tree;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrRoot_gg11 := NIL_PAGE_NO_GG00;
    trace.bdiTrType_gg11    := bdtrInt_egg11;
    trace.bdiInt_gg11 [0]   := pos;
    trace.bdiInt_gg11 [1]   := length;
    b120InsertTrace (t, bd, b05read, sizeof (trace) - sizeof (trace.bdiInt_gg11 [2]), @trace)
    END;
&ifdef TRACE
(*ENDIF*) 
t01str30  (bi, '====> bd read bytestr         ');
t01treeid (bi, 'treeid      ', file_id);
t01int4   (bi, 'pos         ', pos);
t01int4   (bi, 'length      ', length);
t01int4   (bi, 'bufpos      ', bufpos);
&endif
nptr.np_ptr    := NIL;
nptr.np_cbptr  := NIL;
t.trError_gg00 := e_ok;
b73cmd_count (iread_string);
IF  b01downfilesystem
THEN
    t.trError_gg00 := e_shutdown
ELSE
    WITH t DO
        BEGIN
        IF  (length < 1) OR (length + bufpos - 1 > buf_size)
        THEN
            trError_gg00 := e_buffer_limit
        ELSE
            IF  (pos < 1) OR (pos > cbd_cspmaxint4_mxspbuf)
            THEN
                trError_gg00 := e_file_limit;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            bd30GetTree (t, file_id, current, NOT LOCK_TREE_EXCL_BD00, m_column);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                root_trace.bdrRoot_gg11 := current.curr_tree_id.fileRoot_gg00;
                nptr                    := current.currRootNptrs_bd00;
                flength := nptr.np_ptr^.ndStrFileSize_bd00;
                pos     := pos - 1;
                IF  pos < flength
                THEN
                    BEGIN
                    IF  (pos + length) > flength
                    THEN
                        BEGIN
                        length := flength - pos;
&                       ifdef TRACE
                        t01int4 (bi, 'trunc length', length);
&                       endif
                        END;
                    (*ENDIF*) 
                    IF  ((pos MOD MAX_BSTR_COVERING_BD00) + length)
                        < MAX_BSTR_COVERING_BD00
                    THEN
                        BEGIN
                        IF  flength <= MAX_BSTR_COVERING_BD00
                        THEN
                            BEGIN
                            leaf_pos := pos;
                            b60read_bytestr (nptr.np_ptr, leaf_pos,
                                  length, buf_size, buf_addr, bufpos, trError_gg00)
                            END
                        ELSE
                            BEGIN
                            b61search_leaf (nptr, pos, leaf_pos, current);
                            IF  trError_gg00 = e_ok
                            THEN
                                b60read_bytestr (nptr.np_ptr, leaf_pos,
                                      length, buf_size, buf_addr, bufpos, trError_gg00)
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        b61search_leaf (nptr, pos, leaf_pos, current);
                        IF  trError_gg00 = e_ok
                        THEN
                            b60get_bytestr (nptr, leaf_pos, length,
                                  buf_size, buf_addr, bufpos, current)
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  nptr.np_ptr <> NIL
                    THEN
                        b13r_release_node (nptr, current, lru_normal)
                    (*ENDIF*) 
                    END
                ELSE
                    IF  (flength = 0) OR (pos = flength)
                    THEN
                        BEGIN
                        length := 0;
                        trError_gg00 := e_key_not_found
                        END
                    ELSE
                        trError_gg00 := e_file_limit;
                    (*ENDIF*) 
                (*ENDIF*) 
                IF  nptr.np_ptr <> NIL
                THEN
                    b13r_release_node (nptr, current, lru_normal)
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            bd30ReleaseTree (current);
            IF  trError_gg00 = e_ok
            THEN
                file_id := current.curr_tree_id;
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
(*ENDIF*) 
&ifdef TRACE
IF  t.trError_gg00 = e_ok
THEN
    t01moveobj (bi, buf_addr^, 1, length);
&endif
(*ENDIF*) 
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrTrType_gg11 := bdtrRoot_egg11;
    root_trace.bdrError_gg11  := t.trError_gg00;
    b120InsertTrace (t, bd, b05read, sizeof (root_trace), @root_trace)
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05trunc_bytestr ( VAR t : tgg00_TransContext;
            VAR file_id     : tgg00_FileId;
            new_filelength  : tsp00_Int4;
            new_str_version : tsp00_Int4);
 
VAR
      nptr       : tbd_node_ptrs;
      current    : tbd_current_tree;
      trace      : tgg11_BdIntTrace;
      root_trace : tgg11_BdRootTrace;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrRoot_gg11 := NIL_PAGE_NO_GG00;
    trace.bdiTrType_gg11    := bdtrInt_egg11;
    trace.bdiInt_gg11 [0]   := new_filelength;
    b120InsertTrace (t, bd, b05trunc,
          sizeof (trace)
          - sizeof (trace.bdiInt_gg11 [1])
          - sizeof (trace.bdiInt_gg11 [2]), @trace)
    END;
&ifdef TRACE
(*ENDIF*) 
t01name   (bi, 'bd trunc bytestr  ');
t01treeid (bi, 'treeid      ', file_id);
t01p2int4 (bi, 'new flength ', new_filelength
      ,        'str version ', new_str_version);
&endif
nptr.np_ptr    := NIL;
nptr.np_cbptr  := NIL;
t.trError_gg00 := e_ok;
WITH t DO
    BEGIN
    IF  b01downfilesystem
    THEN
        trError_gg00 := e_shutdown
    ELSE
        BEGIN
        file_id.fileBdUse_gg00 := file_id.fileBdUse_gg00 + [bd_write_acc];
        bd30GetTree (t, file_id, current, LOCK_TREE_EXCL_BD00, m_column);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            root_trace.bdrRoot_gg11 := current.curr_tree_id.fileRoot_gg00;
            nptr                    := current.currRootNptrs_bd00;
            IF  new_str_version <> NIL_STR_VERSION_GG00
            THEN
                nptr.np_ptr^.ndStrVersion_bd00 := new_str_version;
            (*ENDIF*) 
            IF  new_filelength < nptr.np_ptr^.ndStrFileSize_bd00
            THEN
                BEGIN
                IF  nptr.np_ptr^.ndStrFileSize_bd00 <= MAX_BSTR_COVERING_BD00
                THEN
                    b61rtrunc_bstrroot (nptr, new_filelength, current)
                ELSE
                    b61trunc_bstr (nptr, new_filelength, false, current)
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  nptr.np_ptr <> NIL
            THEN
                b13r_release_node (nptr, current, lru_normal)
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        bd30ReleaseTree (current);
        IF  trError_gg00 = e_ok
        THEN
            file_id := current.curr_tree_id;
        (*ENDIF*) 
        file_id.fileBdUse_gg00 := file_id.fileBdUse_gg00 - [bd_write_acc];
        END;
    (*ENDIF*) 
    IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
    THEN
        BEGIN
        root_trace.bdrTrType_gg11 := bdtrRoot_egg11;
        root_trace.bdrError_gg11  := t.trError_gg00;
        b120InsertTrace (t, bd, b05trunc, sizeof (root_trace), @root_trace)
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05write_bytestr (VAR t : tgg00_TransContext;
            VAR file_id     : tgg00_FileId;
            pos             : tsp00_Int4;
            length          : tsp00_Int4;
            buf_size        : tsp00_Int4;
            buf_addr        : tsp00_MoveObjPtr;
            bufpos          : tsp00_Int4;
            new_str_version : tsp00_Int4);
 
VAR
      extended         : boolean;
      fill_char        : char;
      leaf_pos         : tsp00_Int4;
      trace_str_len    : tsp00_Int4;
      ext_length       : tsp00_Int4;
      last_page_length : tsp00_Int4;
      nptr             : tbd_node_ptrs;
      flength          : tsp00_Int4;
      trace            : tgg11_BdWriteStrTrace;
      root_trace       : tgg11_BdRootTrace;
      current          : tbd_current_tree;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrRoot_gg11             := NIL_PAGE_NO_GG00;
    trace.bdwsHead_gg11.bdwhTrType_gg11 := bdtrWriteStr_egg11;
    trace.bdwsHead_gg11.bdwhPos_gg11    := pos;
    trace.bdwsHead_gg11.bdwhLen_gg11    := length;
    trace_str_len                       := length;
    IF  sizeof (trace.bdwsHead_gg11) + trace_str_len > sizeof (tgg11_VtraceBody)
    THEN
        trace_str_len := sizeof (tgg11_VtraceBody) - sizeof (trace.bdwsHead_gg11);
    (*ENDIF*) 
    g10mv ('VBD05 ',   1,    
          buf_size,  sizeof (trace.bdwsStr_gg11),
          @buf_addr^, bufpos, @trace.bdwsStr_gg11, 1, trace_str_len, t.trError_gg00);
    b120InsertTrace (t, bd, b05write, sizeof (trace.bdwsHead_gg11) + trace_str_len, @trace)
    END;
&ifdef TRACE
(*ENDIF*) 
t01str30   (bi, '====> bd write bytestr        ');
t01treeid  (bi, 'treeid      ', file_id);
t01int4    (bi, 'pos         ', pos);
t01int4    (bi, 'length      ', length);
t01moveobj (bi, buf_addr^, bufpos, bufpos + length - 1);
&endif
nptr.np_ptr    := NIL;
nptr.np_cbptr  := NIL;
t.trError_gg00 := e_ok;
fill_char      := bsp_c1;
b73cmd_count (iwrite_string);
IF  b01downfilesystem
THEN
    t.trError_gg00 := e_shutdown
ELSE
    WITH t DO
        BEGIN
        IF  (length < 1                      ) OR
            (length > buf_size               ) OR
            ((bufpos + length - 1) > buf_size)
        THEN
            trError_gg00 := e_buffer_limit
        ELSE
            IF  (pos <> cgg_eo_bytestr       ) AND
                (
                (pos < 1                     ) OR
                (pos > cbd_cspmaxint4_mxspbuf)
                )
            THEN
                trError_gg00 := e_file_limit;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            bd999CheckSpace (t, 3);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            file_id.fileBdUse_gg00 := file_id.fileBdUse_gg00 + [bd_write_acc];
            bd30GetTree (t, file_id, current, LOCK_TREE_EXCL_BD00, m_column);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                root_trace.bdrRoot_gg11 := current.curr_tree_id.fileRoot_gg00;
                nptr                    := current.currRootNptrs_bd00;
                flength                 := nptr.np_ptr^.ndStrFileSize_bd00;
                IF  pos = cgg_eo_bytestr
                THEN
                    pos := flength
                ELSE
                    pos := pos - 1;
                (*ENDIF*) 
&               ifdef TRACE
                t01int4 (bd_byte, 'pos         ', pos);
                t01int4 (bd_byte, 'flength     ', flength);
&               endif
                IF  (pos > flength                           ) OR
                    ((pos + length) >= cbd_cspmaxint4_mxspbuf)
                THEN
                    trError_gg00 := e_file_limit
                ELSE
                    BEGIN
                    IF  flength <> 0
                    THEN
                        last_page_length := ((flength - 1)
                              MOD MAX_BSTR_COVERING_BD00) + 1
                    ELSE
                        last_page_length := 0;
                    (*ENDIF*) 
                    ext_length := flength - pos;
                    ext_length := length - ext_length;
                    leaf_pos   := pos MOD MAX_BSTR_COVERING_BD00;
                    IF  ext_length > 0
                    THEN
                        extended := true
                    ELSE
                        extended := false;
                    (*ENDIF*) 
                    IF  (last_page_length + ext_length)
                        <= MAX_BSTR_COVERING_BD00
                    THEN
                        BEGIN
                        (* PTS 1001460 Torsten Strahl 1998-08-02 *)
                        IF  new_str_version <> NIL_STR_VERSION_GG00
                        THEN
                            nptr.np_ptr^.ndStrVersion_bd00 := new_str_version;
                        (*ENDIF*) 
                        IF  flength <= MAX_BSTR_COVERING_BD00
                        THEN
                            b60rput_bstrroot (nptr, pos, length,
                                  c_use_buffer, fill_char, buf_size,
                                  buf_addr, bufpos, extended, current)
                        ELSE
                            b60lput_bstrleaf (nptr, pos, length,
                                  c_use_buffer, fill_char, buf_size,
                                  buf_addr, bufpos, extended, current)
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        (* PTS 1001460 Torsten Strahl 1998-08-02 *)
                        IF  new_str_version <> NIL_STR_VERSION_GG00
                        THEN
                            nptr.np_ptr^.ndStrVersion_bd00 := new_str_version;
                        (*ENDIF*) 
                        IF  flength <= MAX_BSTR_COVERING_BD00
                        THEN
                            b60rext_bstrroot (nptr, pos, length,
                                  c_use_buffer, fill_char, buf_size,
                                  buf_addr, bufpos, current)
                        ELSE
                            b60extend_bytestr (nptr, pos, length,
                                  c_use_buffer, fill_char, buf_size,
                                  buf_addr, bufpos, current)
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
            THEN
                b13r_release_node (nptr, current, lru_normal);
            (*ENDIF*) 
            bd30ReleaseTree (current);
            IF  trError_gg00 = e_ok
            THEN
                file_id := current.curr_tree_id;
            (*ENDIF*) 
            file_id.fileBdUse_gg00 := file_id.fileBdUse_gg00 - [bd_write_acc];
            END
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
(*ENDIF*) 
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrTrType_gg11 := bdtrRoot_egg11;
    root_trace.bdrError_gg11  := t.trError_gg00;
    b120InsertTrace (t, bd, b05write, sizeof (root_trace), @root_trace)
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd05ExtractBlob (
            VAR trans        : tgg00_TransContext;
            root             : tsp00_PageNo;
            VAR hostFileName : tsp00_VFilename);
 
VAR
      fileId  : tgg00_FileId;
      current : tbd_current_tree;
 
BEGIN
&ifdef TRACE
t01name (bi, '===> extract blob ');
t01int4 (bi, 'fileRoot    ', root);
&endif
fileId               := b01niltree_id;
fileId.fileRoot_gg00 := root;
fileId.fileType_gg00 := [ ftsPerm_egg00, ftsByteStr_egg00 ];
fileId.fileTfn_gg00  := tfnColumn_egg00;
IF  b01downfilesystem
THEN
    trans.trError_gg00 := e_shutdown
ELSE
    WITH trans DO
        BEGIN
        trError_gg00 := e_ok;
        bd30GetTree (trans, fileId, current, NOT LOCK_TREE_EXCL_BD00, m_column);
        IF  trError_gg00 = e_ok
        THEN
            bd60ExtractBlob (current, hostFileName );
        (*ENDIF*) 
        bd30ReleaseTree (current);
        IF  (trError_gg00 = e_old_fileversion) OR
            (trError_gg00 = e_file_not_found )
        THEN
            trError_gg00 := e_invalid_root;
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
(*ENDIF*) 
&ifdef TRACE
t01basis_error (bi, 'end extract ', trans.trError_gg00);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd05Prefetch (
            VAR trans    : tgg00_TransContext;
            VAR fileId   : tgg00_FileId;
            blobPosition : tsp00_Int4);
 
VAR
      leafPosition : tsp00_Int4;
      nextLeaf     : tsp00_Int4;
      nptrs        : tbd_node_ptrs;
      current      : tbd_current_tree;
      trace        : tgg11_BdIntTrace;
      rootTrace    : tgg11_BdRootTrace;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    rootTrace.bdrRoot_gg11 := NIL_PAGE_NO_GG00;
    trace.bdiTrType_gg11   := bdtrInt_egg11;
    trace.bdiInt_gg11 [0]  := blobPosition;
    trace.bdiInt_gg11 [1]  := 0;
    b120InsertTrace (trans, bd, b05read, sizeof (trace) - sizeof (trace.bdiInt_gg11 [2]), @trace)
    END;
&ifdef TRACE
(*ENDIF*) 
t01name   (bi, '====> bd prefetch ');
t01treeid (bi, 'fileId      ', fileId);
t01int4   (bi, 'blob pos    ', blobPosition);
&endif
IF  b01downfilesystem
THEN
    trans.trError_gg00 := e_shutdown
ELSE
    WITH trans DO
        BEGIN
        trError_gg00    := e_ok;
        nptrs.np_ptr    := NIL;
        nptrs.np_cbptr  := NIL;
        nextLeaf        := NIL_PAGE_NO_GG00;
        (* *)
        bd30GetTree (trans, fileId, current, NOT LOCK_TREE_EXCL_BD00, m_column);
        (* *)
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            nptrs := current.currRootNptrs_bd00;
            b61search_leaf (nptrs, blobPosition, leafPosition, current);
            WHILE (trError_gg00 = e_ok) AND (nptrs.np_ptr <> NIL) DO
                BEGIN
                nextLeaf := nptrs.np_ptr^.nd_right;
                b13r_release_node (nptrs, current, lru_normal);
                IF  nextLeaf <> NIL_PAGE_NO_GG00
                THEN
                    bd13GetNode (current, nextLeaf, plmLock_ebd00, nr_for_read, nptrs);
                (*ENDIF*) 
                END;
            (*ENDWHILE*) 
            IF  nptrs.np_ptr <> NIL
            THEN
                b13r_release_node (nptrs, current, lru_normal);
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        bd30ReleaseTree (current)
        END;
    (*ENDWITH*) 
(*ENDIF*) 
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    rootTrace.bdrTrType_gg11 := bdtrRoot_egg11;
    rootTrace.bdrError_gg11  := trans.trError_gg00;
    b120InsertTrace (trans, bd, b05read, sizeof (rootTrace), @rootTrace);
    END;
(*ENDIF*) 
trans.trError_gg00 := e_ok; (* ignore all errors *)
END;
 
(*========== locals ============*)
(*------------------------------*) 
 
PROCEDURE
      bd05copy_2 (VAR source_info : tbd05_bstr_info;
            VAR dest_info : tbd05_bstr_info;
            length        : tsp00_Int4;
            flen_max      : tsp00_Int4);
 
VAR
      firstcall  : boolean;
      extended   : boolean;
      fill_char  : char;
      act_root   : tsp00_PageNo;
      f_lpos     : tsp00_Int4;
      remain_len : tsp00_Int4;
      act_len    : tsp00_Int4;
      t          : tgg00_TransContextPtr;
      Buffer     : tsp00_Page;
 
BEGIN
extended  := false;
firstcall := true;
fill_char := bsp_c1;
act_root  := dest_info.b_nptr.np_ptr^.nd_id;
t         := dest_info.b_curr.curr_trans;
WITH source_info DO
    IF  b_flen > MAX_BSTR_COVERING_BD00
    THEN
        b61search_leaf (b_nptr, b_fpos, f_lpos, b_curr)
    ELSE
        f_lpos := b_fpos;
    (*ENDIF*) 
(*ENDWITH*) 
IF  (act_root = source_info.b_curr.curr_tree_id.fileRoot_gg00) AND
    (source_info.b_flen > MAX_BSTR_COVERING_BD00             ) AND
    (t^.trError_gg00 = e_ok                                  )
THEN
    bd13GetNode (dest_info.b_curr, act_root, plmLock_ebd00,
          nr_for_update, dest_info.b_nptr);
(*ENDIF*) 
IF  t^.trError_gg00 = e_ok
THEN
    BEGIN
    remain_len := length;
    REPEAT
        IF  remain_len > sizeof (Buffer)
        THEN
            act_len := sizeof (Buffer)
        ELSE
            act_len := remain_len;
        (*ENDIF*) 
        WITH source_info DO
            IF  (f_lpos + remain_len) < MAX_BSTR_COVERING_BD00
            THEN
                b60read_bytestr (b_nptr.np_ptr, f_lpos, act_len,
                      sizeof (Buffer), @Buffer, 1, t^.trError_gg00)
            ELSE
                b60get_bytestr (b_nptr, f_lpos, act_len, sizeof (Buffer), @Buffer,
                      1, b_curr);
            (*ENDIF*) 
        (*ENDWITH*) 
        IF  t^.trError_gg00 = e_ok
        THEN
            BEGIN
            WITH dest_info DO
                BEGIN
                IF  (b_fpos + act_len) > flen_max
                THEN
                    IF  b_flen <= MAX_BSTR_COVERING_BD00
                    THEN
                        b60rext_bstrroot (b_nptr, b_fpos, act_len,
                              c_use_buffer, fill_char, sizeof (Buffer), @Buffer,
                              1, b_curr)
                    ELSE
                        BEGIN
                        IF  b_nptr.np_ptr^.nd_id <>
                            b_nptr.np_ptr^.nd_root
                        THEN
                            BEGIN
                            b13w_release_node (b_nptr, b_curr);
                            firstcall := true;
                            IF  t^.trError_gg00 = e_ok
                            THEN
                                bd13GetNode (b_curr, act_root, plmLock_ebd00,
                                      nr_for_update, b_nptr);
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        IF  t^.trError_gg00 = e_ok
                        THEN
                            b60extend_bytestr (b_nptr, b_fpos, act_len,
                                  c_use_buffer, fill_char, sizeof (Buffer),
                                  @Buffer, 1, b_curr)
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                ELSE
                    BEGIN
                    IF  NOT extended
                    THEN
                        extended := (b_fpos + act_len) > b_flen;
                    (*ENDIF*) 
                    IF  b_flen <= MAX_BSTR_COVERING_BD00
                    THEN
                        b60rput_bstrroot (b_nptr, b_fpos, act_len,
                              c_use_buffer, fill_char, sizeof (Buffer), @Buffer,
                              1, extended, b_curr)
                    ELSE
                        b60conlput_bstrleaf (b_nptr, b_fpos, act_len,
                              Buffer, firstcall, extended, b_flen, b_curr)
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  t^.trError_gg00 = e_ok
                THEN
                    BEGIN
                    remain_len := remain_len - act_len;
                    b_fpos     := b_fpos + act_len;
                    f_lpos     :=
                          (f_lpos + act_len) MOD MAX_BSTR_COVERING_BD00;
                    IF  (b_nptr.np_ptr = NIL) AND (remain_len > 0)
                    THEN
                        BEGIN
                        firstcall := true;
                        bd13GetNode (b_curr, act_root, plmLock_ebd00,
                              nr_for_update, b_nptr);
                        IF  t^.trError_gg00 = e_ok
                        THEN
                            BEGIN
                            b_flen   := b_nptr.np_ptr^.ndStrFileSize_bd00;
                            flen_max := (b_flen - 1) DIV
                                  MAX_BSTR_COVERING_BD00;
                            flen_max := (flen_max + 1) *
                                  MAX_BSTR_COVERING_BD00
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDWITH*) 
            END
        (*ENDIF*) 
    UNTIL
        (t^.trError_gg00 <> e_ok) OR (remain_len = 0);
    (*ENDREPEAT*) 
    IF  t^.trError_gg00 = e_ok
    THEN
        BEGIN
        WITH source_info DO
            IF  b_nptr.np_ptr <> NIL
            THEN
                IF  (b_nptr.np_ptr^.nd_id <>
                    dest_info.b_curr.curr_tree_id.fileRoot_gg00)
                THEN
                    b13r_release_node (b_nptr, b_curr, lru_normal);
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDWITH*) 
        WITH dest_info DO
            IF  b_nptr.np_ptr <> NIL
            THEN
                b13w_release_node (b_nptr, b_curr)
            (*ENDIF*) 
        (*ENDWITH*) 
        END
    (*ENDIF*) 
    END
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
