.ad 8
.bm 8
.fm 4
.bt $Copyright by SAP AG, 1999$$Page %$
.tm 12
.hm 6
.hs 3
.TT 1 $SQL$Project Distributed Database System$VAK101$
.tt 2 $$$
.TT 3 $ThomasA$Syteminfo_cache$1999-01-04$
***********************************************************
.nf


    ========== licence begin  GPL
    Copyright (C) 2000 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end

.fo
.nf
.sp
MODULE  :  Systeminfo_cache
=========
.sp
Purpose : Verwaltung des Cache f?ur Syteminformationen.
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        FUNCTION
              a10_ptr_ok (VAR acv : tak_all_command_glob;
                    p : tak_cache_dir_pointer) : boolean;
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
        FROM
              Pointer-Arithmetik : VSP35;
 
        FUNCTION
              s35add_bufaddr (buf_addr : tsp_bufaddr;
                    pos : tsp_int4) : tsp_bufaddr;
 
        FUNCTION
              s35le_bufaddr (addr1 : tsp_bufaddr;
                    addr2 : tsp_bufaddr) : boolean;
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
        PROCEDURE
              s35add_bufaddr;
 
              tsp_int4 tsp_bufaddr
 
        FUNCTION
              s35le_bufaddr;
 
              tsp_addr tsp_bufaddr
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : ThomasA
.sp
.cp 3
Created : 1985-02-05
.sp
.cp 3
Version : 1999-01-04
.sp
.cp 3
Release :      Date : 1999-01-04
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
 
.pb '@'
.pa
General :
.sp
The AK cache is a 48-K area of memory that forms the interface
between the AK modules and the catalog, i.e. catalog records
are transferred from the system files to an area in the cache and the
AK modules then access these records via pointers. Newly built
catalog records are also first of all built in the cache and
then are they passed to KB for inserting or updating.
.br
Because of the size of the cache and the locality principle of
applications, frequent KB requests are reduced to the system files,
which is important particularly in distribution.
Cache management is accomplished by means of the cache
directory and the free-memory management.
The cache directory contains information about the catalog records
allocated in the cache. For each catalog record, the
following information is stored in the directory:
.sp
.hi +12
d_pointer^: ^is the pointer to the cache address starting at which
the catalog record is stored in the cache.
.br
d_posp^@@@: ^relative position of the record in the cache.
.br
d_state^@@: ^specifies the state of the record allocated in cache.
If the record may not be shifted within the cache or may not be
displaced from the cache, dfix is specified. Otherwise the record may be
shifted or displaced.
The d_state = dnot_exist is assigned if, on accessing the
system file, it is found that a catalog record that has been
requested does not exist. In subsequent accessing of the same record,
it is then possible without KB access to decide that the record does
not exist (access to Public Tables without PUBLIC). The states dwritten
and dadd_rec are used for temporary catalog records only.
Temporary records are
not written through immediately upon the Insert or Update command,
but only when the record is to be displaced from the cache.
This frequently dispenses with the need for BD operations
in the case of separate parsing/executing. The state dwritten indicates
that the record must be viewed as inserted into the temporary
catalog file, whereas dwritten indicates that the record has already
been inserted into the temporary catalog file.
.br
d_syslen^@: ^Length occupied by the block in the cache.
.br
d_sysclock: contains a kind of access counter of the record.
This counter is used in displacing in order to decide which
record will be displaced.
.br
.sp;.hi -12
The directory entries are sorted in ascending order according to
the keys of the catalog records, so that the search for a record
can be conducted by means of a binary search.
In order, when searching, not always to have to search through
the entire directory, a subdivision has been made
into records with key x'FF...' and those with
key <> x'FF...'. d_first_x_ff identifies the
first directory entry with key x'FF...'.
.br
The free-memory management is stored a structure called tfreelist, where
the positions of the free blocks are stored.
The first 4 bytes of each free block contain the length of the block
and the next 4 bytes contain the position of the free block.
This position is checked against the position stored in the freelist in
order to be able to determine cache violations.
.sp 4
PROCEDURE  A10_INIT_CACHE (VAR acv : all_command_glob;
                           cachep  : takcachebufaddress);
