BOS-banks



next up previous contents
Next: Bank documentation Up: ALEPH Programmers hints Previous: Naming of SUBROUTINES

BOS-banks

BOS is the memory manager chosen for ALEPH software. As data structure we use the entity-relationship model. The Bos manual [2] is available in the ALEPH documentation office.

There are two types of banks in the system: Named banks and work banks. All named banks shall be described in the form of DDL (Data definition language). Any named bank created shall have its FORMAT defined by a call to BKFMT. Any bank should have a mini-header of two integer numbers giving the number of columns and the number of rows of the table.

Lists of BOS-Banks

There are 5 lists available in the BOS system : C, E, R, S, T. A list is a collection of bank names, a bank name can appear in various lists. A bank name can be on a list even if the bank does not exist. A bank name can be deleted from a list without dropping the bank. We use the following conventions:

  1. 'C' list

    means Constants list. This list contains the names of all banks containing constants valid for more than one event (usually for a run). The banks which names appear on the 'C' list are written on the output before the 1st event. Then the 'C' list is reset to '0', but the banks of constants are kept.

  2. 'E' list

    means Event list. This list contains names of banks which belong to the current event (input or output). A bank can be added to the 'E' list by a process or can be deleted from the 'E' list by a process. Information going from one process to the next must go to the 'E' list. At the end of an event the 'E' list is written to output, then the 'E' list is dropped.

  3. 'R' list

    means Reading list This list contains the names of all banks read in a logical record. The 'R' list is reset to '0' before reading. After reading, the content of the list is analyzed.

    IF the EVEH bank is  found THEN
        it is  an event  record and 'E' list = 'R' list
    ELSE it is a Constant  record 
        and new names  are added to the 'C' list 
        'C' list = old 'C' list + 'R' list 
    ENDIF

  4. 'S' list

    means System list.This list cannot be used by users.

  5. 'T' list

    means Temporary list. Users can use it as they want.

HAC (HAnd Coding)

In order to unify the way in which tables are handled we present here guidelines for the coding using mostly statement functions. Statement functions are expanded by the compiler in-line and can be treated subsequently by the optimizer.

Mapping of tables onto BOS-banks

A 'mini header' at the beginning of every BOS-bank gives the row length and the number of rows of the ADAMO table that is mapped onto the BOS-bank. Relations to rows of tables will be represented by integer numbers giving the row number (id) of the target. The long name of an entity set appearing on data-flow-diagrams will be mapped upon a four-character long BOS-bank name. The correspondence of long and short name should be given already in the data-dictionary [6].

Two types of banks are possible:

  1. Static tables the id is implicitly given by the position (row number) in the table.
  2. Dynamic tables the id is explicitly given as an integer number at the beginning of every row.

The latter form is preferable in the case where rows of the table are suppressed frequently and relationships should be easily maintained. In the TAP dynamic tables are mapped onto single BOS-banks. An alternate way is to use the BOS bank numbers.

Name Index

Maintaining the 'name-index' : Each named bank has a name-index set by BOS the first time a name is encountered. This name-index does not change during the processing even after garbage collection. The user has access to the name-index through the function NAMIND.

              NAXYZT = NAMIND ('XYZT')
NAXYZT is the name-index of the bank XYZT. The index of the bank XYZT is stored in JQ(NAXYZT).
              KXYZT = JQ(NAXYZT)
JQ(NAXYZT) is updated after garbage collection. The following scheme for named banks is adopted:

Each process sets a common block called /xxNAMC/ (xx being the two letter code of the process) with the name-indices of all the banks created and filled by the process. This common block will be filled at initialization time. The format of the banks will be defined at the same time.

The name of the name-indices is of the form : NAxyzt, xyzt being the bank name starting with the 1st letter code of the process.

   i.e. - ITC processor
          SUBROUTINE ITIRUN
  C! initialization of ITC module
  *CA JQCOM
  *CA ITNAMC
  C
  C - Set name-indices
        NAITHT = NAMIND ('ITHT')
        NAITDI = NAMIND ('ITDI')
        NAITDT = NAMIND ('ITDT')
        NAITTD = NAMIND ('ITTD')
  C
  C - Define bank formats
        CALL BKFMT ('ITHT','2I,(3I,6F)')
        CALL BKFMT ('ITDI','B16')
        CALL BKFMT ('ITDT','I')
        CALL BKFMT ('ITTD','I')
 C
        RETURN
        END

