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