MANION@CURIE.RM.FCCC.EDU (Frank Manion) (08/05/88)
Mike Temkin writes: >Does anyone out there know how to make a file multi-accessible (readwise) >in VMS? There must be a way since I would think that the help file is >that way. Any help is appreciated. Yes, there is a way: Most high level languages allow an option on the OPEN statements of the language of the form READONLY and/or SHARING, SHARED, etc. In Fortran: (1) OPEN(1,file='file.dat',status='old',readonly) will open a file for reading allowing sharing with other readers; (2) OPEN(1,file='file.dat',status='old',readonly,shared) will open a file for reading allowing sharing with other readers and potentially other shared writers. (3) OPEN(1,file='file.dat',status='old',shared) will open a file for reading and writing allowing sharing with other readers/writers which have fab$m_shrput set; (4) OPEN(1,file='file.dat',status='old') will open a file and disallow any sharing... A later writer replies... > Any program that opens a file to write to it will almost certainly open >it for exclusive access. Programs written in high level languages >sometimes default to exclusive access. From VAX Fortran, for example, the >OPEN statement must include the keyword SHARED, else the file is opened for >exclusive access, (FAB$B_SHR=FAB$V_NIL). Sorry my friend, but you are wrong. VAX Fortran simply leaves the FAB$B_SHR field initialized to zero in this case, which forces the RMS default to be set. The defaults, taken from page 5-26 of the V4 RMS ref. manual are as follows: "* If the FAB$B_FAC field is set or defaulted to FAB$V_GET, the SHR filed defaults to SHRGET". "* If the FAB$B_FAC field is set or defaulted to either PUT, DEL, UPD, or TRN, the FAB$B_SHR field defaults to FAB$V_NIL." Thus if the user opens a file without the SHARED keyword, but with the READONLY keyword, GET sharing will be allowed. Files opened for create or write access will default to NIL sharing, as stated above. But don't take my word for it; for that matter, don't take DEC's either. At the end of this message is a Fortran program which peeks into the FAB fields an prints out what they are for each type of open. It also can be used to see how different types of OPENs interact. Now for a very important point: on normal sequential files (i.e. most text files) RMS only takes out record locks on files openned with SHRPUT, SHRDEL or SHRUPD sharing. This means that record locking overhead is ***AVOIDED*** on opens which only declare SHRGET. OPEN statement (1) above, only opens the file for SHRGET. OPEN statements (2) and (3) declare SHRPUT, SHRDEL, and SHRUPD, as well as SHRGET. Thus, openning a file from fortran with READONLY,SHARED will result in substantially slower access then a READONLY open. On a 11/785 the READONLY,SHARED form is about 500 percent slower than a READONLY open. If all you want to do is allow multiple readers to access a file, the READONLY open (i.e. SHRGET) is the way to go. Opening a file unnecessarily with READONLY,SHARED has another problem: It will 1) allow a shared writter access to the file, which 2) may cause the original program to encounter RECORD-LOCK ERRORS! This may break programs written before V4.3 when full sharing of sequential files was implemented. Prior to V4.3, READONLY,SHARED had to be specified to allow file sharing of sequential files. The moral of the above story is (on V4.3 and above) to only declare that type of sharing which you need. Failing to heed this warning may result in 1) slower execution, and additional burden on programming to correctly handle possible record locking. c*********************************************************************** c program TESTLOCK.FOR to test accessability of files with different c fortran sharing options. c Note that this program appears to bear out the RMS reference manual c with record to unspecified (i.e. 0 or defaulted) values for the fab$b_fac c and fab$b_shr fields of the FAB. c At prompt, type: c type RS to open readonly, shared file c type R to open readonly file c type S to open file shared c type anything else to open file without readonly and shared keywords. c the program attempts to open TESTLOCK.FOR multiple times with the c different sharing options requested. implicit none integer*4 AccessTest external AccessTest integer*4 status integer*4 a(1000) integer*4 i,n, lun character*3 opt logical*4 is_there lun = 7 do while(.true.) lun = lun + 1 write(5,'(a)')'$Options: ' read(5,'(a)',end=500)opt call str$upcase(opt,opt) if( is_there(opt,'RS') ) then write(6,'(a)')' Readonly, shared' open(lun,file='testlock.for',status='old',shared, 1 readonly,useropen=AccessTest) read(lun,900)(a(i),i=1,n) else if( is_there(opt,'S') ) then write(6,'(a)')' shared' open(lun,file='testlock.for',status='old',shared, 1 useropen=AccessTest) read(lun,900)(a(i),i=1,n) else if(is_there(opt,'R')) then write(6,'(a)')' Readonly' open(lun,file='testlock.for',status='old',readonly, 1 useropen=AccessTest) read(lun,900)(a(i),i=1,n) else write(6,'(a)')' not readonly and not shared' open(lun,file='testlock.for',status='old', 1 useropen=AccessTest) read(lun,900)(a(i),i=1,n) end if end do 500 stop 900 format(q,a) end logical*4 function is_there(a,b) character*(*) a,b is_there = .true. i = 1 do while(is_there.and.i.le.len(b)) is_there = is_there .and. (index(a,b(i:i)).ne.0) i = i + 1 end do return end integer*4 function AccessTest( fab, rab, lun ) implicit none c fetch needed definitions of system data structures. include '($fabdef)' ! FAB definitions include '($rabdef)' ! RAB definitions c formal parameter declarations record /fabdef/ fab ! Declare fab as a FAB record /rabdef/ rab ! Declare rab as a RAB integer*4 lun c declare local constants and data types integer*4 sys$open, sys$connect byte shr, fac c open file and connect the stream. fac = fab.fab$b_fac shr = fab.fab$b_shr AccessTest = sys$open(fab) if(AccessTest) then AccessTest = sys$connect(rab) end if c print the options. The defaults if fac is 0 are found on page c 5-10 under subheading fab$v_get of the "VAX Record Management c Services reference manual" (version 4.0 edition) c " Get is the default access if fab$b_fac field is not specified c or the del,upd,or trn sharing options are set in fab$b_shr." c Note that fab$b_fac = 0 does not imply NIL sharing! c Note: this routine assumes the file is being OPENED, not CREATED. c the defaults are slightly different in this case. write(6,'(a,z2.2,a,$)')' Accessability(',fac,'):' if ( ( fac .and. fab$m_put ) .ne. 0 ) write(6,'(a,$)')'+ put' if ( ( fac .and. fab$m_get ) .ne. 0 ) write(6,'(a,$)')'+ get' if ( ( fac .and. fab$m_del ) .ne. 0 ) write(6,'(a,$)')'+ del' if ( ( fac .and. fab$m_upd ) .ne. 0 ) write(6,'(a,$)')'+ upd' if ( ( fac .and. fab$m_trn ) .ne. 0 ) write(6,'(a,$)')'+ trn' if ( ( fac .and. fab$m_bio ) .ne. 0 ) write(6,'(a,$)')'+ bio' if ( ( fac .and. fab$m_bro ) .ne. 0 ) write(6,'(a,$)')'+ bro' if ( ( fac .and. fab$m_exe ) .ne. 0 ) write(6,'(a,$)')'+ exe' if ( fac .eq. 0 .or. (shr .and. (fab$m_shrdel.or. 1 fab$m_shrupd.or.fab$m_trn) .ne. 0) ) then if ( ( fac .and. fab$m_get ) .eq. 0) then write(6,'(a,$)')'+ defaults to get' end if end if c the defaults if shr is 0 are fond on page 5-26 of the c above referenced manual at the end of the section on Fab$b_shr c "if the fab$b_fac field is set or defaulted to GET, the SHR field c defaults to SHRGET. If the fab$b_fac field is set or defaulted c to either PUT, DEL, UPD, or TRN, the SHR field defaults to c NIL." write(6,'(a,z2.2,a,$)')' Sharing(',shr,'):' if ( ( shr .and. fab$m_nil ) .ne. 0 ) write(6,'(a,$)')'+ nil' if ( ( shr .and. fab$m_shrput ) .ne. 0 ) write(6,'(a,$)')'+ put' if ( ( shr .and. fab$m_shrget ) .ne. 0 ) write(6,'(a,$)')'+ get' if ( ( shr .and. fab$m_shrdel ) .ne. 0 ) write(6,'(a,$)')'+ del' if ( ( shr .and. fab$m_shrupd ) .ne. 0 ) write(6,'(a,$)')'+ upd' if ( ( shr .and. fab$m_upi ) .ne. 0 ) write(6,'(a,$)')'+ upi' if ( ( shr .and. fab$m_mse ) .ne. 0 ) write(6,'(a,$)')'+ mse' if ( shr .eq. 0 ) then if ( (fac.and.(fab$m_put.or.fab$m_del.or.fab$m_upd 1 .or.fab$m_trn)) .ne. 0) then write(6,'(a,$)')'+ defaults to nil' c nil sharing takes precedence over all other forms, thus c it would be confusing to say defaults to get and defaults to nil else if ( fac .eq. 0 .or. (fac.and.fab$m_get).ne.0 ) then write(6,'(a,$)')'+ defaults to get' end if end if return end