Then the access to a name bank will be done through the name-index for the 1st bank :

  *CA xxNAMC
  *CA JQCOM
  *CA BMACRO
           KXYZT = JQ(NAXYZT)
  C - if necessary the index of the next bank is :
           KXYZ2 = JQ(KXYZT-1)

Creating a named-bank

BOS banks should not be created directly through calls to BOS routines. Instead, the routine AUBOS should be used. This checks whether there is enough space. If not, a garbage collection is done. If this fails as well, the processing of the current event is terminated. Assume a process called PROCES which creates and fills the bank PBNK. The process is entered only once per event.

To CREATE the bank PBNK the following has to be done:

        1st check the existence of the bank,
        IF yes, RENAME it, or DROP it.
        THEN create the bank.
        THEN put the bank on a list :   'E' event list put on output file
                'T' temporary list drop after the processor

Example

          SUBROUTINE PROCES
   C! PROCES module
   *CA JOBCOM  contains flags and counters
   *CA JQCOM   BOS array
   *CA PRNAMC  name-index for PROCES
   *CA BMACRO  statment functions
   C
   C - if PBNK exists rename it as OPBK or drop it depending on FKEPJO
          KPBNK = JQ (NAPBNK)
          IF ( KPBNK .NE. 0 ) THEN
             IF (FKEPJO) THEN
                CALL BSWAP ( JQ,'PBNK','OPBK')
             ELSE
                CALL BDROP ( JQ,'PBNK' )
             ENDIF
          ENDIF
    C
    C - THEN create the bank 'PBNK', NR=0, with NROW of NCOL words
          LEN = NROW * NCOL + LHEVT
          CALL AUBOS ('PBNK',0,LEN,KPBNK,IGARB,*998)
    C
    C - THEN put the bank on the 'E' list
          CALL BLIST (JQ,'E+','PBNK')
    C
          RETURN
          END

Statement functions to access tables

A number of statement functions have been defined for the Monte-Carlo program. They are stored in the COMDECK BMACRO. Statement functions are expanded by the compiler into the code and thus do not create major overhead in execution time.

*CD BMACRO        set of intrinsic functions to handle BOS banks
C - # of cols/row in bank with index ID
      LCOLS(ID) = JQ(ID+1)
C - # of rows in bank with index ID
      LROWS(ID) = JQ(ID+2)
C - index of next row in the bank with index ID
      KNEXT(ID) = ID + LHEVT + JQ(ID+1)*JQ(ID+2)
C - index of row # NRBOS in the bank with index ID
      KROW(ID,NRBOS) = ID + LHEVT + JQ(ID+1)*(NRBOS-1)
C - # of free words in the bank with index ID
      LFRWRD(ID) = ID + JQ(ID) - KNEXT(ID)
C - Lth integer element of the NRBOSth row of the bank with index ID
      ITABL(ID,NRBOS,L) = JQ(ID+LHEVT+(NRBOS-1)*JQ(ID+1)+L)
C - Lth real element of the NRBOSth row of the bank with index ID
      RTABL(ID,NRBOS,L) = QJ(ID+LHEVT+(NRBOS-1)*JQ(ID+1)+L)

Examples

        SUBROUTINE NEWHIT(HIT)
        DIMENSION HIT(*)
*CA JOBCOM,JQCOM,XXNAMC,BMACRO
C-------------------------------------------
C       get index of bank 'XXHT'
C
        JXXHT = JQ(NAXXHT)
C
C       if bank does not exist -- return
C
        IF (JXXHT.EQ.0) RETURN
C
C       get # of words/hit
C
        NWRD = LCOLS(JXXHT)
C
C       check if there is enough space to fill a row
C
        IF (LFRWRD(JXXHT).LT.NWRD) THEN
C
C         increase bank length by NHIT
C
          ND = JQ (JXXHT) + NHIT * NWRD
          CALL AUBOS ('XXHT',0,ND,JXXHT,IGARB,*998)
        ENDIF
C
C       get the index for the next row
C
        KXXHT = KNEXT(JXXHT)
        CALL UCOPY(HIT,QJ(KXXHT+1),NWRD)
C
C       increment the # of filled rows
C
        JQ(JXXHT+2) = JQ(JXXHT+2) + 1
        GOTO 999
 998    LERRBO = .TRUE.
 999    RETURN
        END
        FUNCTION INLOC ( KIND,IREL,ICOL)
