[comp.os.vms] Specific RMS questions

LEICHTER-JERRY@YALE.ARPA (07/17/87)

    We are in the process of dovetailing our filesystem interfaces (indexed
    files, sequential files and relative files) to RMS (from UNIX)....

    Our interface has an open mode called "shared output", the definition of
    which states that if the file is already opened by another user then the
    open fails. If the open succeeds then the file is truncated (other users
    can open the file for shared input if they so choose).
    
    ...[W]e have them as follows for shared input and shared output.
    
    Shared Output:
    	fab$b_fac = FAB$M_PUT	 - I want to put records
    	fab$b_shr = FAB$M_SHRGET - I will allow shared gets
    
    Shared Input
    	fab$b_fac = FAB$M_GET	 - I want to get records
    	fab$b_shr = FAB$M_SHRPUT - Puts are allowed
    	            FAB$M_SHRGET - Others can also read records
    		    FAB$M_SHRDEL - Others can delete records
    		    FAB$M_SHRUPDATE - Others can update records
    
    Thus the following happens:
    	1) User 1 opens file for shared input.
    	2) User 2 opens the file for shared output, the open succeeds. 
    	   The file gets truncated. User 1 still sees the "old" file.
    
The fact that User 1 still sees the "old" file seems to imply that you've
managed to create a new version of the file, which User 2 sees; User 1 keeps
running merrily along with the old version.  You can avoid this by providing
an explicit version number.

    We want the open in 2) to fail, but can see no way to do this with the RMS
    file sharing flags. The question is then how can we tell if a file is open
    in RMS (or in VMS in general)? 
    I noticed that the SHOW DEVICE/FILES lists all the open files on a device.

Well, you can tell if a file is open "right now" by trying to open it with
fab$b_shr = FAB$V_NIL.  This is certain to fail if anyone else has the file
open, whatever sharing options they've asked for.  However, there is no way
to change the "allowed sharing" without closing and reopening the file, which
leaves a timing window - as does any other method of checking whether the file
is open.  If you can live with this, or arrange for your code to work around
it, this is the simplest approach.  (If I understand what you are trying to
accomplish - one writer, any number of readers, if the writer finds NO readers
it creates a new file - then the sequence for the writer:  Open with NIL
sharing; if you succeed, truncate the file and close it then open for write
allowing read - will work, since at worst it means a truncated file may get
truncated again.)
    
    Our DEC person suggested we use the lock manager rather than walk through 
    the VMS internal data structures, since we do not want the applications
    programs to have special privileges to run. Using the lock manager would 
    also imply that our feature of shared output would only work if
    all accesses to that file is through our interface.

The particular set of access constraints you want is different from the ones
RMS provides.  You can build any access constraints you want with the lock
manager, but there's no way around the fact that, if you want what RMS doesn't
provide, programs that use RMS and don't use your code can't possibly hew to
your constraints.
    
    We also have a function that locks a file provided you already have
    the file open in shared mode. The lock will fail if:
    		1) Any records are locked by another user
    		2) The file is already locked by another user
    		3) The file is open in exclusive mode
    
    Any ideas how this might fit into RMS??

The lock manager is probably the only way to do this, again short of closing
and re-opening the file.  You might be able to hack something up by choosing
a distinguished record in the file - like the first - and locking it to indi-
cate the file is locked.  BTW, I don't understand what condition 3) means,
given that you started off by assuming the file was open in shared mode.

							-- Jerry
-------

BOLTHOUSE%MCOPN1@eg.ti.COM (07/30/87)

John Weald wrote:
>>>Thus the following happens:
>>>	1) User 1 opens file for shared input.
>>>	2) User 2 opens the file for shared output, the open succeeds. 
>>>	   The file gets truncated. User 1 still sees the "old" file.

David L. Bolthouse (me) wrote:
>> I believe the problem is due to the fact that RMS is opening a new file.
>> If you could coerce RMS into attempting to open the same file, it should
>> behave as you want.  So, use the $PARSE service to determine the version
>> number of the most recent file and open *it* for shared output.  