.sp
Initializes the cache buffer and the directory.
The entire cache is then a free block.
.sp 4
PROCEDURE  A10_CACHE_DELETE (VAR acv : all_command_glob)
.sp
The entire cache is emptied. Since catalog records of the parse file are not
written through immediately, they must be inserted beforehand into the parse
file by means of a10temp_add.
.sp 4
PROCEDURE A10_NIL_GET_SYSINFO (VAR acv : all_command_glob;
.nf
                  VAR syskey   : tsysinfokey;
                  dstate       : directory_state;
                  syslen       : int2;
                  VAR syspoint : tsysbufferaddress;
                  VAR b_err    : basis_error);
.sp;.fo
By this procedure, an empty cache area of length syslen is requested for the
catalog record with key syskey. For this purpose, the key is first
searched for in the directory in order to find the insertion point in the
directory. If the key is found during this search, the error message
duplicate_key is reported back.
.br
Otherwise a10_put_mbuf_into_cache is called in  order to search a
free area of length syslen and to store the key in the cache and the
cache directory.
.br
.sp 4;.nf
PROCEDURE  A10_GET_SYSINFO (VAR acv : all_command_glob;
                  VAR syskey   : tsysinfokey;
                  dstate       : directory_state;
                  sysloc       : location;
                  VAR syspoint : tsysbufferaddress;
                  VAR b_err    : basis_error);
.sp;.fo
The catalog record with key syskey is loaded into the cache. For this purpose,
the record is first of all searched for in the cache directory. If the record
is found there, the syspoint is set to the address in the cache under which the
record is allocated.
.br
If the record does not yet exist in the cache directory, it must first of all
be read from the corresponding system file. For this purpose, either the parse
file or one of the system files (KB request) must be accessed. By means of
a10_put_mbuf_into_cache, the record that has been read is transferred to an
area in the cache and the corresponding address is entered in syspoint.
.sp 4;.nf
.sp 4;.nf
PROCEDURE a10_next_sysinfo (VAR acv : all_command_glob;
                  VAR syskey   : tsysinfokey;
                  dstate       : directory_state;
                  sysloc       : location;
                  rec_kind     : int2;
                  VAR syspoint : tsysbufferaddress;
                  VAR b_err    : basis_error);
.sp;.fo
From the location sysloc, the procedure reads the next catalog record with
sreckind = rec_kind into the cache. If rec_kind < 0, the next catalog record is
fetched without examining the sreckind. If the record already exists in the
cache, the old entry is passed to the free-memory management and the new one is
entered in the cache. The next record is read into the message buffer by a KB
request and is then transferred to the cache by means of
a10_put_mbuf_into_cache. The key of the record that has been found is passed in
syskey; syspoint is the address in the cache under which the record is
allocated.
.sp 4;.nf
PROCEDURE  A10_PUT_MBUF_INTO_CACHE (VAR acv : all_command_glob;
                  VAR mbuf     : rel3_mess_buffer;
                  dstate       : directory_state;
                  VAR syskey   : tsysinfokey;
                  VAR syspoint : tsysbufferaddress;
                  VAR b_err    : basis_error);
.sp;.fo
The catalog record in part 2 of mbuf is entered into the cache.
The key of the record and cache address of the record are returned in
syskey and syspoint.
.br
At first the record (i.e. the key of the record) is searched in the
cache directory. If the record is already stored in the cache, nothing
happens. Otherwise the search returns the position in the directory
where the record in part2 of mbuf must be described.
If all directory entries are accupied, a record must be diplaced from
the cache in order to get a free directory entry for the  new record
(a10_search_del_buf).
The next step is to request for a free block of length syslen
(a10_freepos_get). If the request cannot be satisfied, an attempt is
made to satisfy the request by displacing records (a10_search_del_buf). In this
case, it is necessary to redetermine the index where the record is stored
in the directory (a10_index_get).
.br
If, even after records have been displaced, there is no free block available
for the record, there is a programming error and the error message
ak_cachedirectory_full is returned. If this is not the case, a directory entry
is generated for the record (ak10add_ind_in_dir), an entry is made in it,
and the record is copied from mbuf to the allocated cache area.
.sp 4;.nf
PROCEDURE  A10_ALL_RELEASE (VAR acv : all_command_glob)
.sp;.fo
The state dfix is removed from all cache directory entries.
.sp 4;.nf
PROCEDURE  A10_REL_SYSINFO (VAR acv : all_command_glob;
                  VAR syskey   : tsysinfokey);