C
C       locate the row # which contains the value IVAL in column # ICOL
C       of the bank known by its index KIND
C
C       if ICOL<1 or > # of columns of the table then return INLOC = -1
C       if the value IVAL is not found then return INLOC = 0
C       if the index KIND = 0 then return INLOC = -2
C
*CA JQCOM,BMACRO
C
        IF (IND.EQ.0) THEN
          INLOC = -2
           GOTO 999
        ELSE
          IF (ICOL.LT.1.OR.ICOL.GT.LCOLS(KIND) )THEN
            INLOC=-1
            GOTO 999
          ELSE
            DO 100 I = 1,LROWS(KIND)
              IF (IVAL.EQ.ITABL(KIND,I,ICOL)) THEN
                INLOC = I
                GOTO 999
              ENDIF
 100        CONTINUE
          INLOC = 0
 999      RETURN
          END

Inverting Relationships

Assume a static table known by its bank index KBNK2 which contains in column ICOLR the relation to table 1.

The routine UINDXS will build 2 banks:

IWREL(1) is a table with 3 columns. It has as many rows as table 1.
IWREL(1)[col1]          will contain a list sorted in increasing order of
                        relations with bank1
IWREL(1)[col2]          will contain the # of elements of table2 associated
                        with the element of bank1
IWREL(1)[col3]          pointer into the bank IWREL(2) to the first element
                        of table 2 associated to the current row of table 1.
IWREL(2)                is a list of pointers to rows of table 2.

Work-banks

Work-banks are used within the BOS system [2] for the purpose of storing banks, that are used by the BOS system itself (banks to hold the FORMAT information, banks of indices of named banks produced by call to BWIND,...). In the ALEPH off-line software work-banks can be used to temporarily store information within a module. If improperly used, work-banks can be a source of serious problems, that are very difficult to trace. We therefore require, that the following rules be followed:

RULES

  1. A work bank index has to be in a common block. (otherwise the variable may be put into a register by the compiler and in a garbage collection something else than the pointer will be updated)
  2. A work bank index cannot be a subroutine argument (similar reason as 1.).
  3. A work-bank shall be dropped at the end of a module.
  4. A work bank index shall be set to 0 (zero) once before the first creation of the bank (It should not be assumed, that variables are initially set to 0 on every computer).
  5. There should be no path in the program, whereby a work-bank index can be modified (e.g. set to zero) for an existing work-bank. (If this rule is violated, there will be two banks, the real one and one 'dead' bank in the BOS structure. During a garbage collection the pointer will be updated twice, first to point to the good bank and immediately later to point to the 'dead' bank which will contain data from a previous pass through the program-module - sometimes several events back. This will at least give bad results).
  6. If a bank is not only used locally (i.e. in more than one FUNCTION or SUBROUTINE), it should be given a name in the following way: IW(KWINDX-3)=INTCHA('WSRT') , where KWINDX is the bank index and WSRT the name. This will facilitate debugging in the work-bank area.

A typical way of using a work-bank is as follows:

      SUBROUTINE EXAMPLE(IERR)
      ...
      COMMON/EWINDX/KWINDX              | Rule 1
      LOGICAL FIRST                     | Note 1
      DATA FIRST/.TRUE./                |
      ...
      IF(FIRST) THEN                    | Note 2
         KWINDX=0
         FIRST=.FALSE.
      ENDIF
      ...
      CALL WBANK(IW,KWINDX,LEN,*995)    | Note 3
      ...
 995  WRITE ....
      IERR=3
      GOTO 999                          | Note 4
 996  IERR=4
      GOTO 999                          | Note 4
      ...
 999  CALL WDROP(IW,KWINDX)
      RETURN
      END

NOTES:

  1. Please note that "LOGICAL FIRST/.TRUE./" is not allowed by FORTRAN77.
  2. Make sure, that this construct does not appear in more than one routine for the same index. Otherwise rule 5 may be violated.
  3. This structure and the rules apply also, if you call instead of WBANK the routines BKTOW,BWIND,UINDXS which also create work-banks with a user-given index.
  4. Every error exit of a subroutine should go through the part of the module where work-banks are dropped.



next up previous contents
Next: Bank documentation Up: ALEPH Programmers hints Previous: Naming of SUBROUTINES



Eric Lancon
Thu Sep 29 15:07:07 MET 1994