Creating a new server on VXCRNA

Although it is possible to access remote database files from VAX/VMS systems using NFS, there are cases, such as on an online VAXcluster, when it is desirable to have a database server on the VAX itself.

As above, an account is first created using USERREG. This account is then configured using the following command file, included in the standard distribution:

                             CDNEW.COM
                                  

$!DECK ID>, CDNEW.COM
$ !
$ ! Setup the directory and file structure for a new
$ ! server
$ !
$   procedure = f$parse(f$environment("PROCEDURE"),,,"NAME")
$   say       = "write sys$output"
$   if p1 .eqs. ""
$      then
$         write sys$output "''procedure': usage ''procedure' group"
$         exit
$   endif
$ !
$ ! Does the directory already exist?
$ !
$   home = f$search("DISK$MF:[000000]''p1'.dir")
$   if home .eqs. ""
$      then
$         say "''procedure': home directory for ''p1' does not exist."
$         say "''procedure': please create an account using USERREG"
$         exit
$   endif
$ !
$ ! Create subdirectories
$ !
$   create/directory DISK$MF:['p1'.BAD]
$   create/directory DISK$MF:['p1'.LOG]
$   create/directory DISK$MF:['p1'.QUEUE]
$   set file/protection=w:rwe DISK$MF:['p1']QUEUE.DIR
$   create/directory DISK$MF:['p1'.TODO]
$   create/directory DISK$MF:['p1'.SAVE]
$   directory DISK$MF:['p1'] /security
$ !
$ ! Create names file
$ !
$   open/write out DISK$MF:['p1']HEPDB.NAMES
$   write out ":nick.config"
$   write out ":list.aa"
$   write out ":bad.DISK$MF:[''p1'.BAD]"
$   write out ":log.DISK$MF:[''p1'.LOG]"
$   write out ":queue.DISK$MF:[''p1'.QUEUE]"
$   write out ":todo.DISK$MF:[''p1'.TODO]"
$   write out ":save.DISK$MF:[''p1'.SAVE]"
$   write out ":wakeup.120"
$   write out ":loglevel.3"
$   close out
$   type DISK$MF:['p1']HEPDB.NAMES

Should the disk in question have disk quotas enabled, one should ensure that the queue directory is owned by an identifier and has an ACL as in the following example:

                Queue directory on VAX/VMS systems
                                  

(IDENTIFIER=CDCHORUS,ACCESS=READ+WRITE+EXECUTE+DELETE+CONTROL)
(IDENTIFIER=ID$_CHORUS,ACCESS=READ+WRITE+EXECUTE)
(IDENTIFIER=ID$_CHORUS,OPTIONS=DEFAULT,ACCESS=READ+WRITE+EXECUTE+DELETE+CONTROL)
(IDENTIFIER=CDF_EXPERIMENT,OPTIONS=DEFAULT,ACCESS=READ+WRITE+EXECUTE)

The identifier must be granted to all users who should be permitted to update the database with the RESOURCE attribute.

As for CERNVM, an extra account exists which is used to exchange updates between VXCRNA and hepdb.

The files created on hepdb must have the correct ownership (in this case UID 102 and GID 3) which must be mapped to the UIC under which the command file is executed on the VAX.

This is performed as follows:

           Mapping a Unix UID/GID pair to a VMS username
                                  

$ !    MULTINET CONFIGURE /NFS
$ !    NFS-CONFIG>add cdhepdb 102 3
$ !    NFS-CONFIG>ctrl-z

This is done using the following command file:

              Moving updates between VXCRNA and hepdb
                                  

$!DECK ID>, CDSEND.COM
$ !
$ ! Command file to move updates between 'slave' and 'master'
$ !
$ ! Invoked by CDSERV.COM from the account CDHEPDB on VXCRNA
$ !
$ ! Assumes correct UID & GID mapping for directories on 'master'
$ !    MULTINET CONFIGURE /NFS
$ !    NFS-CONFIG>add cdhepdb 102 3
$ !    NFS-CONFIG>ctrl-z
$ !
$ set noon
$ !
$ ! List of servers
$ !
$   cdservers = "CDCPLEAR,CDCHORUS,CDNOMAD"
$ !
$ ! Master & slave definitions
$ !
$   slave     = "VXCRNA"
$   master    = "HEPDB"
$ !
$ main_loop:
$   nserver   = 0
$ !
$ ! Loop over all servers
$ !
$ loop_servers:
$   server    = f$element(nserver,",",cdservers)
$   nserver   = nserver + 1
$   if server .eqs. "," then goto sleep
$ !
$ ! Look for files waiting to be sent to 'master'
$ !
$ to_hepdb:
$    journal_file = f$search("DISK$MF:[''server'.TO''master']*.*")
$ !
$    if journal_file .eqs. "" then goto from_hepdb
$ !
$ ! Skip 'active' files
$ !
$    if f$extract(0,2,journal_file) .eqs. "ZZ" then goto to_hepdb
$ !
$ ! Build remote file name
$ !
$   istart = f$locate("]",journal_file) + 1
$   remote_file = "''master':[''server'.TODO]ZZ" + -
       f$extract(istart+2,f$length(journal_file),journal_file)
$ !
$ ! Copy the file over
$ !
$   copy 'journal_file' 'remote_file' /log /noconfirm
$ !
$ ! Rename remote file and delete local file if it was ok
$ !
$   if $severity .eq. 1
$      then
$         remote_update = "''master':[''server'.TODO]" + -
             f$extract(istart,f$length(journal_file),journal_file)