.sp;.fo
In the directory entry representing the catalog record with key syskey,
the state dfix is removed.
.sp 4;.nf
PROCEDURE  A10_ADD_SYSINFO (VAR acv : all_command_glob;
                  VAR locset   : locnoset;
                  VAR syspoint : tsysbufferaddress;
                  VAR b_err    : basis_error);
.sp;.fo
The catalog record starting at address syspoint in the cache is inserted
into the corresponding system file if it is a permanent catalog record.
If the record is a temporary catalog record, merely the flag
dadd_rec is set, which means that the record is inserted into the parse
file when it must be displaced.
.br
If the record is shorter than the reserved cache area, the remainder is
passed to the free-memory management as a free block (a10_in_freelist).
.sp 4;.nf
PROCEDURE  A10_REPL_SYSINFO (VAR acv : all_command_glob;
                  VAR locset   : locnoset;
                  VAR syspoint : tsysbufferaddress;
                  VAR b_err    : basis_error);
.sp;.fo
If the catalog record starting at address syspoint in the cache is
a permanent catalog record, it is inserted into the corresponding
system file by  a KB Update order.
Since temporary catalog records are not written through directly,
nothing needs to be done for them.
.sp 4;.nf
PROCEDURE  A10_UPD_KEY (VAR acv : all_command_glob;
                  VAR parsk    : parskey;
                  displacement : integer;
                  VAR b_err    : basis_error);
.sp;.fo
In all related parse information records with key parsk,
the parsk.p_no part is reduced by displacement, i.e. virtually a
key update is performed for the records.
.br
The number of records to be handled is determined from the first parse
information record.
.br
Each record to be handled is loaded into the cache by a10_get_sysinfo. The
associated directory entry is placed in intermediate storage and is then
deleted in the directory. By means of a10_index_get, a search is
then made for the insertion point in the directory for the new key
and the original entry that was saved is transferred there.
By means of a10_add_sysinfo, the record is then marked as to be inserted.
.sp 4;.nf
PROCEDURE  A10_DEL_SYSINFO (VAR acv : all_command_glob;
                  VAR locset   : locnoset;
                  VAR syskey   : tsysinfokey;
                  VAR b_err    : basis_error);
.sp;.fo
The catalog record with key syskey is deleted. For this purpose,
the record is
first of all removed from the cache and from the directory
(a10_buf_in_freelist). If the record to be deleted is a permanent record,
it is removed from the corresponding system file by a KB Delete
command. Conversely, a temporary catalog record only needs
to be deleted from the parse file if it
has already been written through (dwritten in state).
.sp 4;.nf
PROCEDURE  A10DEL_USER_TAB_SYSINFO  (VAR acv : all_command_glob;
                  VAR locset : locnoset;
                  VAR tabid  : tableid;
                  VAR b_err  : basis_error);
.sp;.fo
All catalog records whose keys have the value of tabib in the stableid
field are deleted both from system file 1 and from system file 2.
For this purpose the corresponding delete order is sent to KB.
By means of a10table_cache_delete,
all relevant catalog records are then deleted from the cache.
.sp 4;.nf
PROCEDURE  A10RELEASE_TABLE (VAR acv : all_command_glob;
                  VAR tabid  : tableid);
.sp;.fo
In all cache directory entries
concerning the table determined by tabid the state dfix is removed, which
means that the corresponding catalog records allocated in cache are
allowed to be shifted or displaced.
.sp 4;.nf
PROCEDURE  A10_INDEX_GET (VAR acv : all_command_glob;
                  VAR syskey : tsysinfokey;
                  VAR keyind : integer;
                  VAR newind : integer);
.sp;.fo
The catalog record with key syskey is searched for in the directory
by means of a binary search. If the key is found, keyind subsequently
contains the corresponding directory index;
otherwise, keyind = 0 and newind conains the
directory index where the syskey must be inserted.
.sp 4;.nf
PROCEDURE  A10_LOCK_SYSINFO (VAR acv : all_command_glob;
                  VAR locset : locnoset;
                  VAR syskey : tsysinfokey;
                  lockm      : lockmode);
