.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$VBD19$
.tt 2 $$$
.tt 3 $JuergenP$flist$2000-02-11$
***********************************************************
.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  : flist
=========
.sp
Purpose : Internal file directory
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        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 filename : tgg00_Filename;
                    VAR fi       : tbd_fileinfo);
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
&       ifdef TRACE
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01filename (layer : tgg00_Debug;
                    fn : tgg00_Filename);
&       endif
 
      ------------------------------ 
 
        FROM
              Regions_and_Longwaits : VGG08;
 
        VAR
              g08permfdir  : tsp00_RegionId;
 
      ------------------------------ 
 
        FROM
              RTE_kernel : VEN101;
 
        PROCEDURE
              vbegexcl (pid : tsp00_TaskId;
                    region : tsp00_RegionId);
 
        PROCEDURE
              vendexcl (pid : tsp00_TaskId;
                    region : tsp00_RegionId);
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : JuergenP
.sp
.cp 3
Created : 1983-03-14
.sp
.cp 3
Version : 2002-08-22
.sp
.cp 3
Release :      Date : 2000-02-11
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
 
The internal file directory (resident in the main memory) contains
entries for frequently referenced files.  Each entry consists of
an unambiguous file name fn and the file information fi.  The file
information describes the file type (temporary or permanent), the
key type (variable or fixed length) and the page number of the root
of the B* tree used to manage the file's index and entries.
.sp2
   b19init_flist
.sp
Must be called during system generation.  Afterwards, the file
directory does not (yet) contain any entries.
.sp 2
   b19add_flist(fn,fi,new,temp_dfdir)
.sp
Forms a new entry from fn and fi and inserts it in the file
directory.  If it has been determined that an entry with the
same file name fn is already contained in the directory, this
entry is overwritten.  If such an entry does not yet exist,
a free space is found to which the entry is written.  Under
certain circumstances, an 'old' entry is overwritten in
the process.
.sp 2
   b17del_fdir(fn)
.sp
Deletes the entry with the file name fn from the file directory,
if such an entry is present.
.sp 2
   b19search_flist(fn,fi,found)
.sp
Searches directory for the entry with the file name fn.  If such
an entry is present, its file information fi is fetched and 'found'
registers 'true'; otherwise 'found' registers 'false'.
.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.
For this reason, the file directory is supported by a card file
named flist resident in the main memory.
.sp
In order to avoid accesses to the external directory as much as
possible during system operation, the internal card file should be
allocated a relatively large space (flistsize).
.sp
The internal directory is organized in the form of chained lists
(separate chaining) consisting of an entry ARRAY (flist), a
beginning-of-chain ARRAY (head_list) and a index variable clock.
An entry contains the file name, additional current file
information such as the root segment, a statement on the probability
of reuse (chance) and a boolean field 'dirty' which has the
value 'true' during the exact period when the associated file
entry has not yet been stored to the external file directory.
.sp
If file information is requested, the file name fn is first
mapped onto the beginning of a chain via a hash function (modulo)
and then a search is carried out sequentially within the same
chain.
.sp
If a file entry is to be written to the internal directory with
b19add_flist, first a check is carried out to determine whether
an old entry already exists.  If yes, the old entry is overwritten
by the new entry; if no, a search is carried out for an empty entry
space and, if none is found, an entry is displaced.  Under certain
circumstances, the displaced entry must then be transferred to the
external directory.
.sp
The displacement algorithm (see empty_flistentry) is based on a
clock strategy that takes into account the frequency of access.
Each time an entry is accessed, its 'chance' field is raised by one.
During the search for an entry that is to be displaced from the
internal directory, the clock variable cyclicly processes the
entries and decrements the chance fields until a chance field is
found with the value zero.
.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
      p_flistsize     = 511;  (* 2 * max_processes - 1 *)
      p_flistsize_1   = 510;
      p_flistnilindex = p_flistsize;
      first_chance    = 2;
 
TYPE
 
      p_flistentry = RECORD
            flist_no   : tsp00_Int2;
            chance     : tsp00_Int2;
            fname      : tgg00_Filename;
            finfo      : tbd_fileinfo;
            next       : tsp00_Int2;
            h_fill     : tsp00_Int2;
      END;
 
 
