![]() |
![]() 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.
|