HP OpenVMS Systemsask the wizard |
The Question is:
Our question concerns on a shared read access to fixed record length
sequencial files. We use ALPHA servers 1000A and 800, operation
systems OpenVMS V7.1 and OpenVMS V7.1-1H2
respectively, programming language FORTRAN-77.
While trying to get a shared read access to one given record in one given
file from several (two or more) identical programs running in different
processes the following obstacle was revealed:
- the first program to access a record reads it successfully;
- the other programs trying to get access to this very record are denied with
an error code 52 (decimal), i.e. "RECORD LOCKED BY ANOTHER USER", even though
the first program completed operations with this record (the other records are
free for access).
We partially managed to get rid of this fault adding after READ operator
UNLOCK operator. It enabled shared access if attempts to read a record are not
simultaneous. However attempts of multiple simultaneous access, that occures
ocassionally, lead to
collisions with the same error code, notwithstanding UNLOCK. Thus we were
forced to analyze a status
word after READ operation and, in cases of errors, try reading repeatedly.
Sometimes it leads to quite a large number of attempts until clunch prosesses
disperse in time.
An example of a program to demonstrate shared access collisions looks like
this (two or more instances of this program run in separate processes
simultaneously until all except one fall out because of the said error):
program check_unlock
byte buffer(1100)
C Record size is not principal and is chosen of 1100 just for example.
C File 'FILESHAR.DAT' with record length of 1100 bytes
C with arbitrary nutrition for test should be prepared beforehand:
open(unit=10, file='FILESHAR.DAT', access='direct', shared,
* organization='sequential', status='old', disp='keep',
* form='unformatted', recordtype='fixed', recl=275)
i=1
C Infinite cycle for reading, say, of the 7-th record:
do while(.true.)
read(unit=10, rec=7, iostat=istatus) buffer
unlock(unit=10)
i=i+1 !Count of attempts
C Shutdown the cycle after collision is detected:
if(istatus.ne.0) then
type *,' Read error ', istatus,' Attempt No ', i
stop
end if
end do
end
We would greately like to know whether there is any remedy to avoid such
collisions.
Thank you for assistance, Valentin Pisartchuk.
The Answer is :
Your application is apparently encountering record-level contention,
and you will need to understand the nature of this contention. This
contention can involve specific heavily accessed records within a file,
or this can involve deadlocks within the application(s), or this can
involve various other conflicting file access patterns.
In this particular case, you will need to disable all record locks
and maintain your own file-level and record-level access coordination,
or manually release the record lock via explicit program request, or
implicitly release the record lock by selecting another record in the
file. If you are simply reading the record, you can entirely disable
lock acquisition (RAB$L_ROP NLK). If writing, you can permit other
readers but disable writers (RAB$L_ROP RLK).
A typical pattern involves either waiting for the record lock (via
RAB$L_ROP WAT option, and potentially adding the TMO option), or by
periodically retrying access to the record.
If you have no need to write to the file, you should specify READONLY
in your OPEN statement:
open(unit=10, file='FILESHAR.DAT', access='direct', shared,
* organization='sequential', status='old', disp='keep',
* form='unformatted', recordtype='fixed', recl=275, readonly)
Otherwise, Fortran keeps the most recently-read record locked in
expectation that you will then want to update it -- without
unwittingly also overwriting another process's update.
Some application programmers provide for an automatic release of the
record lock (WAT and TMO options, or an explicit timer and AST), either
via a timer that explicitly unlocks the record when the timer expires,
or via an algorithm that reads the data and -- if a record update is
needed -- re-reads and verifies the original contents, and then writes
out the updated record if the original record has not changed.
You can also use various tools to determine the cause of deadlocks,
particularly if you have an application coded to wait for the lock
without a timeout. Example tools include AMDS and the Availability
Manager, and SDA.
|