VAR
 
      b19permfdir_cache : RECORD
            flist     : ARRAY [ 0..p_flistsize_1 ] OF p_flistentry;
            head_list : ARRAY [ 0..p_flistsize_1 ] OF tsp00_Int2;
            clock     : tsp00_Int2
      END;
 
 
 
(*------------------------------*) 
 
PROCEDURE
      b19init_flists;
 
VAR
      i : integer;
 
BEGIN
WITH b19permfdir_cache DO
    BEGIN
    clock := 0;
    FOR i := 0 TO p_flistsize_1 DO
        BEGIN
        head_list [ i ] := i;
        WITH flist [ i ] DO
            BEGIN
            flist_no := i;
            fname := cgg_zero_fn;
            chance := 0;
            h_fill := 0;
            next   := p_flistnilindex
            END
        (*ENDWITH*) 
        END
    (*ENDFOR*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b19p_search_flist (
            TaskId       : tsp00_TaskId;
            VAR filename : tgg00_Filename;
            VAR fi       : tbd_fileinfo;
            VAR found    : boolean);
 
VAR
      h     : tsp00_Int2;
      there : tsp00_Int2;
 
BEGIN
found := false;
h     := p_hash_flist (filename);
vbegexcl (TaskId, g08permfdir);(* CR 1105315 TS 2000-01-12 *)
WITH b19permfdir_cache DO
    BEGIN
    there := head_list [ h ];
    IF  head_list [ h ] <> p_flistnilindex
    THEN
        REPEAT
            WITH flist[ there ] DO
                IF  fname = filename
                THEN
                    found := true
                ELSE
                    there := next
                (*ENDIF*) 
            (*ENDWITH*) 
        UNTIL
            found OR (there = p_flistnilindex);
        (*ENDREPEAT*) 
    (*ENDIF*) 
    IF  found
    THEN
        WITH flist [ there ] DO
            BEGIN
            fi := finfo;
            IF  chance < p_flistsize
            THEN
                chance := chance + 1
            (*ENDIF*) 
            END
        (*ENDWITH*) 
    (*ENDIF*) 
    END;
(*ENDWITH*) 
vendexcl (TaskId, g08permfdir);(* CR 1105315 TS 2000-01-12 *)
END;
 
(*------------------------------*) 
 
PROCEDURE
      b19p_del_flist (
            TaskId       : tsp00_TaskId;
            VAR filename : tgg00_Filename;
            VAR fi       : tbd_fileinfo;
            VAR found    : boolean);
 
VAR
      h     : tsp00_Int2;
      there : tsp00_Int2;
 
BEGIN
found := false;
h     := p_hash_flist (filename);
vbegexcl (TaskId, g08permfdir);(* CR 1105315 TS 2000-01-12 *)
WITH b19permfdir_cache DO
    BEGIN
    there := head_list [ h ];
    IF  head_list [ h ] <> p_flistnilindex
    THEN
        REPEAT
            WITH flist[ there ] DO
                IF  fname = filename
                THEN
                    found := true
                ELSE
                    there := next
                (*ENDIF*) 
            (*ENDWITH*) 
        UNTIL
            found OR (there = p_flistnilindex);
        (*ENDREPEAT*) 
    (*ENDIF*) 
    IF  found
    THEN
        WITH flist [ there ] DO
            BEGIN
            fi     := finfo;
            fname  := cgg_zero_fn;
            chance := 0
            END
        (*ENDWITH*) 
    (*ENDIF*) 
    END;
(*ENDWITH*) 
vendexcl (TaskId, g08permfdir);(* CR 1105315 TS 2000-01-12 *)
END;
 
(*------------------------------*) 
 
PROCEDURE
      b19p_add_flist (
            TaskId       : tsp00_TaskId;
            VAR filename : tgg00_Filename;
            VAR fi       : tbd_fileinfo);
 
VAR
      found : boolean;
      h     : tsp00_Int2;
      there : tsp00_Int2;
      succ  : tsp00_Int2;
 
BEGIN
found := false;
h     := p_hash_flist (filename);
vbegexcl (TaskId, g08permfdir);(* CR 1105315 TS 2000-01-12 *)
WITH b19permfdir_cache DO
    BEGIN
    there := head_list [ h ];
    IF  there <> p_flistnilindex
    THEN
        REPEAT
            WITH flist [ there ] DO
                IF  fname = filename
                THEN
                    found := true
                ELSE
                    there := next
                (*ENDIF*) 
            (*ENDWITH*) 
        UNTIL
            found OR (there = p_flistnilindex);
        (*ENDREPEAT*) 
    (*ENDIF*) 
    IF  NOT found
    THEN
        BEGIN
        p_empty_flistentry (there);
        IF  head_list [ h ] <> p_flistnilindex
        THEN
            succ := head_list [ h ];
        (*ENDIF*) 
        flist [ there ].next := head_list [ h ];
        head_list [ h ]      := there
        END;
    (*ENDIF*) 
    WITH flist [ there ] DO
        BEGIN
        fname  := filename;
        finfo  := fi;
        chance := first_chance
        END
    (*ENDWITH*) 
    END;
(*ENDWITH*) 
vendexcl (TaskId, g08permfdir);(* CR 1105315 TS 2000-01-12 *)
END;
 
(*------------------------------*) 
 
PROCEDURE
      p_empty_flistentry (VAR there : tsp00_Int2);
 
VAR
      found : boolean;
      succ  : tsp00_Int2;
      pred  : tsp00_Int2;
      h     : tsp00_Int2;
 
BEGIN
found := false;
WITH b19permfdir_cache DO
    BEGIN
    h := clock;
    REPEAT
        succ := head_list [ h ];
        pred := p_flistnilindex;
        IF  succ <> p_flistnilindex
        THEN
            REPEAT
                WITH flist [ succ ] DO
                    BEGIN
                    IF  fname = cgg_zero_fn
                    THEN
                        BEGIN
                        there := flist_no;
                        found := true
                        END
                    ELSE
                        BEGIN
                        IF  chance > 0
                        THEN
                            chance := chance - 1;
                        (*ENDIF*) 
                        IF  chance = 0
                        THEN
                            BEGIN
                            there := flist_no;
                            found := true;
                            END
                        ELSE
                            BEGIN
                            pred := succ;
                            succ := next
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDWITH*) 
            UNTIL
                found OR (succ = p_flistnilindex);
            (*ENDREPEAT*) 
        (*ENDIF*) 
        IF  NOT found
        THEN
            h := (h + 1) MOD p_flistsize
        ELSE  (* found *)
            IF  pred = p_flistnilindex
            THEN
                head_list[ h ] := flist[ there ].next
            ELSE
                flist[ pred ].next := flist[ there ].next
            (*ENDIF*) 
        (*ENDIF*) 
    UNTIL
        found;
    (*ENDREPEAT*) 
    IF  found
    THEN
        BEGIN
        WITH flist [ there ] DO
            succ := next;
        (*ENDWITH*) 
        IF  head_list [ h ] = there
        THEN
            head_list [ h ] := succ;
        (*ENDIF*) 
        clock := (clock + 1) MOD p_flistsize
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      p_hash_flist (VAR filename : tgg00_Filename) : tsp00_Int2;
 
VAR
      hashvalue : integer;
      i         : integer;
 
BEGIN
hashvalue := 0;
FOR i := 1 TO sizeof (filename) DO
    hashvalue := hashvalue + ord(filename[ i ]);
(*ENDFOR*) 
hashvalue    := hashvalue MOD p_flistsize;
p_hash_flist := hashvalue
END;
 
(*------------------------------*) 
 
PROCEDURE
      print_flist;
 
VAR
      i : integer;
 
BEGIN
WITH  b19permfdir_cache DO
    BEGIN
    FOR i := 0 TO p_flistsize_1 DO
        WITH flist[ i ] DO
            IF  fname <> cgg_zero_fn
            THEN
                BEGIN
&               ifdef TRACE
                t01filename (bd, fname);
&               endif
                END
            (*ENDIF*) 
        (*ENDWITH*) 
    (*ENDFOR*) 
    END
(*ENDWITH*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
*-PRETTY-*  statements    :        106
*-PRETTY-*  lines of code :        347        PRETTYX 3.10 
*-PRETTY-*  lines in file :        584         1997-12-10 
.PA 
