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.
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:
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.
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.
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
means System list.This list cannot be used by users.
means Temporary list. Users can use it as they want.
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.
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:
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.
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)
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
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
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 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
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: