.ad 8
.bm 8
.fm 4
.bt $Copyright (c) 2000-2005 SAP AG$$Page %$
.tm 12
.hm 6
.hs 3
.tt 1 $SQL$Project Distributed Database System$VBD17$
.tt 2 $$$
.tt 3 $JuergenP$filedirectory$$2000-05-04$
***********************************************************
.nf
 
 .nf
 
    ========== licence begin  GPL
    Copyright (c) 2000-2005 SAP AG
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end
.fo
 
 
.fo
.nf
.sp
Module  : filedirectory
=========
.sp
Purpose : Complete directory of all existing files
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        VAR
              bd17BlobFdirFileId : tgg00_FileId;
 
        PROCEDURE
              b17add_fdir (VAR fn : tgg00_Filename;
                    VAR fi : tbd_fileinfo;
                    VAR t  : tgg00_TransContext);
 
        PROCEDURE
              b17add_blob_fdir_nolock (
                    VAR current_fdir : tbd_current_tree;
                    VAR fn           : tgg00_Filename;
                    VAR fi           : tbd_fileinfo;
                    VAR t            : tgg00_TransContext);
 
        PROCEDURE
              b17del_fdir (VAR fn   : tgg00_Filename;
                    shared_file     : boolean;
                    VAR t           : tgg00_TransContext);
 
        PROCEDURE
              b17fadd_file_state (
                    VAR t      : tgg00_TransContext;
                    VAR fileId : tgg00_FileId;
                    newState   : tbd_file_state_set);
 
        PROCEDURE
              b17fsub_file_state (
                    VAR t      : tgg00_TransContext;
                    VAR fileId : tgg00_FileId;
                    subState   : tbd_file_state_set);
 
        PROCEDURE
              b17next_del_fdir (VAR prefix : tgg00_Filename;
                    prefix_len      : integer;
                    VAR fn          : tgg00_Filename;
                    VAR fi          : tbd_fileinfo;
                    VAR t           : tgg00_TransContext);
 
        PROCEDURE
              b17repl_fdir (VAR fn : tgg00_Filename;
                    VAR fi      : tbd_fileinfo;
                    shared_file : boolean;
                    VAR t       : tgg00_TransContext);
 
        PROCEDURE
              b17reset_read_only (VAR t : tgg00_TransContext);
 
        PROCEDURE
              b17state_fdir (VAR fn : tgg00_Filename;
                    VAR fi      : tbd_fileinfo;
                    shared_file : boolean;
                    VAR t       : tgg00_TransContext);
 
        PROCEDURE
              bd17AddBlobToFDir (
                    VAR trans : tgg00_TransContext;
                    VAR fn    : tgg00_Filename;
                    VAR fi    : tbd_fileinfo );
 
        PROCEDURE
              bd17CreateBlobFDir (VAR trans : tgg00_TransContext);
 
        FUNCTION
              bd17GetBlobFdirRoot : tsp00_PageNo;
 
        PROCEDURE
              bd17GetNextBlob (
                    VAR trans    : tgg00_TransContext;
                    VAR filename : tgg00_Filename;
                    VAR fileInfo : tbd_fileinfo);
 
        PROCEDURE
              bd17GetBlobFileInfo (
                    VAR trans       : tgg00_TransContext;
                    VAR fileId      : tgg00_FileId;
                    VAR fileVersion : tgg91_FileVersion;
                    VAR fileState   : tbd_file_state_set);
 
        PROCEDURE
              bd17MigrateFdir (
                    VAR t          : tgg00_TransContext;
                    oldFdirRootPNo : tsp00_PageNo);
 
        PROCEDURE
              bd17RestartBlobFdir (
                    VAR t          : tgg00_TransContext;
                    blob_fdir_root : tsp00_PageNo);
 
        PROCEDURE
              bd17RenameFile(
                    VAR trans      : tgg00_TransContext;
                    VAR srcFileId  : tgg00_FileId;
                    VAR destFileId : tgg00_FileId;
                    VAR parent_Id  : tgg00_Surrogate);
 
        PROCEDURE
              bd17VerifyBlobFdir (
                    VAR trans          : tgg00_TransContext;
                    bIsCold            : boolean;
                    bWithExtendedCheck : boolean);
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
        FROM
              nodehandling : VBD13;
 
        PROCEDURE
              b13new_root (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b13w_release_node (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              treehandling : VBD30;
 
        PROCEDURE
              bd30AddToTree (
                    VAR recKey    : tgg00_Lkey;
                    VAR rec       : tgg00_Rec;
                    VAR current   : tbd_current_tree);
 
        PROCEDURE
              bd30BuildCurrent (
                    VAR trans   : tgg00_TransContext;
                    VAR fileId  : tgg00_FileId;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30DelFromTree (
                    VAR recKey  : tgg00_Lkey;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30DropTree (
                    VAR current     : tbd_current_tree;
                    longColumnCount : integer;
                    bOnlyEmpty      : boolean);
 
        PROCEDURE
              b30fdir_to_treeid (VAR fi : tbd_fileinfo;
                    VAR file_id : tgg00_FileId);
 
        PROCEDURE
              bd30GetTree (
                    VAR trans            : tgg00_TransContext;
                    VAR fileId           : tgg00_FileId;
                    VAR current          : tbd_current_tree;
                    messType             : tgg00_MessType;
                    bLockTreeExcl        : boolean;
                    bSynchronizeExclLock : boolean);
 
        PROCEDURE
              bd30GetFromTree (
                    VAR recKey       : tgg00_Lkey;
                    VAR rec          : tgg00_Rec;
                    VAR current      : tbd_current_tree;
                    wantedLock       : tgg00_LockReqMode);
 
        PROCEDURE
              bd30NextFromTree (
                    VAR recKey   : tgg00_Lkey;
                    bInclusive   : boolean;
                    bWithSQLLock : boolean;
                    VAR rec      : tgg00_Rec;
                    VAR current  : tbd_current_tree);
 
        PROCEDURE
              bd30ReleaseSubTree(
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30ReleaseTree (
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30ReplaceInTree (
                    VAR recKey    : tgg00_Lkey;
                    VAR rec       : tgg00_Rec;
                    VAR current   : tbd_current_tree;
                    VAR beforeRef : tgg91_PageRef;
                    VAR updTrans  : tgg91_TransNo);
 
        PROCEDURE
              bd30SubFileState (
                    VAR current : tbd_current_tree;
                    fileState   : tbd_file_state_set);
 
        PROCEDURE
              bd30VerifyTree (
                    VAR trans          : tgg00_TransContext;
                    VAR fileId         : tgg00_FileId;
                    VAR treeStatistic  : tbd00_TreeStatistic;
                    bUpdateConverter   : boolean;
                    bWithExtendedCheck : boolean);
 
      ------------------------------ 
 
        FROM
              InvHandling : VBD300;
 
        PROCEDURE
              bd300SetRootCheck (VAR FileId  : tgg00_FileId);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_1 : VBD01;
 
        VAR
              b01niltree_id : tgg00_FileId;
 
      ------------------------------ 
 
        FROM
              error_text_handling : vbd06;
 
        PROCEDURE
              b06write_filename_and_root (VAR file_id : tgg00_FileId);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        PROCEDURE
              g01optextmsg (msg_prio : tsp3_priority;
                    msg_type  : tsp3_msg_type;
                    msg_no    : tsp00_Int4;
                    msg_label : tsp00_C8;
                    msg_text  : tsp00_C40);
 
      ------------------------------ 
 
        FROM
              GG_cpp_auxiliary_functions : VGG06;
 
        PROCEDURE
              gg06SetNilRef (VAR PageRef : tgg91_PageRef);
 
        PROCEDURE
              gg06SetDummyRef (VAR PageRef : tgg91_PageRef);
 
        PROCEDURE
              gg06SetDummyTrans (VAR TransNo : tgg91_TransNo);
 
      ------------------------------ 
 
        FROM
              GG_edit_routines : VGG17;
 
        PROCEDURE
              g17hexto_line (c : char;
                    VAR ln_len : integer;
                    VAR ln     : tsp_c40);
 
        PROCEDURE
              g17nameto_line (n : tsp00_Name;
                    VAR ln_len  : integer;
                    VAR ln      : tsp_c40);
 
      ------------------------------ 
 
        FROM
              RTE_kernel : VEN101;
 
        PROCEDURE
              vmessage (prio     : tsp3_priority;
                    msg_type     : tsp3_msg_type;
                    msg_no       : tsp00_Int4;
                    msg_label    : tsp00_C8;
                    VAR msg_line : tsp00_C40);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              Test_Procedures : vta01;
 
        PROCEDURE
              t01basis_error (layer : tgg00_Debug;
                    nam   : tsp00_Sname;
                    b_err : tgg00_BasisError);
 
        PROCEDURE
              t01filename (
                    debug : tgg00_Debug;
                    fn    : tgg00_Filename (*ptocSynonym const char**));
 
        PROCEDURE
              t01int4 (debug : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int4     : tsp00_Int4);
&       endif
 
      ------------------------------ 
 
        FROM
              KB_Logging : vkb560;
 
        PROCEDURE
              kb560SetSys1CatalogTreeId(
                    VAR treeId : tgg00_FileId);
 
        PROCEDURE
              kb560SetSys2CatalogTreeId(
                    VAR treeId : tgg00_FileId);
 
      ------------------------------ 
 
        FROM
              KB_restart_record : vkb57;
 
        PROCEDURE
              k57SetSys1CatalogTabId (
                    VAR sys1CatalogTabId : tgg00_Surrogate);
 
        PROCEDURE
              k57SetSys2CatalogTabId (
                    VAR sys2CatalogTabId : tgg00_Surrogate);
 
      ------------------------------ 
 
        FROM
              FileDir_Wrapper : VBD998;
 
        PROCEDURE
              bd998AddFileNoSafetyMargin(
                    taskId          : tsp00_TaskId);
 
        PROCEDURE
              bd998AddFileStatesToEntry(
                    VAR transContext: tgg00_TransContext;
                    VAR table_surr  : tgg00_Surrogate;
                    VAR fileinfo    : tbd_fileinfo;
                    shared_file     : boolean;
                    VAR newState    : tbd_file_state_set);
 
        PROCEDURE
              bd998SubFileStatesFromEntry(
                    VAR transContext: tgg00_TransContext;
                    VAR table_surr  : tgg00_Surrogate;
                    VAR fileinfo    : tbd_fileinfo;
                    shared_file     : boolean;
                    VAR subState    : tbd_file_state_set);
 
        PROCEDURE
              bd998ResetReadOnly(
                    VAR transContext: tgg00_TransContext);
 
        PROCEDURE
              bd998AddToFDir(
                    VAR transContext: tgg00_TransContext;
                    VAR filename    : tgg00_Filename;
                    VAR fileinfo    : tbd_fileinfo);
 
        PROCEDURE
              bd998ConvTableFDirEntry (
                    taskId           : tsp00_TaskId;
                    VAR file_id      : tgg00_FileId;
                    VAR rootPno      : tsp00_PageNo;
                    blobColCount     : tsp00_Int2;
                    VAR fileTypeSet  : tgg00_FiletypeSet;
                    VAR fileVersion  : tgg91_FileVersion);
 
        PROCEDURE
              bd998ConvIndexFDirEntry (
                    taskId           : tsp00_TaskId;
                    VAR file_id      : tgg00_FileId;
                    VAR rootPno      : tsp00_PageNo;
                    VAR fileTypeSet  : tgg00_FiletypeSet;
                    VAR fileVersion  : tgg91_FileVersion);
 
        PROCEDURE
              bd998ConvShortColFDirEntry (
                    taskId           : tsp00_TaskId;
                    VAR file_id      : tgg00_FileId;
                    VAR rootPno      : tsp00_PageNo;
                    VAR fileTypeSet  : tgg00_FiletypeSet;
                    VAR fileVersion  : tgg91_FileVersion);
 
        PROCEDURE
              bd998DelFDirEntry(
                    VAR transContext: tgg00_TransContext;
                    VAR filename    : tgg00_Filename;
                    VAR fileinfo    : tbd_fileinfo;
                    shared_file     : boolean);
 
        PROCEDURE
              bd998GetFDirEntry(
                    VAR transContext: tgg00_TransContext;
                    VAR filename    : tgg00_Filename;
                    VAR fileinfo    : tbd_fileinfo;
                    shared_file     : boolean;
                    VAR entryhandle : tsp00_MoveObjPtr);
 
        PROCEDURE
              bd998ReleaseFDirEntry(
                    VAR transContext: tgg00_TransContext;
                    VAR entryhandle : tsp00_MoveObjPtr;
                    shared_file     : boolean);
 
        PROCEDURE
              bd998GetFDirEntryFileinfo(
                    VAR transContext: tgg00_TransContext;
                    VAR filename    : tgg00_Filename;
                    VAR fileinfo    : tbd_fileinfo;
                    shared_file     : boolean);
 
        PROCEDURE
              bd998SetFDirEntry(
                    VAR transContext: tgg00_TransContext;
                    VAR fileinfo    : tbd_fileinfo;
                    VAR entryhandle : tsp00_MoveObjPtr);
 
        PROCEDURE
              bd998SetFDirMigrationFinished;
 
        PROCEDURE
              bd998SetFDirMigrationRunning;
 
      ------------------------------ 
 
        FROM
              filesysteminterface_5 : VBD05;
 
        PROCEDURE
              bd05ModifyFdirLength (
                    VAR trans        : tgg00_TransContext;
                    bDoIncrement     : boolean;
                    VAR fileId       : tgg00_FileId;
                    VAR parentFileNo : tgg00_Surrogate );
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
        PROCEDURE
              g17hexto_line;
 
              tsp00_Line tsp_c40
 
        PROCEDURE
              g17nameto_line;
 
              tsp00_Line tsp_c40
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : JuergenP
.sp
.cp 3
Created : 1983-03-14
.sp
.cp 3
.sp
.cp 3
Release :      Date : 2000-05-04
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
 
The file directory contains exactly one entry for each file created.
Each entry consists of the file's unambiguous file name fn and
file information fi.  File information describes the file type
(temporary or permanent), the key type (variable or fixed length)
and the page number for the root of the B* tree used to manage the
file's index and entries.
.sp
The task of the file directory is to maintain a record of which
file names belong to created files and which B* tree belongs
to which created file.  Such information is required
almost every time a file-system command is called!
.sp 2
   b17create_fdir(t,e)
.sp
Must be called during system generation.  Afterwards, the file
directory does not (yet) contain any entries.
.br
Possible acknowledgements in e:
   - e_ok
   - b_disk_not_accessible.
.sp 2
   b17restart_fdir(t,e)
.sp
Must be called each time the system is restarted.  Afterwards, the
file directory contains exactly one entry for each created
permanent file.
.br
Possible acknowledgements in e:
   - e_ok
   - b_disk_not_accessible.
.sp 2
   b17add_fdir(fn,fi,t,e)
.sp
Forms a new entry from fn and fi and inserts it in the file
directory, if it has been determined that there is no other entry
with the same name already present and if there is enough
space available for a new entry.  If fn is the name of a permanent
file, a check is always run to determine whether the directory
already contains an entry with this name; if the entry is for a
temporary file, the file directory can take on an undefined status
if the unambiguousness of fn is not ensured by the calling
environment.
.br
Possible acknowledgements in e:
   - e_ok
   - b_duplicate_filename
   - b_too_many_files
   - b_disk_not_accessible.
.sp 2
   b17repl_fdir(fn,fi,t,e)
.sp
Replaces the previous file information with the new file
information fi in the entry with the file name fn, if such
an entry is present.  However, the file type must not be changed
in the process (otherwise, b_file_not_found is sent).
.br
Possible acknowledgements in e:
   - e_ok
   - b_file_unloaded
   - b_file_not_found
   - b_disk_not_accessible.
.sp 2
   b17del_fdir(fn,fi,t);
.sp
Deletes the entry with the file name fn from the file directory,
if such an entry is present.
.br
Possible acknowledgements in e:
   - e_ok
   - b_file_not_found
   - b_disk_not_accessible.
.sp 2
   b17next_del_fdir(prefix,fn,fi,t,e);
.sp
Searches the file directory for a file name with the prefix
'prefix'.  If such an entry is found, this entry with the file
name fn is removed from the file directory.
.br
Possible acknowledgements in e:
   - e_ok
   - b_file_not_found
   - b_disk_not_accessible.
.sp 2
   b17state_fdir(fn,fi,t,e)
.sp
Searches directory for the entry with the file name fn.  If such
an entry is present, its file information fi is fetched.
.br
Possible acknowledgements in e:
   - e_ok
   - b_file_unloaded
   - b_file_not_found
   - b_disk_not_accessible.
.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
 
Due to the fact that a read access to the file directory takes
place almost every time a file-system command is called,
the file directory must be efficiently implemented.  In addition,
information concerning permanent files must also be retained
during the period between system shutdown and restart.
For this reason, the file directory is partially kept on secondary
storage (disk filedirectory) and partially kept in main memory (flist).
.sp
The entries of permanent files are located in the external
directory at all times during their existence.  They are copied
to the internal card file only during b17get_fdir.  The entries
of temporary files are normally located in the internal directory
(flist) only.  They may, within the framework of the displacement
algorithm (see below), be transferred to the external directory and
remain there only until they are reinserted in the internal directory
with b17get_fdir (implicit); in the process, the corresponding
internal entry is either set to 'false' or it is
permanently removed from the file directory with b17del_fdir.
This means that temporary file entries are always either in the
internal card file or in the external directory (whereas permanent
file entries can be in both locations).
.sp
In order to avoid accesses to the external directory as much as
possible during system operation, the internal directory should be
allocated a relatively large space (flistsize).
.sp
The internal directory consists of a cyclic list that is
implemented via an ARRAY (entry):  each ARRAY element contains
a field 'next' in which the index of the following element is
indicated, and a field 'prev' indicating the predecessor.  The
variables 'first' and 'last' contain the index for the first and
last list elements used by a file entry; the current number of list
elements being used is maintained in 'count'.  Beginning with
'first', the (nonempty) list contains, first of all, all used
elements (up to 'last') and then the unused elements, with the last
unused element pointing to the first.
.sp
Within the used section of the list, the elements are sorted
according to frequency of access, i.e. file names that are often
referenced are at the head of the list (self organizing list).
The greater the size of the internal directory, the more
advantages this type of organization offers.  The call
b19search_flist(fn,fi,found) registers either found = TRUE and
sends the file entry with the file name fn to fi, or it registers
found = FALSE; if TRUE, the element that is being searched for is
moved to the first position in the list.
.sp
If the internal directory is full and another entry must be
inserted, the last list entry is removed.  If this last entry that
is to be displaced belongs to a temporary file, it is stored to
the external directory.  The new entry is placed in the first position.
This displacement strategy prevents the external storage of file
entries that tend to be referenced often.
.sp
If one of the routines in e does not return e_ok, the state of
the file directory is still consistent.  This is achieved by
changes in the internal card file not being executed until the
external directory has been successfully processed and by the
external directory always being in a consistent state.
.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    :
 
 
(*************************************************************************)
(*                                                                       *)
(*                           new file directory                          *)
(*                                                                       *)
(*************************************************************************)
CONST
      MSG_RESTART        = 'LOB file directory restart successful   ';
      c_inclusive        = true;
      c_withSQLLock      = true;
      (* *)
 
 
(*------------------------------*) 
 
PROCEDURE
      bd17AddBlobToFDir (
            VAR trans : tgg00_TransContext;
            VAR fn    : tgg00_Filename;
            VAR fi    : tbd_fileinfo );
 
VAR
      fileId       : tgg00_FileId;
      current_fdir : tbd_current_tree;
 
BEGIN
&ifdef TRACE
t01filename (bi, fn);
&endif
WITH trans DO
    BEGIN
    trError_gg00          := e_ok;
    fileId                := bd17BlobFdirFileId;
    fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 + [bd_write_acc];
    bd30GetTree (trans, fileId, current_fdir, m_insert,
          NOT LOCK_TREE_EXCL_BD00, SYNC_TREE_LOCK_BD00);
    IF  trError_gg00 = e_ok
    THEN
        bd17_AddFdir (fn, fi, current_fdir);
    (*ENDIF*) 
    bd30ReleaseTree (current_fdir);
    fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 - [bd_write_acc];
    END;
(*ENDWITH*) 
&ifdef TRACE
t01filename (bi, fn);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd17CreateBlobFDir (VAR trans : tgg00_TransContext);
 
VAR
      nptr         : tbd_node_ptrs;
      current_fdir : tbd_current_tree;
 
BEGIN
WITH trans DO
    BEGIN
    trError_gg00  := e_ok;
    nptr.np_ptr   := NIL;
    nptr.np_cbptr := NIL;
    bd17_InitBlobFdirFileId;
    bd30BuildCurrent (trans, bd17BlobFdirFileId, current_fdir);
    b13new_root (nptr, current_fdir);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        bd17BlobFdirFileId.fileRoot_gg00 := nptr.np_ptr^.nd_id;
        nptr.np_ptr^.nd_pmode    := nptr.np_ptr^.nd_pmode + [pmFdir_egg00];
        nptr.np_ptr^.nd_trailer  := nptr.np_ptr^.nd_header;
        b13w_release_node (nptr, current_fdir);
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17add_fdir (VAR fn : tgg00_Filename;
            VAR fi : tbd_fileinfo;
            VAR t  : tgg00_TransContext);
 
VAR
      fileId        : tgg00_FileId;
      current_fdir : tbd_current_tree;
 
BEGIN
&ifdef TRACE
t01filename (bi, fn);
&endif
WITH t DO
    BEGIN
    trError_gg00 := e_ok;
    IF  bd17_IsInBlobFdir( fn )
    THEN
        BEGIN
        fileId                := bd17BlobFdirFileId;
        fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 + [bd_write_acc];
        bd30GetTree (t, fileId, current_fdir, m_insert,
              NOT LOCK_TREE_EXCL_BD00, SYNC_TREE_LOCK_BD00);
        IF  trError_gg00 = e_ok
        THEN
            b17add_blob_fdir_nolock (current_fdir, fn, fi, t);
        (*ENDIF*) 
        bd30ReleaseTree (current_fdir);
        fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 - [bd_write_acc];
        END
    ELSE
        bd998AddToFDir (t, fn, fi);
    (*ENDIF*) 
    END;
(*ENDWITH*) 
&ifdef TRACE
t01filename (bi, fn);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17del_fdir (
            VAR fn      : tgg00_Filename;
            shared_file : boolean;
            VAR t       : tgg00_TransContext);
 
VAR
      fi      : tbd_fileinfo;
      fileId  : tgg00_FileId;
      current : tbd_current_tree;
 
BEGIN
&ifdef TRACE
t01filename (bi, fn);
&endif
WITH t DO
    BEGIN
    trError_gg00 := e_ok;
    IF  bd17_IsInBlobFdir( fn )
    THEN
        BEGIN
        fileId                := bd17BlobFdirFileId;
        fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 + [bd_write_acc];
        bd30GetTree (t, fileId, current, m_delete,
              NOT LOCK_TREE_EXCL_BD00, SYNC_TREE_LOCK_BD00);
        IF  trError_gg00 = e_ok
        THEN
            bd17_DelFdir (fn, current);
        (*ENDIF*) 
        bd30ReleaseTree (current);
        fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 - [bd_write_acc];
        END
    ELSE
        bd998DelFDirEntry (t, fn, fi, shared_file);
    (*ENDIF*) 
    END;
(*ENDWITH*) 
&ifdef TRACE
t01filename (bi, fn);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17add_blob_fdir_nolock (
            VAR current_fdir : tbd_current_tree;
            VAR fn           : tgg00_Filename;
            VAR fi           : tbd_fileinfo;
            VAR t            : tgg00_TransContext);
 
BEGIN
t.trError_gg00 := e_ok;
bd17_AddFdir (fn, fi, current_fdir);
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17fadd_file_state (
            VAR t      : tgg00_TransContext;
            VAR fileId : tgg00_FileId;
            newState   : tbd_file_state_set);
 
VAR
      shared_file       : boolean;
      found             : boolean;
      fi                : tbd_fileinfo;
      fDirFileId        : tgg00_FileId;
      current_fdir      : tbd_current_tree;
 
BEGIN
&ifdef TRACE
t01filename (bi, fileId.fileName_gg00);
&endif
WITH t  DO
    BEGIN
    trError_gg00 := e_ok;
    found        := false;
    shared_file  := (ftsShared_egg00 IN fileId.fileType_gg00);
    IF  bd17_IsInBlobFdir( fileId.fileName_gg00 )
    THEN
        BEGIN
        fDirFileId                := bd17BlobFdirFileId;
        fDirFileId.fileBdUse_gg00 := fDirFileId.fileBdUse_gg00 + [bd_write_acc];
        bd30GetTree (t, fDirFileId, current_fdir, m_set,
              NOT LOCK_TREE_EXCL_BD00, NOT SYNC_TREE_LOCK_BD00);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            bd17_SearchFdir (fileId.fileName_gg00, fi, current_fdir);
            bd30ReleaseSubTree (current_fdir);
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            fi.fi_state := fi.fi_state + newState;
            bd17_ReplFdir (fileId.fileName_gg00, fi, current_fdir);
            END;
        (*ENDIF*) 
        bd30ReleaseTree (current_fdir);
        fDirFileId.fileBdUse_gg00 := fDirFileId.fileBdUse_gg00 - [bd_write_acc];
        END
    ELSE
        BEGIN
        bd998AddFileStatesToEntry ( t, fileId.fileTabId_gg00,
              fi, shared_file, newState);
        END;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17fsub_file_state (
            VAR t      : tgg00_TransContext;
            VAR fileId : tgg00_FileId;
            subState   : tbd_file_state_set);
 
VAR
      shared_file  : boolean;
      found        : boolean;
      fi           : tbd_fileinfo;
      fDirFileId   : tgg00_FileId;
      current_fdir : tbd_current_tree;
 
BEGIN
&ifdef TRACE
t01filename (bi, fileId.fileName_gg00);
&endif
WITH t DO
    BEGIN
    trError_gg00 := e_ok;
    found        := false;
    shared_file  := (ftsShared_egg00 IN fileId.fileType_gg00);
    IF  bd17_IsInBlobFdir( fileId.fileName_gg00 )
    THEN
        BEGIN
        fDirFileId := bd17BlobFdirFileId;
        fDirFileId.fileBdUse_gg00 := fDirFileId.fileBdUse_gg00 + [bd_write_acc];
        bd30GetTree (t, fDirFileId, current_fdir, m_set,
              NOT LOCK_TREE_EXCL_BD00, NOT SYNC_TREE_LOCK_BD00);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            bd17_SearchFdir (fileId.fileName_gg00, fi, current_fdir);
            bd30ReleaseSubTree (current_fdir);
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            fi.fi_state := fi.fi_state - subState;
            bd17_ReplFdir (fileId.fileName_gg00, fi, current_fdir);
            END;
        (*ENDIF*) 
        bd30ReleaseTree (current_fdir);
        fDirFileId.fileBdUse_gg00 := fDirFileId.fileBdUse_gg00 - [bd_write_acc];
        END
    ELSE
        BEGIN
        bd998SubFileStatesFromEntry ( t, fileId.fileTabId_gg00,
              fi, shared_file, subState);
        END;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17next_del_fdir (
            VAR prefix : tgg00_Filename;
            prefix_len : integer;
            VAR fn     : tgg00_Filename;
            VAR fi     : tbd_fileinfo;
            VAR t      : tgg00_TransContext);
 
VAR
      fileId       : tgg00_FileId;
      current_fdir : tbd_current_tree;
 
BEGIN
(* this procedure is called only by b01prefix_destroy_files
      and only accesses the b17LongFdirFileId *)
WITH t DO
    BEGIN
    trError_gg00          := e_ok;
    fileId                := bd17BlobFdirFileId;
    fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 + [bd_write_acc];
    bd30GetTree (t, fileId, current_fdir, m_delete,
          NOT LOCK_TREE_EXCL_BD00, SYNC_TREE_LOCK_BD00);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        bd17_NextFdir (fn, fi, current_fdir);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  bd17is_prefix (prefix, fn, prefix_len)
            THEN
                BEGIN
                bd17_DelFdir (fn, current_fdir);
                END
            ELSE
                trError_gg00 := e_file_not_found
            (*ENDIF*) 
            END
        ELSE
            IF  trError_gg00 = e_no_next_record
            THEN
                trError_gg00 := e_file_not_found;
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    bd30ReleaseTree (current_fdir);
    fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 - [bd_write_acc];
    END;
(*ENDWITH*) 
&ifdef TRACE
t01filename (bi, fn);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17repl_fdir (VAR fn : tgg00_Filename;
            VAR fi      : tbd_fileinfo;
            shared_file : boolean;
            VAR t       : tgg00_TransContext);
 
VAR
      entryhandle       : tsp00_MoveObjPtr;
      dummy_fi          : tbd_fileinfo;
      fileId            : tgg00_FileId;
      current_fdir      : tbd_current_tree;
 
BEGIN
&ifdef TRACE
t01filename (bi, fn);
&endif
t.trError_gg00 := e_ok;
WITH t DO
    BEGIN
    IF  bd17_IsInBlobFdir( fn )
    THEN
        BEGIN
        fileId                := bd17BlobFdirFileId;
        fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 + [bd_write_acc];
        bd30GetTree (t, fileId, current_fdir, m_update,
              NOT LOCK_TREE_EXCL_BD00, NOT SYNC_TREE_LOCK_BD00);
        IF  trError_gg00 = e_ok
        THEN
            bd17_ReplFdir (fn, fi, current_fdir);
        (*ENDIF*) 
        bd30ReleaseTree (current_fdir);
        fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 - [bd_write_acc];
        END
    ELSE
        BEGIN
        bd998GetFDirEntry (t, fn, dummy_fi, shared_file, entryhandle);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            bd998SetFDirEntry (t, fi, entryhandle);
            bd998ReleaseFDirEntry (t, entryhandle, shared_file);
            END;
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
&ifdef TRACE
t01filename (bi, fn);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17reset_read_only (VAR t : tgg00_TransContext);
 
VAR
      len           : integer;
      id_pos        : integer;
      ro_tfn        : tgg00_Tfn;
      fi            : tbd_fileinfo;
      n             : tsp00_Name;
      msg           : tsp00_C40;
      file_id       : tgg00_FileId;
      fDirFileId    : tgg00_FileId;
      current       : tbd_current_tree;
      current_fdir  : tbd_current_tree;
 
BEGIN
WITH t DO
    BEGIN
    file_id    := b01niltree_id;
    ro_tfn     := tfnColumn_egg00;
    fDirFileId := bd17BlobFdirFileId;
    file_id.fileName_gg00 [ 1 ] := chr (ord (ro_tfn));
    (* *)
    fDirFileId.fileBdUse_gg00 := fDirFileId.fileBdUse_gg00 + [bd_write_acc];
    bd30GetTree (t, fDirFileId, current_fdir, m_set,
          LOCK_TREE_EXCL_BD00, NOT SYNC_TREE_LOCK_BD00);
    REPEAT
        bd17_NextFdir (file_id.fileName_gg00, fi, current_fdir);
        IF  trError_gg00 = e_ok
        THEN
            IF  file_id.fileName_gg00 [ 1 ] =  chr (ord (ro_tfn))
            THEN
                BEGIN
                IF  f_read_only in fi.fi_state
                THEN
                    BEGIN
                    bd30ReleaseTree (current_fdir);
                    b30fdir_to_treeid (fi, file_id);
                    bd30GetTree (t, file_id, current, m_set,
                          LOCK_TREE_EXCL_BD00, NOT SYNC_TREE_LOCK_BD00);
                    IF  trError_gg00 = e_ok
                    THEN
                        bd30SubFileState (current, [ f_read_only ]);
                    (*ENDIF*) 
                    bd30ReleaseTree (current);
                    IF  trError_gg00 = e_ok
                    THEN
                        bd30GetTree (t, fDirFileId, current_fdir, m_set,
                              LOCK_TREE_EXCL_BD00, NOT SYNC_TREE_LOCK_BD00);
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        fi.fi_state := fi.fi_state - [ f_read_only ];
                        bd17_ReplFdir (file_id.fileName_gg00, fi, current_fdir);
                        n   := 'RESET 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 (file_id.fileName_gg00 [id_pos], len, msg);
                            IF  id_pos = 2
                            THEN
                                len := len + 1;
                            (*ENDIF*) 
                            END;
                        (*ENDFOR*) 
                        vmessage (sp3p_knldiag, sp3m_info, csp3_b17_1_reset_read_only,csp3_n_btree, msg);
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            ELSE
                trError_gg00 := e_no_next_record
            (*ENDIF*) 
        (*ENDIF*) 
    UNTIL
        (trError_gg00 <> e_ok);
    (*ENDREPEAT*) 
    IF  trError_gg00 = e_no_next_record
    THEN
        trError_gg00 := e_ok;
    (*ENDIF*) 
    bd30ReleaseTree (current_fdir);
    fDirFileId.fileBdUse_gg00 := fDirFileId.fileBdUse_gg00 - [bd_write_acc];
    END;
(*ENDWITH*) 
bd998ResetReadOnly (t);
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd17RestartBlobFdir (
            VAR t          : tgg00_TransContext;
            blob_fdir_root : tsp00_PageNo);
 
BEGIN
t.trError_gg00 := e_ok;
bd17_InitBlobFdirFileId;
bd17BlobFdirFileId.fileRoot_gg00 := blob_fdir_root;
g01optextmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
      csp3_n_btree, MSG_RESTART)
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17state_fdir (
            VAR fn      : tgg00_Filename;
            VAR fi      : tbd_fileinfo;
            shared_file : boolean;
            VAR t       : tgg00_TransContext);
 
VAR
      fileId       : tgg00_FileId;
      current_fdir : tbd_current_tree;
 
BEGIN
&ifdef TRACE
t01filename (bi, fn);
&endif
WITH t DO
    BEGIN
    trError_gg00 := e_ok;
    IF  bd17_IsInBlobFdir( fn )
    THEN
        BEGIN
        fileId := bd17BlobFdirFileId;
        bd30GetTree (t, fileId, current_fdir, m_get,
              NOT LOCK_TREE_EXCL_BD00, NOT SYNC_TREE_LOCK_BD00);
        IF  trError_gg00 = e_ok
        THEN
            bd17_SearchFdir (fn, fi, current_fdir);
        (*ENDIF*) 
        bd30ReleaseTree (current_fdir);
        IF  trError_gg00 <> e_ok
        THEN
            WITH fi DO
                BEGIN
                fi_type := [ ftsTemp_egg00 ];
                fi_root := NIL_PAGE_NO_GG00
                END
            (*ENDWITH*) 
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        bd998GetFDirEntryFileinfo (t, fn, fi, shared_file);
        IF  trError_gg00 <> e_ok
        THEN
            WITH fi DO
                BEGIN
                fi_type := [ ftsTemp_egg00 ];
                fi_root := NIL_PAGE_NO_GG00;
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
&ifdef TRACE
t01filename (bi, fn);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd17GetBlobFileInfo (
            VAR trans       : tgg00_TransContext;
            VAR fileId      : tgg00_FileId;
            VAR fileVersion : tgg91_FileVersion;
            VAR fileState   : tbd_file_state_set);
 
VAR
      fileInfo : tbd_fileinfo;
 
BEGIN
trans.trError_gg00 := e_ok;
b17state_fdir (fileId.fileName_gg00, fileInfo,
      ftsShared_egg00 IN fileId.fileType_gg00, trans);
IF  trans.trError_gg00 = e_ok
THEN
    BEGIN
    fileId.fileRoot_gg00 := fileInfo.fi_root;
    fileId.fileType_gg00 := fileInfo.fi_type;
    fileVersion          := fileInfo.fi_vers;
    fileState            := fileInfo.fi_state;
    IF  fileId.fileRoot_gg00 = NIL_PAGE_NO_GG00
    THEN
        fileId.fileRootCheck_gg00 := ROOT_CHECK_GG00
    ELSE
        bd300SetRootCheck (fileId);
    (*ENDIF*) 
&   ifdef trace
    t01int4 (bi, '30n_root_che', fileId.fileRootCheck_gg00);
&   endif
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd17GetBlobFdirRoot : tsp00_PageNo;
 
BEGIN
bd17GetBlobFdirRoot := bd17BlobFdirFileId.fileRoot_gg00;
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd17GetNextBlob (
            VAR trans    : tgg00_TransContext;
            VAR filename : tgg00_Filename;
            VAR fileInfo : tbd_fileinfo);
 
VAR
      auxFilename  : tgg00_Filename;
      fileId       : tgg00_FileId;
      current_fdir : tbd_current_tree;
 
BEGIN
&ifdef TRACE
t01filename (bi, filename);
&endif
WITH trans DO
    BEGIN
    trError_gg00 := e_ok;
    auxFilename  := filename;
    fileId       := bd17BlobFdirFileId;
    bd30GetTree (trans, fileId, current_fdir, m_get,
          NOT LOCK_TREE_EXCL_BD00, NOT SYNC_TREE_LOCK_BD00);
    IF  trError_gg00 = e_ok
    THEN
        bd17_NextFdir (auxFilename, fileInfo, current_fdir);
    (*ENDIF*) 
    bd30ReleaseTree (current_fdir);
    IF  trError_gg00 = e_ok
    THEN
        filename := auxFilename;
    (*ENDIF*) 
    IF  trError_gg00 = e_no_next_record
    THEN
        trError_gg00 := e_file_not_found;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
&ifdef TRACE
t01filename (bi, filename);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd17RenameFile(
            VAR trans      : tgg00_TransContext;
            VAR srcFileId  : tgg00_FileId;
            VAR destFileId : tgg00_FileId;
            VAR parent_Id  : tgg00_Surrogate);
 
VAR
      srcFileInfo  : tbd_fileinfo;
      destFileInfo : tbd_fileinfo;
      fileDirId    : tgg00_FileId;
      currFileDir  : tbd_current_tree;
 
BEGIN
(* only for blobs and temporary files *)
WITH trans DO
    BEGIN
    b17state_fdir (srcFileId.fileName_gg00, srcFileInfo,
          ftsShared_egg00 IN srcFileId.fileType_gg00, trans);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        b17state_fdir (destFileId.fileName_gg00, destFileInfo,
              ftsShared_egg00 IN destFileId.fileType_gg00, trans);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  destFileInfo.fi_root = srcFileInfo.fi_root
            THEN
                BEGIN
                (* *)
                (* old was already renamed before *)
                (* *)
                destFileId.fileRoot_gg00 := srcFileInfo.fi_root;
                destFileId.fileType_gg00 := srcFileInfo.fi_type;
                (* *)
                b17del_fdir (srcFileId.fileName_gg00,
                      ftsShared_egg00 IN srcFileId.fileType_gg00, trans)
                END
            ELSE
                trError_gg00 := e_duplicate_filename
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            IF  trError_gg00 = e_file_not_found
            THEN
                BEGIN
                trError_gg00             := e_ok;
                destFileInfo             := srcFileInfo;
                fileDirId                := bd17BlobFdirFileId;
                fileDirId.fileBdUse_gg00 := fileDirId.fileBdUse_gg00 + [bd_write_acc];
                (* *)
                bd30GetTree (trans, fileDirId, currFileDir, m_insert,
                      NOT LOCK_TREE_EXCL_BD00, SYNC_TREE_LOCK_BD00);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    IF  bd17_IsInBlobFdir( destFileId.fileName_gg00 )
                    THEN
                        BEGIN
                        bd17_AddFdir (destFileId.fileName_gg00, destFileInfo,
                              currFileDir);
                        bd30ReleaseSubTree (currFileDir);
                        END
                    ELSE
                        bd998AddToFDir (trans, destFileId.fileName_gg00, destFileInfo);
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    destFileId.fileRoot_gg00 := srcFileInfo.fi_root;
                    destFileId.fileType_gg00 := srcFileInfo.fi_type;
                    (* *)
                    IF  bd17_IsInBlobFdir( srcFileId.fileName_gg00 )
                    THEN
                        BEGIN
                        (* set root to avoid look-up in fdir during      *)
                        (* bd05ModifyFdirLength because we already have  *)
                        (* a share lock on the lob fdir root and another *)
                        (* lock request might result in a deadlock       *)
                        srcFileId.fileRoot_gg00 := srcFileInfo.fi_root;
                        IF  ((srcFileId.fileTfn_gg00 = tfnAux_egg00) OR
                            (srcFileId.fileTfn_gg00 = tfnTempAux_egg00))
                        THEN
                            bd05ModifyFdirLength(trans, true, srcFileId,
                                  parent_Id)
                        ELSE
                            bd05ModifyFdirLength(trans, false, srcFileId,
                                  parent_Id);
                        (*ENDIF*) 
                        bd17_DelFdir (srcFileId.fileName_gg00, currFileDir)
                        END
                    ELSE
                        bd998DelFDirEntry (trans, srcFileId.fileName_gg00,
                              srcFileInfo,
                              ftsShared_egg00 IN srcFileId.fileType_gg00);
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                bd30ReleaseTree (currFileDir);
                fileDirId.fileBdUse_gg00 := fileDirId.fileBdUse_gg00
                      - [bd_write_acc]
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd17VerifyBlobFdir (
            VAR trans          : tgg00_TransContext;
            bIsCold            : boolean;
            bWithExtendedCheck : boolean);
 
VAR
      treeStatistic : tbd00_TreeStatistic;
      fileId        : tgg00_FileId;
 
BEGIN
fileId := bd17BlobFdirFileId;
bd30VerifyTree (trans, fileId, treeStatistic, bIsCold, bWithExtendedCheck);
&ifdef TRACE
IF  trans.trError_gg00 = e_ok
THEN
    BEGIN
    t01int4 (bi, 'indexPages  ', treeStatistic.ts_IndexPages_bd00);
    t01int4 (bi, 'leafPages   ', treeStatistic.ts_LeafPages_bd00);
    t01int4 (bi, 'fdir entries', treeStatistic.ts_RecordCount_bd00);
    END;
&endif
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd17is_prefix (VAR prefix : tgg00_Filename;
            fn         : tgg00_Filename;
            prefix_len : integer) : boolean;
 
VAR
      comp : boolean;
      i    : integer;
 
BEGIN
comp := true;
i    := 0;
REPEAT
    i := i + 1;
    IF  prefix [ i ] <> fn [ i ]
    THEN
        comp := false
    (*ENDIF*) 
UNTIL
    (NOT comp) OR (i = prefix_len);
(*ENDREPEAT*) 
bd17is_prefix := comp
END;
 
(*------------------------------*) 
 
FUNCTION
      bd17_IsInBlobFdir (VAR fileName : tgg00_Filename) : boolean;
 
BEGIN
bd17_IsInBlobFdir := (
      (fileName[ 1 ] = chr (ord (tfnColumn_egg00    ))) OR
      (fileName[ 1 ] = chr (ord (tfnAux_egg00       ))) OR
      (fileName[ 1 ] = chr (ord (tfnTempAux_egg00))))
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd17MigrateFdir (
            VAR t          : tgg00_TransContext;
            oldFdirRootPNo : tsp00_PageNo);
 
CONST
      c_noLiveCacheMig1 = 'file directory migration is not         ';
      c_noLiveCacheMig2 = 'possible for liveCache objects          ';
      c_wrong_entry_msg = 'unexpected file directory entry:        ';
      c_fileName        = 'file name:                              ';
      c_sys1_catalog_id = '\00\00\00\00\00\00\00\01';
      c_sys2_catalog_id = '\00\00\00\00\00\00\00\02';
      (* maximum number of bad entries that are written to knldiag before *)
      (* migration is aborted                                             *)
      c_maxBadEntryOutput = 20;
 
VAR
      abortMig         : boolean;
      badEntryCount    : integer;
      ErrorRoot        : tsp00_PageNo;
      table_surr       : tgg00_Surrogate;
      fi               : tbd_fileinfo;
      permFileDir_id   : tgg00_FileId;
      file_id          : tgg00_FileId;
      current_fdir     : tbd_current_tree;
 
BEGIN
ErrorRoot       := NIL_PAGE_NO_GG00;
WITH t DO
    BEGIN
    bd998SetFDirMigrationRunning;
    (* init old fdir file id *)
    permFileDir_id                := b01niltree_id;
    permFileDir_id.fileType_gg00  := [ftsPerm_egg00, ftsConcurrent_egg00];
    permFileDir_id.fileBdUse_gg00 := [];
    permFileDir_id.fileTfn_gg00   := tfnTable_egg00;
    permFileDir_id.fileRoot_gg00  := oldFdirRootPNo;
    (* *)
    file_id                := permFileDir_id;
    file_id.fileBdUse_gg00 := file_id.fileBdUse_gg00 + [bd_write_acc];
    bd30GetTree (t, file_id, current_fdir, m_nil,
          LOCK_TREE_EXCL_BD00, SYNC_TREE_LOCK_BD00);
    (* first pass, convert table entries (this implicitely sets *)
    (* highest fileNo used)                                     *)
    file_id.fileName_gg00 := cgg_zero_fn;
    badEntryCount         := 0;
    abortMig              := false;
    IF  trError_gg00 = e_ok
    THEN
        REPEAT
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                bd17_NextFdir (file_id.fileName_gg00, fi, current_fdir);
                b30fdir_to_treeid (fi, file_id);
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_no_next_record
            THEN
                trError_gg00 := e_file_not_found;
            (*ENDIF*) 
            IF  (trError_gg00 = e_ok)                   AND
                ((file_id.fileTfn_gg00 = tfnTable_egg00) OR
                (file_id.fileTfn_gg00  = tfnSys_egg00))
            THEN
                BEGIN
                IF  file_id.fileTfn_gg00  = tfnSys_egg00
                THEN
                    BEGIN
                    IF  file_id.fileTabId_gg00 = c_sys1_catalog_id
                    THEN
                        kb560SetSys1CatalogTreeId (file_id)
                    ELSE
                        IF  file_id.fileTabId_gg00 = c_sys2_catalog_id
                        THEN
                            kb560SetSys2CatalogTreeId (file_id);
                        (*ENDIF*) 
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                bd998ConvTableFDirEntry (t.trTaskId_gg00, file_id, fi.fi_root,
                      fi.fi_col_cnt, fi.fi_type, fi.fi_vers);
                END;
            (* make sure we only have entries that will be converted *)
            (*ENDIF*) 
            CASE file_id.fileTfn_gg00 OF
                tfnTable_egg00,
                tfnSys_egg00,
                tfnMulti_egg00,
                tfnShortScol_egg00,
                tfnOmsInv_egg00:
                    BEGIN
                    (* *)
                    END;
                tfnObj_egg00,
                tfnContObj_egg00:
                    BEGIN
                    g01optextmsg (sp3p_knldiag, sp3m_error,
                          BD17_FDIR_MIGRATION_SP03, csp3_n_migration,
                          c_noLiveCacheMig1);
                    g01optextmsg (sp3p_knldiag, sp3m_error,
                          BD17_FDIR_MIGRATION_SP03, csp3_n_migration,
                          c_noLiveCacheMig2);
                    g01optextmsg (sp3p_knldiag, sp3m_error,
                          BD17_FDIR_MIGRATION_SP03, csp3_n_migration,
                          c_fileName);
                    b06write_filename_and_root (file_id);
                    badEntryCount := succ (badEntryCount);
                    abortMig := true;
                    END;
                tfnAux_egg00,
                tfnTempAux_egg00:
                    (* PTS 1132508 M.Ki. *)
                    (* dropped files; will be deleted during restart *)
                    b17add_fdir (file_id.fileName_gg00, fi, t);
                OTHERWISE
                    BEGIN
                    g01optextmsg (sp3p_knldiag, sp3m_error,
                          BD17_FDIR_MIGRATION_SP03, csp3_n_migration,
                          c_wrong_entry_msg);
                    g01optextmsg (sp3p_knldiag, sp3m_error,
                          BD17_FDIR_MIGRATION_SP03, csp3_n_migration,
                          c_fileName);
                    b06write_filename_and_root (file_id);
                    badEntryCount := succ (badEntryCount);
                    abortMig := true;
                    END;
                END;
            (*ENDCASE*) 
        UNTIL
            (trError_gg00 <> e_ok) OR (badEntryCount > c_maxBadEntryOutput);
        (*ENDREPEAT*) 
    (*ENDIF*) 
    IF  trError_gg00 = e_file_not_found
    THEN
        trError_gg00 := e_ok;
    (* *)
    (*ENDIF*) 
    IF  abortMig
    THEN
        trError_gg00 := e_migration_error;
    (* add catalog information to restart record *)
    (*ENDIF*) 
    table_surr := c_sys1_catalog_id;
    k57SetSys1CatalogTabId (table_surr);
    table_surr := c_sys2_catalog_id;
    k57SetSys2CatalogTabId (table_surr);
    (* *)
    (* increase highest given file no in file directory to create a safety *)
    (* cushion for create table log entries that might be executed during  *)
    (* a log roll forward                                                  *)
    bd998AddFileNoSafetyMargin (t.trTaskId_gg00) ;
    (* *)
    (* second pass: add all index and short column entries *)
    file_id.fileName_gg00  := cgg_zero_fn;
    IF  trError_gg00 = e_ok
    THEN
        REPEAT
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                bd17_NextFdir (file_id.fileName_gg00, fi, current_fdir);
                b30fdir_to_treeid (fi, file_id);
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_no_next_record
            THEN
                trError_gg00 := e_file_not_found;
            (*ENDIF*) 
            IF  (trError_gg00 = e_ok)
                AND ( (file_id.fileTfn_gg00 = tfnMulti_egg00)
                OR    (file_id.fileTfn_gg00 = tfnOmsInv_egg00) )
            THEN
                (* tfnOmsInv_egg00 used to be the tfnNo for *)
                (* single indices (for releases < 7.4)      *)
                bd998ConvIndexFDirEntry (t.trTaskId_gg00, file_id, fi.fi_root,
                      fi.fi_type, fi.fi_vers)
            ELSE
                BEGIN
                IF  (trError_gg00 = e_ok) AND (file_id.fileTfn_gg00 = tfnShortScol_egg00)
                THEN
                    bd998ConvShortColFDirEntry (t.trTaskId_gg00, file_id,
                          fi.fi_root, fi.fi_type, fi.fi_vers)
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        UNTIL
            (trError_gg00 <> e_ok);
        (*ENDREPEAT*) 
    (*ENDIF*) 
    IF  trError_gg00 = e_file_not_found
    THEN
        trError_gg00 := e_ok;
    (*ENDIF*) 
    bd30ReleaseTree (current_fdir);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        file_id                := permFileDir_id;
        file_id.fileName_gg00  := cgg_zero_fn;
        bd30GetTree (t, file_id, current_fdir, m_drop,
              LOCK_TREE_EXCL_BD00, NOT SYNC_TREE_LOCK_BD00);
        IF  t.trError_gg00 = e_ok
        THEN
            bd30DropTree (current_fdir, 0, false);
        (*ENDIF*) 
        bd30ReleaseTree (current_fdir);
        file_id.fileBdUse_gg00 := file_id.fileBdUse_gg00 - [bd_write_acc];
        END;
    (*ENDIF*) 
    bd998SetFDirMigrationFinished;
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd17_AddFdir (
            VAR fn      : tgg00_Filename;
            VAR fi      : tbd_fileinfo;
            VAR current : tbd_current_tree);
 
VAR
      pKey            : ^tgg00_Lkey;
      pRec            : ^tgg00_Rec;
      FDirEntry       : tbd00_FDirEntry;
 
BEGIN
pKey := @FDirEntry;
pRec := @FDirEntry;
WITH FDirEntry DO
    BEGIN
    fdirFill1_bd00          := 0;
    fdirFill2_bd00          := 0;
    fdirFileName_bd00       := fn;
    fdirFileNameLength_bd00 := FN_MXGG00;
    fdirFileInfo_bd00       := fi;
    fdirEntryLength_bd00    := STD_FDIRENTRY_MXBD00;
    END;
(*ENDWITH*) 
bd30AddToTree (pKey^, pRec^, current);
IF  current.curr_trans^.trError_gg00 = e_duplicate_key
THEN
    current.curr_trans^.trError_gg00 := e_duplicate_filename;
&ifdef TRACE
(*ENDIF*) 
t01basis_error (bd, 'b17add fdir ', current.curr_trans^.trError_gg00);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd17_DelFdir (
            VAR fn      : tgg00_Filename;
            VAR current : tbd_current_tree);
 
VAR
      pKey            : ^tgg00_Lkey;
      FDirEntry       : tbd00_FDirEntry;
 
BEGIN
pKey := @FDirEntry;
WITH FDirEntry DO
    BEGIN
    fdirFill1_bd00          := 0;
    fdirFill2_bd00          := 0;
    fdirFileName_bd00       := fn;
    fdirFileNameLength_bd00 := FN_MXGG00;
    END;
(*ENDWITH*) 
bd30DelFromTree (pKey^, current);
IF  current.curr_trans^.trError_gg00 = e_key_not_found
THEN
    current.curr_trans^.trError_gg00 := e_file_not_found;
(*ENDIF*) 
IF  current.curr_trans^.trError_gg00 = e_bad_datapage
THEN
    current.curr_trans^.trError_gg00 := e_bad_fdir;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd17_SearchFdir (
            VAR fn      : tgg00_Filename;
            VAR fi      : tbd_fileinfo;
            VAR current : tbd_current_tree);
 
VAR
      pKey            : ^tgg00_Lkey;
      pRec            : ^tgg00_Rec;
      FDirEntry       : tbd00_FDirEntry;
 
BEGIN
pKey := @FDirEntry;
pRec := @FDirEntry;
WITH FDirEntry DO
    BEGIN
    fdirFill1_bd00          := 0;
    fdirFill2_bd00          := 0;
    fdirFileName_bd00       := fn;
    fdirFileNameLength_bd00 := FN_MXGG00
    END;
(*ENDWITH*) 
bd30GetFromTree (pKey^, pRec^, current, lckFree_egg00);
(* *)
IF  current.curr_trans^.trError_gg00 = e_ok
THEN
    BEGIN
    fi := FDirEntry.fdirFileInfo_bd00;
    gg06SetNilRef (fi.fi_user_ref)
    END
ELSE
    BEGIN
    IF  current.curr_trans^.trError_gg00 = e_key_not_found
    THEN
        current.curr_trans^.trError_gg00 := e_file_not_found;
    (*ENDIF*) 
    IF  current.curr_trans^.trError_gg00 = e_bad_datapage
    THEN
        current.curr_trans^.trError_gg00 := e_bad_fdir;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd17_ReplFdir (
            VAR fn      : tgg00_Filename;
            VAR fi      : tbd_fileinfo;
            VAR current : tbd_current_tree);
 
VAR
      pKey            : ^tgg00_Lkey;
      pRec            : ^tgg00_Rec;
      dummyBeforeRef  : tgg91_PageRef;
      dummyTransNo    : tgg91_TransNo;
      FDirEntry       : tbd00_FDirEntry;
 
BEGIN
gg06SetDummyRef (dummyBeforeRef);
gg06SetDummyTrans (dummyTransNo);
pKey := @FDirEntry;
pRec := @FDirEntry;
WITH FDirEntry DO
    BEGIN
    fdirFill1_bd00          := 0;
    fdirFill2_bd00          := 0;
    fdirFileName_bd00       := fn;
    fdirFileNameLength_bd00 := FN_MXGG00;
    fdirEntryLength_bd00    := STD_FDIRENTRY_MXBD00;
    fdirFileInfo_bd00       := fi;
    END;
(*ENDWITH*) 
bd30ReplaceInTree (pKey^, pRec^, current, dummyBeforeRef, dummyTransNo);
IF  current.curr_trans^.trError_gg00 <> e_ok
THEN
    BEGIN
    IF  current.curr_trans^.trError_gg00 = e_key_not_found
    THEN
        current.curr_trans^.trError_gg00 := e_file_not_found;
    (*ENDIF*) 
    IF  current.curr_trans^.trError_gg00 = e_bad_datapage
    THEN
        current.curr_trans^.trError_gg00 := e_bad_fdir;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd17_NextFdir (
            VAR fn      : tgg00_Filename;
            VAR fi      : tbd_fileinfo;
            VAR current : tbd_current_tree);
 
VAR
      pKey            : ^tgg00_Lkey;
      pRec            : ^tgg00_Rec;
      FDirEntry       : tbd00_FDirEntry;
 
BEGIN
pKey := @FDirEntry;
pRec := @FDirEntry;
WITH FDirEntry DO
    BEGIN
    fdirFill1_bd00          := 0;
    fdirFill2_bd00          := 0;
    fdirFileName_bd00       := fn;
    fdirFileNameLength_bd00 := FN_MXGG00
    END;
(*ENDWITH*) 
bd30NextFromTree (pKey^, NOT c_inclusive, NOT c_withSQLLock, pRec^, current);
bd30ReleaseSubTree (current);
IF  current.curr_trans^.trError_gg00 = e_key_not_found
THEN
    current.curr_trans^.trError_gg00 := e_ok;
(*ENDIF*) 
IF  current.curr_trans^.trError_gg00 = e_ok
THEN
    BEGIN
    fn := FDirEntry.fdirFileName_bd00;
    fi := FDirEntry.fdirFileInfo_bd00;
    gg06SetNilRef (fi.fi_user_ref)
    END
ELSE
    IF  current.curr_trans^.trError_gg00 = e_bad_datapage
    THEN
        current.curr_trans^.trError_gg00 := e_bad_fdir;
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd17_InitBlobFdirFileId;
 
BEGIN
bd17BlobFdirFileId := b01niltree_id;
WITH bd17BlobFdirFileId DO
    BEGIN
    fileType_gg00  := [ftsPerm_egg00, ftsConcurrent_egg00];
    fileBdUse_gg00 := [];
    fileTfn_gg00   := tfnTable_egg00
    END
(*ENDWITH*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
