July 31, 1997 OCS - The E781 Open Constant System ___________________________________ (valid for version v2_4) INTRODUCTION The Open Constant System (OCS) is a set for FORTRAN 77 routines and shell scripts which manage the constants files for E781. All constants files are kept in a single directory tree. Most of these are ASCII text files which can be read and managed with the UNIX tools and editors as well as OCS fortran routines. All OCS constants files contain one or more blocks. A block consists of a key and the particular set of entries for which correspond to that key. It is terminated by '*end' line. The key identifies the particular version of a table. A table is the basic unit of data managed by OCS. It is a user defined group of constants. OCS manages the keying so that the correct set of constants are identified for any particular key (run number, constant class and version...). OCS is invoked with simple calls in the initialization sections of working routines. It will see to it that the currently correct version of each constant table is located among the constant files and loaded into the corresponding constant common block for that table. It also provides optional tools to modify and link constant common blocks. The constant files may be standard form text files or files in user specified formats (either text or binary). In the latter case user code is required to read in the file and fill the constant common block. OCS constant tables are defined by the Fortran include files which describe the common block which contains the table at run time. A section of each of these include files is written in a fixed format as a "DDL" (Data Description Langauge" description of the structure of the table. These include files are read by the OCS routines as text files at initialization time during program execution. This technique allows these table to be reorganized and expanded without requiring modification to all previously existing copies of the table in the database. It also provides a one to one correspondance between the text stored for any constant in a table and the Fortran variable name where that constant may be found at execution time. OCS FILES OCS standard form text files are free format and are handled automatically without user code. The only absolute conventions are that a '#' in column 1 tags a key line, '!' in column 1 tags a comment line and '*' in column 1 tags a block terminating line (blocks are data terminated with a line, beginning with '*end'). Like in Fortran, end of line comments preceeded with a '!' are optional. Standard form OCS text files have the following elements: file.ocs ! files' name ! keyed block ! only keyed blocks ! ! are managed by OCS ... ! as many in a file as you like [eof] keyed block ! standard form of keyed block #key ! see format below table data ! see format below *end ! terminating line required ! ! any number of commentary lines ! (beginning with !) allowed key ! standard key format #table_name first_run last_run mode class version date time author ! comment # ! required key prefix table_name ! c*12 required name of table. table_name//'_cbk.inc' ! is corresponding common block/DDL first_run ! i*4 first valid run number last_run ! i*4 last valid run number (0 - for ALL runs.ge.first_run) mode ! c*8 data mode 'fill' ! table data in FILL_TABLE form follows ! - clear and refill table in memory 'mod' ! table data in FILL_TABLE form follows ! - modify existing table in memory 'binary' ! users "binary" (non standatd) format - OCS table has ! only file name where the table is located ! string available to user to keep table format class ! c*8 class of constants (must begin with [a-z]) ! to select group of tables version ! c*8 version of constants (must begin with [a-z]), default=' ' ! "Latest" is by alphanumeric order in lower case date ! c*11 constant creation date format='dd-Mon-yyyy' time ! c*8 constant creation time format='hh:mm:ss' author ! c*8 constant author identifier ! ! ! comment delimiter comment ! c*80 Any comment that will fit on the line table data ! format of standard form OCS table for 'fill' or 'mod' mode ! all input is free format done using the ARG routine. field names ! column labels for table. MUST match the variables ! defined in the include file (DDL) [field_table] data values ! field data for a record. one line per record. ! *end ! terminating line modes fill ! clear present table common block and fill with the ! records in the order given mod ! search the first field given in the memory for a match ! with the table data. replace all other given fields in ! that record with the table data binary ! stores in memory only file name where the table is located ! ! for non-standard (user read) text tables may be any non- ! blank string except 'fill' or 'mod'. Available to user ! to keep table format Examples Defines two standard and one user tables for a range of runs [1111-2222]. Changes the spectrometers z positions for runs [2000-2222]. One table (spec_sz) is in use for all runs. #spec_pos 1111 2222 fill mc v03.10 07-Mar-1996 11:50 AK ! spectrometer positions name x y z bm 0.0 0.0 0.0000 vx 0.0 0.0 0.0000 ! M1 magnet position: m1 0.0 0.0 199.4043 ! M2 magnet position: m2 0.0 0.0 751.1155 a2 0.0 0.0 2760.0 b2 0.0 0.0 3360.0 c2 0.0 0.0 3960.0 ! M3 magnet position: m3 0.0 0.0 4245.7095 *end #spec_sz 0 0 fill mc v03.10 07-Mar-1996 11:50 AK ! spectrometer sizes name x y z1 z2 bm 200.0 200.0 -200.0000 0.0000 vx 200.0 200.0 0.0000 199.4043 m1 200.0 200.0 199.4043 751.1155 m2 200.0 200.0 751.1155 2760.0 a2 200.0 200.0 2760. 3360.0 b2 200.0 200.0 3360. 3960.0 c2 200.0 200.0 3960. 4245.7095 m3 200.0 200.0 4245.7095 10000.0000 *end #scaler 3624 3624 text example v02.00 16-JUL-90 17:23 psc ! E761 online scalers spill count B1 B2 T2.BV B3 0 1 5272774 6813575 0 4470157 2 2 4749276 6117738 0 4025935 3 3 2948957 3782012 0 2501156 1 4 4781003 6181995 0 4051291 -1 71.0 3.778E+08 4.878E+08 0.000E+00 3.196E+08 *end #spec_pos 2000 2222 mod mc v03.10 15-Apr-1996 14:00 AK ! spectrometer positions name z m1 199.4 m2 751.1 a2 2760.0 b2 3360.0 c2 3960.0 m3 4245.62 *end #user 2222 2222 binary example v01.00 15-Mar-1993 23:23 psc ! example of a binary file /home/pcooper/e781/off781/ocs/testing/peter_ocs *end #user 3333 3333 binary example v02.00 05-Jun-1996 23:33 rud ! example of a binary file $CON781_DIR/testing/peter_ocs *end For version v02.00 of 'user' binary table you may see use of environment variable in a file name. FORTRAN USAGE OCS subroutines with their arguments and functions are listed below. All routines which call OCS routines may have following OCS control include: #include "ocs_cbk.inc". OCS kernel routines: * routine 'ocs_update' - At first call initialises OCS and loads in memory common blocks standard OCS form tables, given in 'ocs_fill' routine. At any following calls it reloads those tables which don't correspond to current 'ocs_run'. * logical function ocs_register(ocs_id, routine, owner_list, user_list) out in in in i4 c12 c* c* - Registers calling routine with OCS Identify all users of constant tables to OCS system. - On first entry initialize the OCS system. - Identify 'routine' with 'ocs_id' which is the internal index into the OCS control tables ('ocs_id' is a local variable defined in ocs_cbk.inc). - Book 'routine' as a "owner" or "user" of the table names listed in 'owner_list' and 'user_list' respectively. - Return '.false.' if an error is detected. Example - see below APPENDIX 1. * logical variables 'ocs_new_const(ocs_id)' in #include "ocs_cbk.inc" Determine if ANY tables used by the calling routine need to be filled, - '.true' if any table user by the calling routine needs to be filled (or refilled). Example - see below APPENDIX 1. * logical function ocs_table(ocs_id, mode, l_cur, line) in out out/in out i4 log i4 c*1024 - Find all tables owned by the calling routine which have to be updated. - Fill standard form table commons automatically. - Return .true. to user with file open on Fortran unit 'ocs_unit' and corresponding key in 'line' for each user formatted table. - Calling routine should determine which table is open from 'line[1]' and the tables' format from line[4]. (line[4] is the fourth argument parsed from 'line' by the ARG routine.) - If format is 'binary' user must read the file name from the next line read and open that file (see below APPENDIX 1). - Read in that table. - Close any files opened - Returns '.false.' when done. Example - see APPENDIX 1 below. * logical function ocs_link_table(table1, l1, n1, table2, l2, n2, link2, c1, c2) in in in in in in out in in c12 i4 i4 c12 i4 i4 i4 i4 i4 - Link one OCS table to another in memory - For each record in table2 scan for a character match with table1(c1:c2) ('name' field); l1 is first dimension of table1, n1 is number of filled rows and same for table2; - store the number of the matched 'table1' record in 'table2' variable 'link2' Example - see APPENDIX 1 below. * logical function ocs_link_tables(table1, name1, table2, name2, link2, c1, c2) in in in in out in in c12 c12 c12 c12 i4 i4 i4 is a new version of previous routine with modified set of arguments, where table1 - name of table-1, table2 - name of table-2, name1 - table-1 name fields, name2 - table-2 name fields, link2 - link in table-2 to table-1 (row number), c1, c2 - string region to match: c1 - first symbol, c2 - last symbol "Link" means that for each record 'name2' in 'table2' routine scan for a character match with 'name1'(c1:c2) ('name' field) and store the number of the matched 'name1' record in 'table2' variable 'link2'. Example - see APPENDIX 1 below. * routine ocs_nafrel(l2, n2, link2, ind1, ind2, c1, c2) in in in in out out out i4 i4 i4 i4 i4 i4 i4 - Link a standard E781 DB common block table to another one by ADAMO like NAFREL way (in MC, for example); where l2 - length of table-2 records n2 - number of entries in table-2 link2 - array of links in table-2 to table-1 ind1 - current position in the table-1 ind2 - current position in the table-2 c1 - string region to match - first c2 - string region to match - last * routine ocs_load_table(table,class,version,f_run,l_run,ierr) in in in in in out c12 c8 c8 i4 i4 i4 - Load new version of the table in memory. table - TABLE name class - input string with CLASS name version - input string with VERSION name f_run - intput FIRST-RUN number l_run - intput LAST-RUN number ierr - ERROR flag: = 0 if OK, = 1 if requested table not found * routine ocs_load_version(class, version, ierr) in in out c8 c8 i4 - Load new version of all tables. For given 'class' those versions will be taken which are not "older" than 'version'. class - CLASS name version - VERSION name ierr - ERROR flag: = 0 if OK, = 1 if NO tables was found * integer function ocs_ntab_reload(key, tables, classes, versions, f_runs, l_runs) out in out out out out out i4 i4 c12(*) c8(*) c8(*) i4(*) i4(*) * = 'mftab' in 'ocs_update' - Function to search for table versions of the same class as current is, which should be refilled for new RUN number. Gives number of those tables as output value. Arguments: key - flag: 1 - reload of all found tables 0 - NO reload, list only tabs - output array with TABLE names classes - output array with CLASS names versions - output array with VERSION names f_runs - output array with first-run numbers l_runs - output array with last-run numbers * routine ocs_bin_table(table, bin_file, ierr) in out out c12 c* i4 - Get file name for the binary table. Arguments: table - TABLE name bin_file - output string with file name for the table ierr - ERROR flag: = 0 if OK, = 1 if requested table not found * routine ocs_tab_version(table,class,version,f_run,l_run, modes, n_out) in out out out out out out c12 c8 c8 i4 i4 c8(20) i4 ........ #include "ocs_tab_version.inc" ! for 'class,version,f_run,l_run,modes,n_out' - Get info about the active table. Arguments: table - TABLE name class - output string with CLASS name version - output string with VERSION name f_run - first RUN for the table l_run - last RUN for the table modes - modes for the table n_out - number of table parts found: =0 in error case, =1 if only 'fill' part found, >1 if 'mod' part(s) found OCS printing routines: * routine ocs_prin_table(table, nrow, xtab, calling) in in in in c12 i4 r4 c* - Print onto unit 'ocs_prt_unit' (see 'ocs_cbk.inc') standard OCS table 'table' stored in array 'xtab' having 'nrow' filled rows heading by 'calling' with the name of calling routine & comment. Example - see routine 'test_ocs.F' below. * routine ocs_prin_all(table, calling) in in c* c* - Print ALL standard OCS tables filled by 'ocs_fill.F' if first argument is empty (' '). Prints only given 'table' if it was specified. To generate routine 'ocs_prin_all.F' type command ocs_prin_all_maker or (better!) type ocs_init Example - see routine 'event_analysis.F' in $OCS781_EXA. * routine 'ocs_dump' - Dump OCS commons. * OCS table include files To generate include files for standard OCS tables use script 'ocs_incl_maker'. It creates .inc file of OCS and writes it as a file 'table_name.inc_Z'. If all is OK with it, you may rename it to 'table_name.inc' Arguments: $1 - table_name $2 - string of USER variable names ( short names like in ddl ); first field of table by OCS requirements is 'name', c*12 - it defines INTERNALLY $3 - string of variable types for each variable name (only c12, c8, c4, r4 and i4 can be used) $4 - maximum number of rows in the table (OPTIONAL parameter, 20 is preset value) $5 - string of linking tables names (OPTIONAL parameter) Short variable names from string will be transformed to long form like: volume_table_name, shape_table_name, x_table_name, k_table_name. Short linking names (l-name) will be transformed by following concatenation: 'l-name' -> 'lk//l-name//_table_name' ATTENTION: You MUST edit the '.inc' file to add table description and to add comments to each variable. Example: ocs_incl_maker rich_def 'volume shape x k ' \ 'c8 c4 r4 i4' 25 'glob_pos' To generate 'ocs_fill' routine by 'ocs_fill_maker' (to include filling of your and system tables) type command ocs_fill_maker or (better!) type ocs_init in directory, where your .inc includes and .ocs files are located. CALLING ORDER EXAMPLE OF FORTRAN USAGE - see APPENDIX 1 OCS INITIALIZATION At OCS initialization stage information about all input tables (allowed by class selection) is stored in OCS metatables. Some of them are marked as active tables in accord with class/version/run selection. Usually reload procedure changes active tables and refills them. OCS has an internally controled parameter described in 'ocs_cbk.inc': - ocs_error_level (i4)- ERROR level: 0 - no errors 1 - OCS warning 2 - fatal OCS error OCS has some user controled internal parameters described in 'ocs_cbk.inc': - ocs_prt_unit (i4) - fortran unit for table printing (default value = 6); - ocs_prt_line (i4) - length of printing lines used in 'ocs_prin_table' for line splitting during the table printing (default=130); - ocs_debug_level(i4) - debugging level: 0 - no debug (default), 1 - short debug, 2 - full debug; - ocs_class_main (c8) - class of the highest priority for table selection; - ocs_class_out (c80) - list of initially rejecting classes; - ocs_class_get (c80) - list of classes which should be accepted; - ocs_sets_out (c80) - list of table sets which should be ignored. Class treatment. Three mentioned string variables in 'ocs_cbk.inc' 'ocs_class_out', 'ocs_class_get', and 'ocs_class_main' should be defined by user just before the first 'call ocs_update'. - 'ocs_class_out' tells OCS what classes should be hardly rejected at initial stage. It means that user in this run will NEVER use these classes (default value is ' ' - NO selection). Example: ocs_class_out='aa test' ! c8 each - 'ocs_class_get' tells OCS tables of what classes should be initialized. It means that user in this run will use exactly these classes (default value is ' ' - NO selection, ALL tables in use). Example: ocs_class_get='mc anal' ! c8 each User is free to choose between these two options, or don't use both of them. It's clear that in the case of clash between '_out' and '_get' requests, '_out' will have priority over '_get'. It's clear too that you will have problem with class selection if you have more then 2 classes on input. To resolve this problem use 'ocs_class_main'. - 'ocs_class_main' gives OCS the class with highest priority at automatic table selection stage (important in the case of class clashes; default value is ' ' - NONE). Example: ocs_class_main='anal' ! c8 Class selection works as follows: - if 'ocs_class_out' is not empty, then at initial stage tables of listed classes will be hardly rejected; - from tables which were left after this rejection will be taken only those tables which are listed in 'ocs_class_get' if it's not empty (if 'ocs_class_get'=' ' then ALL classes will be taken - default); - at any time when class/version/run selection is doing in the case of more then one class for the table a classes clash will be resolved using 'ocs_class_main' which defines the class with highest priority. If you don't wish to load tables for some particulary detectors, you may ignore them listing all these subsets in a string variable 'ocs_sets_out': ocs_sets_out = 'rich_ adc_ phot_' ! SETS to deselect In this case all tables those names match one of substring will be ignored by OCS. After automatic table selection stage in 'ocs_update' user is free to load any available table with any class/version/run by 'call ocs_load_table(...)'. OCS TABLES INFO At any time (after first 'call ocs_update') user may get info about current status of any active table using 'ocs_tab_version': #include "ocs_tab_version.inc" ! for 'class,version,f_run,l_run,modes,n_out' ........ call ocs_tab_version(table,class,version,f_run,l_run,modes, n_out) in out out out out out out c12 c8 c8 i4 i4 c8(20) i4 In 'class' user will get class of currently active 'table', in 'version' - its version, in 'f_run' - first run for the table, in 'l_run' - last run for the table, 'modes' will have list of used modes for the table. n_out > 1 if 'mod's were used in addition to 'fill' for the table and it will be the number of found table parts. File name for 'binary' table can be taken by routine 'ocs_bin_table': call ocs_bin_table(table, bin_file, ierr) in out out c12 c* i4 where 'bin_file' for given 'table' has file name with full path. In error case ierr=1. TABLES REFILLING Table refilling can be done by user for any particulary table or by OCS itself in data driven mode if run number ('ocs_run') was changed. To refill particulary table user needs to call: call ocs_load_table(table, class, version, first_run, last_run, ierr) in in in in in out c12 c8 c8 i4 i4 i4 This routine will force OCS to load requested version of table (its 'fill' and 'mod' parts), if 'class' is allowed by previous requests, 'table' available with requested 'version', and 'first_run', and 'last_run' (ierr=1 if requested table not found). In data driven mode user should use second call to 'ocs_update': ocs_run = call ocs_update to reload those tables which are not valid for new RUN number. At first call 'ocs_update' creates internal metatables and loads all tables in accord with automatic class/version/run selection procedure. At any next calls 'ocs_update' will reload those tables which are not valid for current 'ocs_run' value. Actually in this case 'ocs_update' calls function 'ocs_ntab_reload' with key=1 (user may use it directly): n_tables=ocs_ntab_reload(key, tables, classes, versions, first_runs, + last_runs) out in out out out out i4 i4 c12(*) c8(*) c8(*) i4(*) * - max number of tables (= mftab in 'ocs_update') In the case of key=0 and for given run number 'ocs_run' (see 'ocs_cbk.inc') this function will produce list of tables (in 'tables' array) with those classes, versions and first/last-run numbers (in 'classes', 'versions', 'first_runs', and 'last_runs' arrays) which need to be refilled ('n_tables' - number of refilling tables; if 'n_tables = 0' - NO tables for refilling). After that user is free to change class/version for each table before its reloading by yourself with 'ocs_load_table'. In the case of key=1 'ocs_ntab_reload' internally calls 'ocs_load_table' for each table to load new version of a table (with the same class) using standard OCS version selection procedure. Also user may (re)load all tables of given class choising versions which are .le.'version' in OCS sense by call to 'ocs_load_version': call ocs_load_version(class, version, ierr) in in out c8 c8 i4 For each table those version will be taken which is mostly close to 'version' but not "older" of it. ierr=1 if no one table found for reload. OCS allowes user to have NO own OCS tables (own '*.ocs' files) at both code and script levels. KEYING OCS keys define an instance of the data for a table. The keyed block of a table chosen to be loaded into memory common blocks is determined by comparing all the keys for that table with the present value of the run number in a program and other, user set, criteria. By default the keyed block with the highest version for which the present run number is between the key's run number limits is selected. Highest version is determined in an alphabetical sense (in lower case representation);V2 is after V1 and ZEBRA is after both. If the user selects a specific version for a particular table then that version, if found, is selected. There should never be two keyed blocks with identical keys. If, by error, there are then the last one will be used. For OCS standard form tables MOD mode keyed blocks are permitted. These modify the contents of a table already loaded into memory. There is an additional rule for the selection of MOD mode keyed block. A FILL mode keyed block selected after (in the sense of order in the file) a MOD de-selects that MOD. In the following example #detv 1111 2222 fill example V01.00 15-Mar-1993 23:23 psc ! detector volumes #detv 2000 2222 mod example V01.00 15-Mar-1993 23:23 psc ! detector volumes #detv 1111 2222 fill example V02.00 21-DEC-1993 00:00 psc ! detector volumes the V02.00 keyed block would be selected for run 2100 and the MOD V01.00 would NOT be applied. Had the MOD appeared in the file after the FILL V02.00 block it would be applied. DB Manager beware! User OCS files are scanned after all standard files are scanned. Therefore, the user can always supersede that standard constants either by refilling a table and/or modifying it. OCS INTERNALS The above section allows the user to use OCS as a black box. This section explains how it does what it does. There are two related parts, the OCS internal routines and the OCS files. OCS FILES All standard OCS files are kept in a single directory tree with the exception of user file(s). Nothing in the system requires this. Common sense demands it. There are two classes of files, data and special. The data files were described above. There are two special files which are produced from the whole set of data files: 'master' and 'tables'. 'master' is the index to the standard files. It contains the key line from each keyed block along with the name of the file and line number where that key line can be found. 'tables' is a list of every unique table name found. Every computer system running E781 codes which reference OCS does not have to have the same set of OCS files present. The 'master' and 'tables' files are required to reflect those files which are present. Users keep their own sets of data and special files. These are scanned after the corresponding standard files. There are tool to generate the special files for use by both users and the database manager described in the DB Management section below. OCS INTERNAL ROUTINES When 'ocs_register' is first called the 'tables' file is read in. All table names are compared to this list. If an unknown table is requested by an owner a fatal error is generated. When 'ocs_scan_master' is first called the 'master' file is scanned and the keyed blocks selected for each known table are determined. This scan is redone only when the run number or user version selections (the "key") are changed. Tables kept in standard OCS files are filled immediately and all routines which own or use those tables have their 'ocs_new_const' flags set. User mode key blocks are opened,found and passed back to the calling routine to be read. After a key change if the first 'ocs_table' call is not from the owner of a table an error is reported. A table must be filled completely by its owner before a user can correctly reference it. The OCS system is smart enough to recognize that a particular table has not changed. Only tables which change are opened and read. Only routines which own or use changed tables have their 'ocs_new_const' flags set. * logical variable 'ocs_key_changed' in #include "ocs_cbk.inc" - user's variable to handle information about tables changings. * subroutine ocs_fill_table(table, l_fields, max_records, n_records, xtable, mode, line_current) Arguments: table - table name l_fields - number of fields in table max_records - maximum number of table records n_records - present number of table records (rows) xtable - table array mode - modify flag: TRUE for 'mod', FALSE for 'fill' line_current - current line number in opened file Fill a OCS database common block for standard table from an external file. The INCLUDE file for the common block is used as a DDL to describe the table's format. Example - see any 'ocs_fill.F' * logical function ocs_class_check(class,iflag) in in c8 i4 - Function to check CLASS of a table before loading, sets .TRUE. if the CLASS was requested at initialization stage: if(ocs_class_check(class,iflag)) <'class' was requested> Arguments: class - input string with CLASS name iflag - flag: 0 - check 'class' in 'ocs_class_out' 1 - check 'class' in 'ocs_class_get' * logical function 'ocs_llt' (entry 'ocs_lle') if(ocs_llt(str1, str2)) out in in logical c* c* - Two strings comparison (fortran function 'llt' analog adopted to our version comparison requirements): = .TRUE. if str2 is "older" then str1 = .FALSE. if not OCS TABLE VERSIONS and CLASSES Looking at version selection for each table, it is clear that versions must be taken like date-time values going strongly in chronological order (in the OCS string comparison sence). We need such kind of agreement to have automatic version selection - see example below and explanations after it. step f_run l_run ver comment 1) 0 0 v1 first version * 2) 0 0 v2 improved version 3) 5 10 v3 improved at ANAL stage version * 4) 5 7 v4 improved at ANAL stage version * 5) 8 10 v4 improved at ANAL stage version ________________________ 6) 0 4 v2 7) 5 7 v4 8) 8 10 v4 9) 11 0 v2 OCS in automatic table selection regime will load tables given as a set 2) - 5) by steps 6) - 9) for each run numbers region. DB MANAGEMENT The OCS files are to be maintained by the E781 database manager. A set of procedures written using the UNIX tools are available to help with this task. ocs_make_master - create 'master' and 'tables' special files by searching all files ending in '.ocs' using 'ls' or 'find'. NO arguments - local use in current directory with 'ls'. Flags: Arguments: -d - main working directory (if not current) -a - list of additional directories separated by ':' -f - use 'find' instead of 'ls' flag -e - env. variable substitution flag -h - print help Examples: ocs_make_master # looks for *.ocs files in running directory ocs_make_master -d $CON781_DIR # looks for *.ocs files in $CON781_DIR directory ocs_make_master -d $CON781_DIR -a $CON781_DIR/devel # looks for *.ocs files in $CON781_DIR and in $CON781_DIR/devel directories ocs_make_master -d $CON781_DIR -a $CON781_DIR/devel -e # same as above but replace part of path by env. variable '$CON781_DIR' ocs_make_master -d `pwd` -a `pwd`/devel -e # same as above but you run script in $CON781_DIR directory ocs_make_master -d `pwd` -f -e # you run script in $CON781_DIR directory and it looks into all underlying directories ocs_select - script with key block selection algorithm. Lists keys of selected key blocks for each table a given class, version, and run. It looks in both local 'tables/master' files and in remote files '$OCS781_MASTER/$OCS781_TABLES'. It has four flagged OPTIONAL arguments to select table, class, version, and run number. It has also four option flags: Flags: Arguments: -c - for CLASS name -r - for RUN number -t - for TABLE name -v - for VERSION (optionally includes +- signs) -l - local running flag -nl - nonlocal running flag -s - sort flag -p - print flag -h - print help If flag '-s' given, then output will be sorted by table names. If flag '-l' given, then script will look only into local 'tables/master' files. This option will be switched on automatically if environment variable 'OCS781_TABLES' not defined. If flag '-nl' given, then 'find' will be used instead of 'ls'. If flag '-p' given, then selected tables will be printed. Examples: ocs_select -s - prints all content of 'master' files what gives info about all available tables (sorted by table names) ocs_select -c mc -s - finds all tables with 'mc' class, output will be sorted by table names ocs_select -t pwc_pos - finds all available versions for the table 'pwc_pos' ocs_select -t pwc_pos -r 2222 - finds for selected table all available versions with run numbers which match following conditions: First_run Last_run <- run region 0 0 - selects always 'F-run' 0 - selects tables with 'F-run' <= 2222 'F-run' 'L-run' - select tables with 'F-run' <= 2222 .AND. 'L-run' >= 2222 ocs_select -v v01.01 - finds all tables with versions='v01.01' ocs_select -t pwc_pos -v v01.01 - finds version 'v01.01' of selected table if it exists You may select REGION of versions using +/- signes: ocs_select -t pwc_pos -v +v01.01 - finds all versions >= 'v01.01' for selected table ocs_select -t pwc_pos -v -v01.01 - finds all versions <= 'v01.01' for selected table ocs_assempble_table - script to assemble whole OCS table from its 'fill' & 'mod' parts. It writes assembled table to the standard output. Usage: ocs_assempble_table
- list of all files separated by ':' - directory for include file
- table name - table class - table version - first run for the table Example: ocs_assempble_table $CON781_DIR/pwc.ocs:$CON781_DIR/devel/pwc.ocs \ $OFF781_INC pwc_sz anal v00.01 0 DB PROTECTION Database protection in OCS is guaranteed by READONLY mode for all DB files and limited access to main DB directory. Some additional tools should be developed to check out the DB under running. KNOWN PROBLEMS MOD precedence. Should MOD precedence be determined by "only equal version" rather than file order? AUTHORS OCS was developed by the E781 database working group - Peter Cooper (Fermilab), Alexander Kushnirenko (Carnegie Mellon), Antonio Morelos (San Luis Potosi), Mike Procario (Carnegie Mellon) and Slava Rud (Moscow State University). VERSIONS V0 1-Sep-1994 Peter S. Cooper V1 1-Sep-1995 Slava I. Rud v1_2 16-Nov-1995 Slava I. Rud v1_3 Feb-1996 Slava I. Rud v1_4 15-May-1996 A. Kushnirenko v2_0 06-Jun-1996 Slava I. Rud v2_1 06-Aug-1996 Slava I. Rud v2_2 16-Oct-1996 Slava I. Rud v2_3 05-Apr-1997 Slava I. Rud v2_4 31-Jul-1997 Slava I. Rud ________________________________________________________________________________ APPENDIX 1 EXAMPLE OF FORTRAN USAGE Assume for this example the example tables given above. subroutine test_ocs(func, error_code) c in out c c Example of OCS usage c c 22-Jul-1996 rud last correction c Implicit NONE * *-------OCS includes: * #include "ftabbk.inc" ! #include "ocs_cbk.inc" ! for use with OCS routines #include "ocsbk.inc" ! * *-------User includes: * #include "scaler_cbk.inc" ! a constant table I own #include "ssd_pos_cbk.inc" ! a constant table I own #include "mag_pos_cbk.inc" ! a constant table I own #include "spec_pos_cbk.inc" ! a constant table I use logical * mode ! table mode character * file*80 ,! binary file name * file_name*80 ,! scratch file name * func*8 ,! request function * line*1024 ! space for key integer*4 * i,j ,! dummy do loop indices * error_code ,! global event error code * l_cur ,! current line no. in open file * ifopen ,! file open key * exp_env ! function of MP real*4 * A(10,10) ! binary table array IF(func .eq. 'first') THEN ! initialization section if( ocs_register(ocs_id , ! the id OCS will give me * 'test_ocs' , ! my name * 'scaler user ssd_pos mag_pos',! the tables I own * 'spec_pos ') ) then ! the tables I use but don't own *Stop: print *, 'TEST_OCS: bad OCS_REGISTER result for routine '// * 'test_ocs. Stop' STOP endif if(ocs_debug_level.gt.0) then ! short debug print '(a18,i2)','test_ocs: ocs_id=',ocs_id print *,'test_ocs: ocs_new_const(ocs_id)=',ocs_new_const(ocs_id) end if call ocs_prin_table('spec_pos',nspec_pos,spec_pos,'test_ocs') ELSE IF(func .eq. 'init1') THEN if(ocs_new_const(ocs_id)) then ! constant update section ! OCS will set this flag .true. ! whenever a table I own needs to ! be updated or a table I use ! has been updated do while (ocs_table(ocs_id, mode, l_cur, line)) ! the OCS system will update all of ! my standard form tables and return ! to me for any user format tables ! which require updating if(line(2:8).eq.'scaler') then ! handle my 'scaler' table read(ocs_unit,'(6a8)') (name_scaler(j),j=1,6) ! read in scaler names l_cur = l_cur + 1 ! count each read in line i = 0 do while(i.gt.-1) read (ocs_unit,'(i2,(a))') i,line l_cur = l_cur + 1 ! count each read in line if(i.ge.0) then read(line,*)(value_scaler(j,i),j=1,5) else read(line,*)(summed_scaler(j),j=1,5) end if end do read (ocs_unit,*) ! skip blank line l_cur = l_cur + 1 ! count each read in line else if(line(2:5).eq.'user')then ! handle my binary ! 'user' table read(ocs_unit,'(a)') file ! read file's name * Extract file name from env. variable by function 'exp_env': ifopen = exp_env(file,file_name) ! file --> file_name if(ifopen.ne.0) then print *, 'TEST_OCS: cannot get correct path to '// * file//' file from exp_env. Return.' RETURN end if open(unit=2, file=file_name, ! open file * status='OLD',form='unformatted') read(2) ! readin your data read(2) A close(unit=2) ! close file end if end do ! enddo 'while' ocs_new_const(ocs_id) = .false. ! constant update done end if ! end constant update section ELSE IF(func .eq. 'init2') THEN ! at this point all tables I own or ! use are up to date. do all work ! require to my tables. if(ocs_new_const(ocs_id)) then ! constant update section ! OCS will set this flag .true. ! whenever a table I own needs to ! be updated or a table I use ! has been updated * Old linking: call ! link ssd_pos -> spec_pos: * ocs_link_table( name_spec_pos, lspec_pos, nspec_pos, * name_ssd_pos, lssd_pos, nssd_pos, * lkspec_ssd_pos, 1, 2) call ocs_prin_all('ssd_pos','test2_ocs') ! print table 'ssd_pos' * New linking: call ! link 'mag_pos' -> 'spec_pos' & ocs_link_tables('spec_pos', name_spec_pos, & 'mag_pos', name_mag_pos, & lkspec_mag_pos, 1, 2) call ocs_prin_all('mag_pos','test2_ocs') ! print table 'mag_pos' ocs_new_const(ocs_id) = .false. ! constant update done end if ! end constant update section END IF ! function RETURN end _______________________________________X________________________________________