.sp;.fo
By calling the procedure, it is possible to lock catalog records with
the lock mode lockm. The corresponding command is sent to KB.
.br
The locking of individual records is not possible in system file 1;
instead, all records with tableid = syskey.stableid are locked by KB.
.br
In system file 2, on the other hand, only the syskey that has been
transferred is locked.
.sp 4;.nf
PROCEDURE  A10TABLE_CACHE_DELETE (VAR acv : all_command_glob;
                  VAR tabid  : tableid);
.sp;.fo
All catalog records of the table determined by tabid
are removed from the cache. This is
done for each relevant record by means of a10_buf_in_freelist.
.sp 4;.nf
PROCEDURE  A10_KEY_DEL  (VAR acv : all_command_glob;
                  VAR syskey : tsysinfokey);
.sp;.fo
The catalog record with key syskey is removed from the cache. By means of
a10_index_get, first of all, the corresponding directory index
is determined and the record is removed from the cache and
from the directory by  means of a10_buf_in_freelist.
.sp 4;.nf
PROCEDURE  A10_SEARCH_DEL_BUF (VAR acv : all_command_glob;
                  VAR sl      : integer;
                  VAR freepos : int4);
.sp;.fo
The procedure attempts to generate a free block of length sl
in the cache by the displacing of entries.
If the attempt is successful, the position of the
free block is returned in freepos.
.br
If no free memory is found and if there is no more entry that
can be displaced (no entry which does not contain dfix in its state),
there is an error message.
.br
In a loop, a search is made in the directory for the next entry to be
displaced. For this purpose, starting at index d_pos+1, the clock pointer
d_clock of the respective directory entry is decremented by 1
until a clockpointer containing 0 is found.
If the record is allowed to be displaced,
the corresponding entry is deleted from the directory
and the associated cache area is made available as free memory.
.br
If memory has been released in the cache,
there is a check as to whether a free block of the
requested length is now available (a10_freepos_get).
If sl = 0, freepos is set to = -1.
.br
This is repeated until freepos <> 0, or until there is
no further entry which can be released.
If no available block of the requested length has been found until now,
its possible that a block of the requested length can be created by cache
compactification. Cache compactification is allowed, if the flag
acv.compact_allowed is TRUE.
In this case the compactification is done and an
attempt is then made to satisfy the request by means of a10_freepos_get.
If at the end of the procedure no block has been found which satisfies
the request, this is an error that must not occur in actual fact.
(Incorrect implementation or the cache buffer has been
defined too small (at least 10 * maxbufferlength)).
.sp 4;.nf
PROCEDURE  A10_TEMP_ADD  (VAR acv : all_command_glob;
                  index      : integer);
.sp;.fo
The procedure is called whenever a catalog record
is displaced from the cache.
Temporary entries may possibly be written through only at this point. If
the catalog record described by the directory entry index is a temporary,
one, it must, if applicable, be written into the parse file.
If dwritten in state, this means that the record is already stored
in the parse file and, therefore, an update must be performed.
If only dadd_rec in state, the record has been built in the cache and
an a10_add_sysinfo has been performed. The record must, therefore, now be
inserted.
.sp 4;.nf
PROCEDURE  A10_FREEPOS_GET  (VAR acv : all_command_glob;
                  VAR required_len : integer;
                  VAR freepos      : int4);
.sp;.fo
According to the first fit method, a free block of
length >= required_len is searched for in the free-memory list.
If a free block is not found, freepos is
then = 0. Otherwise, freepos contains the position of the free block.
Required_len is always aligned to 4 bytes, so that freepos,
too, is always aligned to 4 bytes.
.sp 4;.nf
PROCEDURE  A10_BUF_IN_FREELIST (VAR acv : all_command_glob;
                  dirind : integer);
.sp;.fo
The directory entry with index dirind is removed from the directory
(a10del_ind_in_dir) and the associated cache area is passed
to the free-memory management (a10_in_freelist).
.sp 4;.nf
PROCEDURE  A10_IN_FREELIST (VAR acv : all_command_glob;
                  block_pos : int4;
                  block_len : integer);
.sp;.fo
The block starting at position block_pos of length block_len
is marked as a free block by insertion into the free-memory list.
If the block adjoins free
blocks on right and/or left, these are combined to form one free block.
.sp 4;.nf
PROCEDURE  AK10ADD_IND_IN_DIR (VAR acv : all_command_glob;
                  ind            : integer;
                  is_x_ff        : boolean);