$         rename 'remote_file' 'remote_update' /nolog /noconfirm
$         if $severity .eq. 1 then delete /nolog /noconfirm 'journal_file'
$   endif
$ !
$   goto to_hepdb
$ !
$ ! Look for files to be pulled over from 'master'
$ !
$ from_hepdb:
$    journal_file = f$search("HEPDB:[''server'.TO''slave']*.*")
$ !
$    if journal_file .eqs. "" then goto loop_servers
$ !
$ ! Skip 'active' files
$ !
$    if f$extract(0,2,journal_file) .eqs. "ZZ" then goto from_hepdb
$ !
$ ! Build local file name
$ !
$   istart = f$locate("]",journal_file) + 1
$   local_file = "DISK$MF:[''server'.TODO]ZZ" + -
       f$extract(istart+2,f$length(journal_file),journal_file)
$ !
$ ! Copy the file over
$ !
$   copy 'journal_file' 'local_file' /log /noconfirm
$ !
$ ! Rename local file and delete remote file if it was ok
$ !
$   if $severity .eq. 1
$      then
$         local_update = "DISK$MF:[''server'.TODO]" + -
             f$extract(istart,f$length(journal_file),journal_file)
$         rename 'local_file' 'local_update' /log /noconfirm
$         if $severity .eq. 1 then delete /log /noconfirm 'journal_file'
$   endif
$ !
$   goto from_hepdb
$ !
$ sleep:
$   wait 00:30:00
$   goto main_loop

The servers are controlled by the following job, which runs in the SYS$FATMEN queue:

               Command file to control HEPDB servers
                                  

$!DECK ID>, CDMAST.COM
$SET NOON
$ !
$ !   Master HEPDB command file
$ !
$     save_mess = f$environment("MESSAGE")
$     set message/nofacility/noseverity/noid/notext
$     write sys$output "CDMAST starting at ''f$time()'"
$ !
$ !   define list of servers
$ !
$     servers  = "CDHEPDB,CDCHORUS,CDCPLEAR" ! Separate by commas
$     wakeup :== 00:30:00                    ! Every 30 minutes
$ !
$ !   define symbols - this is VXCRNA specific
$ !
$     n = 0
$ loop:
$     server    = f$element(n,",",servers)
$     if server .eqs. "," then goto again
$     'server' == "DISK$MF:[''server']"
$     n         = n + 1
$     goto loop
$ again:
$ !
$ !   Run the command files that expect a complete list as argument
$ !
$     write sys$output ">>> CDPURGE..."
$     @CERN_ROOT:[EXE]CDPURGE 'servers'  ! Purge old journal files
$ !
$     write sys$output ">>> CDCHECK..."
$     @CERN_ROOT:[EXE]CDCHECK 'servers'  ! Check that servers are started
$ !
$     write sys$output ">>> Time is ''f$time()'. Waiting ''wakeup'..."
$     wait 'wakeup'
$     write sys$output ">>> Wakeup at ''f$time()'."
$     goto again
$     set message 'save_mess'
$     exit

The job CDPURGE purges old journal and log files and is as follows:

              Job to purge old journal and log files
                                  

$!DECK ID>, CDPURGE.COM
$SET NOON
$ !
$ ! Purge journalled HEPDB updates that are over a day old
$ !
$ if p1 .eqs. "" then exit
$ hepdb =  p1
$ count  = 0
$ save_mess = f$environment("MESSAGE")
$ set message/nofacility/noseverity/noid/notext
$loop:
$ server = f$element(count,",",hepdb)
$ if server .eqs. "," then goto end
$ count  = count + 1
$ write sys$output "Processing ''server'..."
$ ON WARNING THEN GOTO UNDEFINED
$ cddir = &server
$ purge 'cddir' ! Purge old log files
$ cdfil = f$extract(0,f$length(cddir)-1,cddir) + ".SAVE]*.*;*"
$ ON WARNING THEN CONTINUE
$ delete/before=-0-23:59 'cdfil'
$ goto loop
$ undefined:
$ write sys$output "Warning: symbol ''server' is not defined"
$ goto loop
$ end:
$ set message 'save_mess'
$ exit

The job to check and restart the servers is as follows:

                       CDCHECK command file
                                  

$!DECK ID>, CDCHECK.COM
$SET NOON
$ !
$ ! Check that HEPDB servers are started
$ !
$ if p1 .eqs. "" then exit
$ servers = p1
$ count   = 0
$ save_mess = f$environment("MESSAGE")
$ set message/nofacility/noseverity/noid/notext
$ !
$ ! Check that the queue is started
$ !
$ if f$getqui("DISPLAY_QUEUE","QUEUE_STOPPED","SYS$FATMEN") .eqs. "FALSE" then -
     start/queue sys$fatmen
$loop:
$ server = f$element(count,",",servers)
$ if server .eqs. "," then goto end
$ count  = count + 1
$ write sys$output "Processing ''server'..."
$ show user/nooutput 'server'
$ if $severity .ne. 1
$    then
$ !
$ !  Check that server has not been stopped
$ !
$    ON WARNING THEN GOTO UNDEFINED
$    cddir = &server
$    ON WARNING THEN CONTINUE
$    cddir = f$extract(0,f$length(cddir)-1,cddir) + ".TODO]SIGNAL.STOP"
$    if f$search(cddir) .nes. ""
$       then write sys$output "Signal.Stop file found - will not restart"
$       goto loop
$    endif
$    write sys$output "Restarting server ..."
$    cdserv = &server + "CDSERV.COM"
$    submit/queue=sys$fatmen/user='server' /id 'cdserv'
$    endif
$ goto loop
$ undefined:$ write sys$output "Warning: symbol ''server' is not defined"
$ goto loop
$ end:
$ exit