Jerry wrote:
>> The fact that User 1 still sees the "old" file seems to imply that you've
>> managed to create a new version of the file, which User 2 sees; User 1 keeps
>> running merrily along with the old version.  You can avoid this by providing
>> an explicit version number.

John replies:
>I do ensure that the same file is opened. The supercede flag is set and
>sys$parse followed by a sys$search is called to get the correct version
>number. The problem still occurs. Perhaps a better method to test this is
>to open a file GET (allow the world to GET, PUT, UPDATE etc) then read
>records from the file. In the mean time remove the file via DCL command delete.
>The program is happy as a pig in mud to keep reading records. This
>behavior does not surprise me.
>Cheers!

In order to get to the bottom of this, we created a file, STUFF.DAT;1,
containing random text.  It's FID (found using DIR/FULL) was 13004,70,0.
The following VAX MACRO program was then run:

;Really short macro to create STUFF.DAT file with the SUP bit in the
;	FOP on...  This will delete the previous file and
;	create a new one in it's place...
	.entry	main,0

	$CREATE	fab=fab
	blbc	r0,999$
	$CLOSE	fab=fab
999$:	ret

fab:	$FAB	fnm=<STUFF.DAT;1>,fop=<SUP>

	.end	main

We opened STUFF.DAT;1 for read via DCL, ran the program, did a DIR/FULL,
and another DCL read.                          

$ open/read/share=write stuff_file stuff.dat;1	! Done by partner in crime...
$ run stuff.exe
$ dir/full stuff.dat;1                                                  

Directory U1:[DCATHEY]

STUFF.DAT;1                   File ID:  (12991,95,0)       
Size:            0/0          Owner:    [DCATHEY]
Created:  30-JUL-1987 09:42   Revised:  30-JUL-1987 09:42 (1)
Expires:   <None specified>   Backup:    <No backup done>
File organization:  Sequential
File attributes:    Allocation: 0, Extend: 0, Global buffer count: 0, Version limit: 10
Record format:      Variable length
Record attributes:  None
Journaling enabled: None
File protection:    System:RWE, Owner:RWED, Group:RE, World:RE
Access Cntrl List:  None

Total of 1 file, 0/0 blocks.

Note the file has been 'truncated' to 0 blocks, and that the File ID (FID)
is *different*.  On the other hand, the 'old' stuff.dat is still around!

$ show dev/files $1$dua12:
(uninteresting files omitted...)

But,It'sMyJob!  21601E58  

!!!!!!! NOTE NO FILE NAME !!!!!!!

The file that had been previously opened, is still open, but has been
removed from the directory.  It is marked for deletion by the XQP (which
RMS calls via $QIO), but it can't be deleted until all open channels to it 
are  closed.  Next, we opened the 'new' file...and then closed the 'old' file, 
making it finally, truly disappear.

$ open/read/share=write new_file stuff.dat;1
$ show dev/files $1$dua12:

But,It'sMyJob!  21601E58  
But,It'sMyJob!  21601E58  [DCATHEY]STUFF.DAT;1

! Now we have a file name on 'new' file...still have 'old' one around

$ close stuff_file
$ show dev/files $1$dua12:

But,It'sMyJob!  21601E58  [DCATHEY]STUFF.DAT;1

! And now it's gone.

The moral of this story:  File names, types, and version numbers don't
entirely describe a file; indeed, they are there only for the convenience
of the programmer/user.  File IDs, on the other hand, are guaranteed unique
by VMS (and therefore RMS).  If you *really* want to truncate the file (as
opposed to doing 'random access-style' updates), use the $TRUNCATE RMS
service.  Hope this helps!

David L. Bolthouse
David L. Cathey
Texas Instruments Defense Electronics Information Systems VAX System Support
McKinney, TX

AT&T:         214.952.2059 (DLB), 214.952.3503 (DLC)
Internet:     bolthouse%mcopn1@eg.ti.com,
              dcathey%mcopn1@eg.ti.com