.sp;.fo
At position ind in the directory, space is created for a directory entry.
This is done by shifting the following entries to the right.
If an entry with syskey x'FF...' is to be entered,
it may be necessary for d_first_ff to have a new
entry made in it.
.sp 4;.nf
PROCEDURE  A10DEL_IND_IN_DIR (VAR acv : all_command_glob;
                  ind     : integer;
                  is_x_ff : boolean);
.sp;.fo
The directory entry with index ind is removed from the directory.
The position
of the first key x'FF...' d_first_xx may have to be updated.
.sp 4;.nf
PROCEDURE  A10PUT_BLOCK_LENGTH (VAR acv : all_command_glob;
                  pos  : int4;
                  len  : int4;
                  check_pos : boolean);
.sp;.fo
The value of the parameter len is written into
the cache at postion pos + 4.
If check_pos is true, the value of pos is compared with the value
stored at position pos. If the values are not equal, a cache violation
has been occured and the corresponding errormessage is returned.
If check_pos is false the value of pos is stored at position pos in the
cache.
.sp 4;.nf
PROCEDURE a10get_block_length (VAR acv : all_command_glob;
            block_pos        : int4;
            VAR block_length : int4);
.sp;.fo
The procedure determines the length of the free block starting at
position block_pos. To be able to determine cache violations,
block_pos is first of all compared with the position stored in
the free block. If the result is unequal, a cache violation has been
occured and the corresponding errormessage is returned. Otherwise
the length of the block is returned in block_length.
.sp 4;.nf
PROCEDURE  A10_VERSION (VAR acv : all_command_glob;
            VAR p_arr      : tsyspointerarr;
            m_type         : message_type;
            view_scan      : boolean);
.sp;.fo
The file version number of the table determined by p_arr
is increased (m_type = m_succ_file_version) or initialized.
The new file version is stored in the treeid of the first tbaserecord of
p_arr.
If view_scan is TRUE, the version number
is updated in all dependent views by a27view_scan.
.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
 
.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:
 
.CM *-END-* structure -----------------------------------
***********************************************************
.sp 2
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :
 
 
CONST
 
TYPE
 
      tak10cache_header = RECORD
            ch_next_cache : tsp_bufaddr;
            ch_size       : tsp_int4;
      END;
 
      tak10cache_header_ptr = ^tak10cache_header;
 
 
(*------------------------------*) 
 
FUNCTION
      a10_ptr_ok (VAR acv : tak_all_command_glob;
            p : tak_cache_dir_pointer) : boolean;
 
VAR
      ok   : boolean;
      size : integer;
 
      start_ptr, end_ptr : RECORD
            CASE integer OF
                1 :
                    (bufaddr : tsp_bufaddr);
                2 :
                    (chptr   : tak10cache_header_ptr);
                3 :
                    (i4      : tsp_int4);
                END;
            (*ENDCASE*) 
 
 
BEGIN
ok := false;
IF  p.buf_ptr <> NIL
THEN
    BEGIN
    start_ptr.bufaddr := acv.a_sysdir.ci_cache_p;
    size              := 1;
    WHILE (start_ptr.bufaddr <> NIL) AND NOT ok DO
        BEGIN
        size := start_ptr.chptr^.ch_size;
        end_ptr.bufaddr := s35add_bufaddr (start_ptr.bufaddr,
              sizeof (tsp_buf) * size);
        IF  end_ptr.i4 > start_ptr.i4
        THEN
            BEGIN
            IF  (s35le_bufaddr (start_ptr.bufaddr, p.buf_ptr)) AND
                (s35le_bufaddr (p.buf_ptr, end_ptr.bufaddr))
            THEN
                ok := true;
            (*ENDIF*) 
            END
        ELSE
            IF  (p.i <= start_ptr.i4) AND (p.i >= end_ptr.i4)
            THEN
                ok := true;
            (*ENDIF*) 
        (*ENDIF*) 
        start_ptr.bufaddr := start_ptr.chptr^.ch_next_cache
        END;
    (*ENDWHILE*) 
    a10_ptr_ok := ok
    END
ELSE
    a10_ptr_ok := true;
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
*-PRETTY-*  statements    :         15
*-PRETTY-*  lines of code :         66        PRETTYX 3.10 
*-PRETTY-*  lines in file :        608         1997-12-10 
.PA 
