.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$VBD17$
.tt 2 $$$
.tt 3 $JuergenP$filedirectory$$2000-05-04$
***********************************************************
.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  : filedirectory
=========
.sp
Purpose : Complete directory of all existing files
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        PROCEDURE
              b17add_fdir (VAR fn : tgg00_Filename;
                    VAR fi : tbd_fileinfo;
                    VAR t  : tgg00_TransContext);
 
        PROCEDURE
              b17create_fdir (VAR t : tgg00_TransContext);
 
        PROCEDURE
              b17del_fdir (VAR fn   : tgg00_Filename;
                    VAR fi          : tbd_fileinfo;
                    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;
                    shared_file     : boolean;
                    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
              b17restart_fdir (
                    VAR t       : tgg00_TransContext;
                    fdir_1_root : tsp00_PageNo;
                    fdir_2_root : tsp00_PageNo);
 
        PROCEDURE
              b17state_fdir (VAR fn : tgg00_Filename;
                    VAR fi      : tbd_fileinfo;
                    shared_file : boolean;
                    VAR t       : tgg00_TransContext);
 
        PROCEDURE
              b17succ_fdir (VAR fn : tgg00_Filename;
                    VAR next_fn     : tgg00_Filename;
                    VAR fi          : tbd_fileinfo;
                    shared_file     : boolean;
                    VAR t           : tgg00_TransContext;
                    include_strcols : boolean);
 
        PROCEDURE
              b17unload_fdir (VAR fn : tgg00_Filename;
                    VAR fi      : tbd_fileinfo;
                    shared_file : boolean;
                    VAR t       : tgg00_TransContext);
 
        FUNCTION
              bd17GetFdirRoot : tsp00_PageNo;
 
        FUNCTION
              bd17GetLongFdirRoot : tsp00_PageNo;
 
        FUNCTION
              bd17GetTempFdirRoot : tsp00_PageNo;
 
        PROCEDURE
              bd17VerifyFdir (
                    VAR trans          : tgg00_TransContext;
                    bIsCold            : boolean;
                    bWithExtendedCheck : boolean);
 
        PROCEDURE
              bd17VerifyLongFdir (
                    VAR trans          : tgg00_TransContext;
                    bIsCold            : boolean;
                    bWithExtendedCheck : boolean);
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
        FROM
              diskfiledirectory    : VBD18;
 
        PROCEDURE
              b18add_dfdir (VAR fn    : tgg00_Filename;
                    VAR fi            : tbd_fileinfo;
                    VAR current_fdir  : tbd_current_tree);
 
        PROCEDURE
              b18repl_dfdir (VAR fn   : tgg00_Filename;
                    VAR fi            : tbd_fileinfo;
                    VAR current_fdir : tbd_current_tree);
 
        PROCEDURE
              b18del_dfdir (VAR fn    : tgg00_Filename;
                    VAR fi            : tbd_fileinfo;
                    VAR current_fdir  : tbd_current_tree);
 
        PROCEDURE
              b18search_dfdir (VAR fn : tgg00_Filename;
                    VAR fi            : tbd_fileinfo;
                    VAR current_fdir  : tbd_current_tree);
 
        PROCEDURE
              b18next_dfdir (VAR fn   : tgg00_Filename;
                    VAR fi            : tbd_fileinfo;
                    VAR current_fdir  : tbd_current_tree);
 
        PROCEDURE
              bd18CreateFdir (
                    VAR trans      : tgg00_TransContext;
                    VAR permFileId : tgg00_FileId;
                    VAR longFileId : tgg00_FileId;
                    VAR tempFileId : tgg00_FileId);
 
        PROCEDURE
              bd18RestartFdir (
                    VAR trans      : tgg00_TransContext;
                    permFileRoot   : tsp00_PageNo;
                    longFileRoot   : tsp00_PageNo;
                    VAR permFileId : tgg00_FileId;
                    VAR longFileId : tgg00_FileId;
                    VAR tempFileId : tgg00_FileId);
 
      ------------------------------ 
 
        FROM
              flist : VBD19;
 
        PROCEDURE
              b19init_flists;
 
        PROCEDURE
              b19p_search_flist (
                    TaskId       : tsp00_TaskId;
                    VAR filename : tgg00_Filename;
                    VAR fi       : tbd_fileinfo;
                    VAR found    : boolean);
 
        PROCEDURE
              b19p_del_flist (
                    TaskId       : tsp00_TaskId;
                    VAR filename : tgg00_Filename;
                    VAR fi       : tbd_fileinfo;
                    VAR found    : boolean);
 
        PROCEDURE
              b19p_add_flist (
                    TaskId       : tsp00_TaskId;
                    VAR fileanme : tgg00_Filename;
                    VAR fi : tbd_fileinfo);
 
      ------------------------------ 
 
        FROM
              task_temp_data_cache : VBD21;
 
        PROCEDURE
              b21lcl_tfdir_root (temp_cache_ptr : tgg00_TempDataCachePtr;
                    is_set  : boolean;
                    VAR pno : tsp00_PageNo);
 
      ------------------------------ 
 
        FROM
              treehandling : VBD30;
 
        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;
                    bTreeExclusive : boolean;
                    messType       : tgg00_MessType);
 
        PROCEDURE
              bd30ReleaseTree (
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd30SubFileState (
                    VAR current : tbd_current_tree;
                    fileState   : tbd_file_state_set);
 
        PROCEDURE
              bd30VerifyTree (
                    VAR trans          : tgg00_TransContext;
                    VAR fileId         : tgg00_FileId;
                    bUpdateConverter   : boolean;
                    bWithExtendedCheck : boolean;
                    VAR numPages       : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_1 : VBD01;
 
        VAR
              b01niltree_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_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);
 
.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.
.sp 2
   b17unload_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 and the
'unloaded' flag is set.  In addition, nil_page_no is
assigned to the root segment 'root'.
.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    :
 
 
CONST
      MSG_1_RESTART = 'Restart FileDir finished successfully   ';
      MSG_2_RESTART = 'Restart FileDir finished unsuccessfully ';
      (* *)
      c_get_pno = false;
 
VAR
      bd17PermFdirFileId : tgg00_FileId;
      bd17LongFdirFileId : tgg00_FileId;
      bd17TempFdirFileId : tgg00_FileId;
 
 
(*------------------------------*) 
 
PROCEDURE
      b17add_fdir (VAR fn : tgg00_Filename;
            VAR fi : tbd_fileinfo;
            VAR t  : tgg00_TransContext);
 
VAR
      is_perm           : boolean;
      LocalTempDirExist : boolean;
      fileId            : tgg00_FileId;
      current_fdir      : tbd_current_tree;
 
BEGIN
WITH t DO
    BEGIN
    trError_gg00 := e_ok;
    is_perm :=
          (ftsByteStr_egg00 in fi.fi_type) OR
          (ftsPerm_egg00 in fi.fi_type   ) OR
          (ftsObject_egg00 in fi.fi_type );
    (*  defensive check *)
    IF  bd17is_temp (fn)
    THEN
        BEGIN
        IF  is_perm
        THEN
            trError_gg00 := e_illegal_filename
        (*ENDIF*) 
        END
    ELSE
        IF  NOT is_perm
        THEN
            trError_gg00 := e_illegal_filename;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  is_perm
        THEN
            BEGIN
            IF  fn [ 1 ] <> chr (ord (tfnColumn_egg00))
            THEN
                fileId := bd17PermFdirFileId
            ELSE
                fileId := bd17LongFdirFileId;
            (*ENDIF*) 
            END
        ELSE (* temp *)
            BEGIN
            IF  t.trBdTcachePtr_gg00 <> NIL
            THEN
                LocalTempDirExist := (t.trBdTcachePtr_gg00^.tdc_fdir_root <> NIL_PAGE_NO_GG00)
            ELSE
                LocalTempDirExist := false;
            (*ENDIF*) 
            IF  (ftsShared_egg00 in fi.fi_type) OR (NOT LocalTempDirExist)
            THEN
                fileId := bd17TempFdirFileId
            ELSE
                bd17_GetLocalTempFdir (trBdTcachePtr_gg00, fileId)
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 + [bd_write_acc];
        bd30GetTree (t, fileId, current_fdir, LOCK_TREE_EXCL_BD00, m_nil);
        IF  trError_gg00 = e_ok
        THEN
            b18add_dfdir (fn, fi, current_fdir);
        (*ENDIF*) 
        bd30ReleaseTree (current_fdir);
        fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 - [bd_write_acc];
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17create_fdir (VAR t : tgg00_TransContext);
 
BEGIN
b19init_flists;
bd18CreateFdir (t, bd17PermFdirFileId, bd17LongFdirFileId, bd17TempFdirFileId);
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17del_fdir (VAR fn   : tgg00_Filename;
            VAR fi          : tbd_fileinfo;
            shared_file     : boolean;
            VAR t           : tgg00_TransContext);
 
VAR
      found             : boolean;
      LocalTempDirExist : boolean;
      dummy_fi          : tbd_fileinfo;
      fileId            : tgg00_FileId;
      current_fdir      : tbd_current_tree;
 
BEGIN
WITH t DO
    BEGIN
    trError_gg00 := e_ok;
    IF  bd17is_temp (fn)
    THEN
        BEGIN
        IF  trBdTcachePtr_gg00 <> NIL
        THEN
            LocalTempDirExist := (trBdTcachePtr_gg00^.tdc_fdir_root <> NIL_PAGE_NO_GG00)
        ELSE
            LocalTempDirExist := false;
        (*ENDIF*) 
        IF  shared_file OR (NOT LocalTempDirExist)
        THEN
            fileId := bd17TempFdirFileId
        ELSE
            bd17_GetLocalTempFdir (trBdTcachePtr_gg00, fileId)
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  fn [ 1 ] <> chr (ord (tfnColumn_egg00))
        THEN
            fileId := bd17PermFdirFileId
        ELSE
            fileId := bd17LongFdirFileId
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 + [bd_write_acc];
    bd30GetTree (t, fileId, current_fdir, LOCK_TREE_EXCL_BD00, m_nil);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        b18del_dfdir (fn, fi, current_fdir);
        IF  bd17_UseHash (fn)
        THEN
            b19p_del_flist (trTaskId_gg00, fn, dummy_fi, found)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    bd30ReleaseTree (current_fdir);
    fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 - [bd_write_acc];
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17fadd_file_state (
            VAR t      : tgg00_TransContext;
            VAR fileId : tgg00_FileId;
            newState  : tbd_file_state_set);
 
VAR
      found             : boolean;
      LocalTempDirExist : boolean;
      fi                : tbd_fileinfo;
      fDirFileId        : tgg00_FileId;
      current_fdir      : tbd_current_tree;
 
BEGIN
WITH t  DO
    BEGIN
    trError_gg00 := e_ok;
    found        := false;
    IF  bd17is_temp (fileId.fileName_gg00)
    THEN
        BEGIN
        IF  trBdTcachePtr_gg00 <> NIL
        THEN
            LocalTempDirExist := (trBdTcachePtr_gg00^.tdc_fdir_root <> NIL_PAGE_NO_GG00)
        ELSE
            LocalTempDirExist := false;
        (*ENDIF*) 
        IF  (ftsShared_egg00 IN fileId.fileType_gg00) OR (NOT LocalTempDirExist)
        THEN
            fDirFileId := bd17TempFdirFileId
        ELSE
            bd17_GetLocalTempFdir (trBdTcachePtr_gg00, fDirFileId)
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  fileId.fileName_gg00[ 1 ] <> chr (ord (tfnColumn_egg00))
        THEN
            fDirFileId := bd17PermFdirFileId
        ELSE
            fDirFileId := bd17LongFdirFileId
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    fDirFileId.fileBdUse_gg00 := fDirFileId.fileBdUse_gg00 + [bd_write_acc];
    bd30GetTree (t, fDirFileId, current_fdir, LOCK_TREE_EXCL_BD00, m_nil);
    IF  trError_gg00 = e_ok
    THEN
        b18search_dfdir (fileId.fileName_gg00, fi, current_fdir);
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        fi.fi_state := fi.fi_state + newState;
        b18repl_dfdir (fileId.fileName_gg00, fi, current_fdir);
        IF  bd17_UseHash (fileId.fileName_gg00)
        THEN
            b19p_del_flist (trTaskId_gg00, fileId.fileName_gg00, fi, found)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    bd30ReleaseTree (current_fdir);
    fDirFileId.fileBdUse_gg00 := fDirFileId.fileBdUse_gg00 - [bd_write_acc];
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17fsub_file_state (
            VAR t      : tgg00_TransContext;
            VAR fileId : tgg00_FileId;
            subState   : tbd_file_state_set);
 
VAR
      found             : boolean;
      LocalTempDirExist : boolean;
      fi                : tbd_fileinfo;
      fDirFileId        : tgg00_FileId;
      current_fdir      : tbd_current_tree;
 
BEGIN
WITH t DO
    BEGIN
    trError_gg00 := e_ok;
    found        := false;
    IF  bd17is_temp (fileId.fileName_gg00)
    THEN
        BEGIN
        IF  trBdTcachePtr_gg00 <> NIL
        THEN
            LocalTempDirExist := (trBdTcachePtr_gg00^.tdc_fdir_root <> NIL_PAGE_NO_GG00)
        ELSE
            LocalTempDirExist := false;
        (*ENDIF*) 
        IF  (ftsShared_egg00 IN fileId.fileType_gg00) OR (NOT LocalTempDirExist)
        THEN
            fDirFileId := bd17TempFdirFileId
        ELSE
            bd17_GetLocalTempFdir (trBdTcachePtr_gg00, fDirFileId)
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  fileId.fileName_gg00[ 1 ] <> chr (ord (tfnColumn_egg00))
        THEN
            fDirFileId := bd17PermFdirFileId
        ELSE
            fDirFileId := bd17LongFdirFileId
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    fDirFileId.fileBdUse_gg00 := fDirFileId.fileBdUse_gg00 + [bd_write_acc];
    bd30GetTree (t, fDirFileId, current_fdir, LOCK_TREE_EXCL_BD00, m_nil);
    IF  trError_gg00 = e_ok
    THEN
        b18search_dfdir (fileId.fileName_gg00, fi, current_fdir);
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        fi.fi_state := fi.fi_state - subState;
        b18repl_dfdir (fileId.fileName_gg00, fi, current_fdir);
        IF  bd17_UseHash (fileId.fileName_gg00)
        THEN
            b19p_del_flist (trTaskId_gg00, fileId.fileName_gg00, fi, found)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    bd30ReleaseTree (current_fdir);
    fDirFileId.fileBdUse_gg00 := fDirFileId.fileBdUse_gg00 - [bd_write_acc];
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17next_del_fdir (VAR prefix : tgg00_Filename;
            prefix_len      : integer;
            VAR fn          : tgg00_Filename;
            VAR fi          : tbd_fileinfo;
            shared_file     : boolean;
            VAR t           : tgg00_TransContext);
 
VAR
      found             : boolean;
      LocalTempDirExist : boolean;
      dummy_fi          : tbd_fileinfo;
      fileId            : tgg00_FileId;
      current_fdir      : tbd_current_tree;
 
BEGIN
(* this procedure is called only by b01prefix_destroy_files
      and does not access the b17strcolfdir *)
WITH t DO
    BEGIN
    trError_gg00 := e_ok;
    IF  bd17is_temp (prefix)
    THEN
        BEGIN
        IF  trBdTcachePtr_gg00 <> NIL
        THEN
            LocalTempDirExist := (trBdTcachePtr_gg00^.tdc_fdir_root <> NIL_PAGE_NO_GG00)
        ELSE
            LocalTempDirExist := false;
        (*ENDIF*) 
        IF  shared_file OR (NOT LocalTempDirExist)
        THEN
            fileId := bd17TempFdirFileId
        ELSE
            bd17_GetLocalTempFdir (trBdTcachePtr_gg00, fileId)
        (*ENDIF*) 
        END
    ELSE
        fileId := bd17PermFdirFileId;
    (*ENDIF*) 
    fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 + [bd_write_acc];
    bd30GetTree (t, fileId, current_fdir, LOCK_TREE_EXCL_BD00, m_nil);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        b18next_dfdir (fn, fi, current_fdir);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  bd17is_prefix (prefix, fn, prefix_len)
            THEN
                BEGIN
                b18del_dfdir (fn, fi, current_fdir);
                IF  bd17_UseHash (fn)
                THEN
                    b19p_del_flist (trTaskId_gg00, fn, dummy_fi, found);
                (*ENDIF*) 
                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*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17repl_fdir (VAR fn : tgg00_Filename;
            VAR fi      : tbd_fileinfo;
            shared_file : boolean;
            VAR t       : tgg00_TransContext);
 
VAR
      found             : boolean;
      LocalTempDirExist : boolean;
      dummy_fi          : tbd_fileinfo;
      fileId            : tgg00_FileId;
      current_fdir      : tbd_current_tree;
 
BEGIN
t.trError_gg00 := e_ok;
WITH t DO
    BEGIN
    IF  NOT (ftsTemp_egg00 IN fi.fi_type)
    THEN
        BEGIN
        IF  fn [ 1 ] <> chr (ord (tfnColumn_egg00))
        THEN
            fileId := bd17PermFdirFileId
        ELSE
            fileId := bd17LongFdirFileId
        (*ENDIF*) 
        END
    ELSE (*  temp *)
        BEGIN
        IF  trBdTcachePtr_gg00 <> NIL
        THEN
            LocalTempDirExist := (trBdTcachePtr_gg00^.tdc_fdir_root <> NIL_PAGE_NO_GG00)
        ELSE
            LocalTempDirExist := false;
        (*ENDIF*) 
        IF  shared_file OR (NOT LocalTempDirExist)
        THEN
            fileId := bd17TempFdirFileId
        ELSE
            bd17_GetLocalTempFdir (trBdTcachePtr_gg00, fileId)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 + [bd_write_acc];
    bd30GetTree (t, fileId, current_fdir, LOCK_TREE_EXCL_BD00, m_nil);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        b18repl_dfdir (fn, fi, current_fdir);
        IF  bd17_UseHash (fn)
        THEN
            b19p_del_flist (t.trTaskId_gg00, fn, dummy_fi, found);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    bd30ReleaseTree (current_fdir);
    fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 - [bd_write_acc];
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17reset_read_only (VAR t : tgg00_TransContext);
 
VAR
      found         : boolean;
      i             : integer;
      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
    FOR i := 1 TO 3 DO
        BEGIN
        file_id := b01niltree_id;
        IF  i = 1
        THEN
            BEGIN
            ro_tfn     := tfnColumn_egg00;
            fDirFileId := bd17LongFdirFileId;
            END
        ELSE
            IF  i = 2
            THEN
                BEGIN
                ro_tfn     := tfnTable_egg00;
                fDirFileId := bd17PermFdirFileId;
                END
            ELSE
                BEGIN
                ro_tfn     := tfnShortScol_egg00;
                fDirFileId := bd17PermFdirFileId;
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        file_id.fileName_gg00 [ 1 ] := chr (ord (ro_tfn));
        (* *)
        fDirFileId.fileBdUse_gg00 := fDirFileId.fileBdUse_gg00 + [bd_write_acc];
        bd30GetTree (t, fDirFileId, current_fdir, LOCK_TREE_EXCL_BD00, m_nil);
        REPEAT
            b18next_dfdir (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
                        IF  NOT (f_unloaded in fi.fi_state)
                        THEN
                            BEGIN
                            bd30ReleaseTree (current_fdir);
                            b30fdir_to_treeid (fi, file_id);
                            bd30GetTree (t, file_id, current, LOCK_TREE_EXCL_BD00, m_nil);
                            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, LOCK_TREE_EXCL_BD00, m_nil)
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        IF  trError_gg00 = e_ok
                        THEN
                            BEGIN
                            fi.fi_state := fi.fi_state - [ f_read_only ];
                            b18repl_dfdir (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);
                            IF  bd17_UseHash (file_id.fileName_gg00)
                            THEN
                                b19p_del_flist (t.trTaskId_gg00, file_id.fileName_gg00, fi, found);
                            (*ENDIF*) 
                            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
    (*ENDFOR*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17restart_fdir (
            VAR t       : tgg00_TransContext;
            fdir_1_root : tsp00_PageNo;
            fdir_2_root : tsp00_PageNo);
 
BEGIN
b19init_flists;
bd18RestartFdir (t, fdir_1_root, fdir_2_root, bd17PermFdirFileId,
      bd17LongFdirFileId, bd17TempFdirFileId);
IF  t.trError_gg00 = e_ok
THEN
    g01optextmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg,
          csp3_n_btree, MSG_1_RESTART)
ELSE
    g01optextmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg,
          csp3_n_btree, MSG_2_RESTART)
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17state_fdir (VAR fn : tgg00_Filename;
            VAR fi      : tbd_fileinfo;
            shared_file : boolean;
            VAR t       : tgg00_TransContext);
 
VAR
      found             : boolean;
      LocalTempDirExist : boolean;
      fileId            : tgg00_FileId;
      current_fdir      : tbd_current_tree;
 
BEGIN
WITH t DO
    BEGIN
    trError_gg00 := e_ok;
    found        := false;
    IF  bd17is_temp (fn)
    THEN
        BEGIN
        IF  trBdTcachePtr_gg00 <> NIL
        THEN
            LocalTempDirExist := (trBdTcachePtr_gg00^.tdc_fdir_root <> NIL_PAGE_NO_GG00)
        ELSE
            LocalTempDirExist := false;
        (*ENDIF*) 
        IF  shared_file OR (NOT LocalTempDirExist)
        THEN
            fileId := bd17TempFdirFileId
        ELSE
            bd17_GetLocalTempFdir (trBdTcachePtr_gg00, fileId)
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  fn[ 1 ] <> chr (ord (tfnColumn_egg00))
        THEN
            fileId := bd17PermFdirFileId
        ELSE
            fileId := bd17LongFdirFileId
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    bd30GetTree (t, fileId, current_fdir, NOT LOCK_TREE_EXCL_BD00, m_nil);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  bd17_UseHash (fn)
        THEN
            b19p_search_flist (trTaskId_gg00, fn, fi, found);
        (*ENDIF*) 
        IF  NOT found
        THEN
            b18search_dfdir (fn, fi, current_fdir);
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (f_unloaded in fi.fi_state)
        THEN
            trError_gg00 := e_file_unloaded;
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND bd17_UseHash (fn) AND NOT found
        THEN
            b19p_add_flist (trTaskId_gg00, fn, fi);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    bd30ReleaseTree (current_fdir);
    IF  (trError_gg00 <> e_ok) AND (trError_gg00 <> e_file_unloaded)
    THEN
        WITH fi DO
            BEGIN
            fi_type := [ ftsTemp_egg00 ];
            fi_root := NIL_PAGE_NO_GG00
            END
        (*ENDWITH*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17succ_fdir (VAR fn : tgg00_Filename;
            VAR next_fn     : tgg00_Filename;
            VAR fi          : tbd_fileinfo;
            shared_file     : boolean;
            VAR t           : tgg00_TransContext;
            include_strcols : boolean);
 
VAR
      LocalTempDirExist : boolean;
      aux_fn            : tgg00_Filename;
      fileId            : tgg00_FileId;
      current_fdir      : tbd_current_tree;
 
BEGIN
WITH t DO
    BEGIN
    trError_gg00 := e_ok;
    aux_fn       := fn;
    IF  NOT bd17is_temp (fn)
    THEN
        BEGIN
        IF  fn [ 1 ] <> chr (ord (tfnColumn_egg00))
        THEN
            fileId := bd17PermFdirFileId
        ELSE
            fileId := bd17LongFdirFileId;
        (*ENDIF*) 
        bd30GetTree (t, fileId, current_fdir, NOT LOCK_TREE_EXCL_BD00, m_nil);
        IF  trError_gg00 = e_ok
        THEN
            b18next_dfdir (aux_fn, fi, current_fdir);
        (*ENDIF*) 
        bd30ReleaseTree (current_fdir);
        IF  trError_gg00 = e_no_next_record
        THEN
            IF  include_strcols AND (fn [ 1 ] <> chr (ord (tfnColumn_egg00)))
            THEN
                BEGIN
                trError_gg00 := e_ok; (* PTS 1113189 TS 2001-12-17 *)
                fileId       := bd17LongFdirFileId;
                bd30GetTree (t, fileId, current_fdir, NOT LOCK_TREE_EXCL_BD00, m_nil);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    aux_fn                  := cgg_zero_fn;
                    b18next_dfdir (aux_fn, fi, current_fdir)
                    END;
                (*ENDIF*) 
                bd30ReleaseTree (current_fdir);
                IF  trError_gg00 = e_no_next_record
                THEN
                    trError_gg00 := e_file_not_found
                (*ENDIF*) 
                END
            ELSE
                trError_gg00 := e_file_not_found;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            next_fn := aux_fn;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  trBdTcachePtr_gg00 <> NIL
        THEN
            LocalTempDirExist := (trBdTcachePtr_gg00^.tdc_fdir_root <> NIL_PAGE_NO_GG00)
        ELSE
            LocalTempDirExist := false;
        (*ENDIF*) 
        IF  shared_file OR (NOT LocalTempDirExist)
        THEN
            fileId := bd17TempFdirFileId
        ELSE
            bd17_GetLocalTempFdir (trBdTcachePtr_gg00, fileId);
        (*ENDIF*) 
        bd30GetTree (t, fileId, current_fdir, NOT LOCK_TREE_EXCL_BD00, m_nil);
        IF  trError_gg00 = e_ok
        THEN
            b18next_dfdir (aux_fn, fi, current_fdir);
        (*ENDIF*) 
        bd30ReleaseTree (current_fdir);
        IF  trError_gg00 = e_no_next_record
        THEN
            trError_gg00 := e_file_not_found;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            next_fn := aux_fn;
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b17unload_fdir (VAR fn : tgg00_Filename;
            VAR fi          : tbd_fileinfo;
            shared_file     : boolean;
            VAR t           : tgg00_TransContext);
 
VAR
      found             : boolean;
      LocalTempDirExist : boolean;
      new_fi            : tbd_fileinfo;
      fileId            : tgg00_FileId;
      current_fdir      : tbd_current_tree;
 
BEGIN
WITH t DO
    BEGIN
    trError_gg00 := e_ok;
    IF  bd17is_temp (fn)
    THEN
        BEGIN
        IF  trBdTcachePtr_gg00 <> NIL
        THEN
            LocalTempDirExist := (trBdTcachePtr_gg00^.tdc_fdir_root <> NIL_PAGE_NO_GG00)
        ELSE
            LocalTempDirExist := false;
        (*ENDIF*) 
        IF  shared_file OR (NOT LocalTempDirExist)
        THEN
            fileId := bd17TempFdirFileId
        ELSE
            bd17_GetLocalTempFdir (trBdTcachePtr_gg00, fileId)
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  fn [ 1 ] <> chr (ord (tfnColumn_egg00))
        THEN
            fileId := bd17PermFdirFileId
        ELSE
            fileId := bd17LongFdirFileId
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 + [bd_write_acc];
    bd30GetTree (t, fileId, current_fdir, LOCK_TREE_EXCL_BD00, m_nil);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        b18search_dfdir (fn, fi, current_fdir);
        IF  (trError_gg00 = e_ok) AND (f_unloaded in fi.fi_state)
        THEN
            trError_gg00 := e_file_unloaded;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            new_fi          := fi;
            new_fi.fi_state := new_fi.fi_state + [ f_unloaded ];
            new_fi.fi_root  := NIL_PAGE_NO_GG00;
            b18repl_dfdir (fn, new_fi, current_fdir);
            IF  bd17_UseHash (fn)
            THEN
                b19p_del_flist (trTaskId_gg00, fn, new_fi, found)
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    bd30ReleaseTree (current_fdir);
    fileId.fileBdUse_gg00 := fileId.fileBdUse_gg00 - [bd_write_acc];
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd17GetFdirRoot : tsp00_PageNo;
 
BEGIN
bd17GetFdirRoot := bd17PermFdirFileId.fileRoot_gg00;
END;
 
(*------------------------------*) 
 
FUNCTION
      bd17GetLongFdirRoot : tsp00_PageNo;
 
BEGIN
bd17GetLongFdirRoot := bd17LongFdirFileId.fileRoot_gg00;
END;
 
(*------------------------------*) 
 
FUNCTION
      bd17GetTempFdirRoot : tsp00_PageNo;
 
BEGIN
bd17GetTempFdirRoot := bd17TempFdirFileId.fileRoot_gg00;
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd17VerifyFdir (
            VAR trans          : tgg00_TransContext;
            bIsCold            : boolean;
            bWithExtendedCheck : boolean);
 
VAR
      numPages     : tsp00_Int4;
      fileId       : tgg00_FileId;
 
BEGIN
fileId := bd17PermFdirFileId;
bd30VerifyTree (trans, fileId, bIsCold, bWithExtendedCheck, numPages);
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd17VerifyLongFdir (
            VAR trans          : tgg00_TransContext;
            bIsCold            : boolean;
            bWithExtendedCheck : boolean);
 
VAR
      numPages     : tsp00_Int4;
      fileId       : tgg00_FileId;
 
BEGIN
fileId := bd17LongFdirFileId;
bd30VerifyTree (trans, fileId, bIsCold, bWithExtendedCheck, numPages);
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
      bd17is_temp (VAR fn : tgg00_Filename) : boolean;
 
BEGIN
bd17is_temp := (
      (fn[ 1 ] = chr (ord (tfnTemp_egg00   ))) OR
      (fn[ 1 ] = chr (ord (tfnTempAux_egg00))) OR
      (fn[ 1 ] = chr (ord (tfnTempInv_egg00))) OR
      (fn[ 1 ] = chr (ord (tfnTempLog_egg00))) OR
      (fn[ 1 ] = chr (ord (tfnTempOms_egg00)))
      )
END;
 
(*------------------------------*) 
 
FUNCTION
      bd17_UseHash (VAR fn : tgg00_Filename) : boolean;
 
BEGIN
bd17_UseHash := (
      (fn[ 1 ] = chr (ord (tfnOmsInv_egg00   ))) OR
      (fn[ 1 ] = chr (ord (tfnMulti_egg00    ))) OR
      (fn[ 1 ] = chr (ord (tfnShortScol_egg00)))
      );
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd17_GetLocalTempFdir (
            pTempCache : tgg00_TempDataCachePtr;
            VAR fileId : tgg00_FileId);
 
BEGIN
fileId := bd17TempFdirFileId;
b21lcl_tfdir_root (pTempCache, c_get_pno, fileId.fileRoot_gg00);
fileId.fileType_gg00  := fileId.fileType_gg00 - [ftsConcurrent_egg00,ftsShared_egg00 ];
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
