====== MFS PROGRAMMING & USAGE=====
^Published By^Date^Version^Knowledge Level^Keywords^
|Revelation Technologies|14 NOV 1989|2.X|EXPERT|%RECORDS%, @-variables, @LIST.ACTIVE, @NEXT.FS, sample, program, Next, Aborting, Disabling, Accessing, file+, also, Calling,, Direct, call, different, files, Accounts,, Non-SYSPROG, Arguments, modifying+, names, Assembly, language, Attaching, after, changing, file, handle, installation, using, volume, name, Audit, trail, calling, system, argument, during, FLUSH, INSTALL, BFS,, definition, BFS-bound, Branching+, Btree, index, Buffers, caching, Bypassing, with, direct, calls, Caching, Calling, directly, from, R/BASIC, next, list, CASE, statement, Cataloging, Changing, CLEARSELECT, CODE, Compatibility, Compiling, Compression, CREATE.FILE, CREATE.MEDIA, Current, accessing, Cursors, Data, passing, De-installing, object, code, Debugger, Debugging,during, development, Decryption, Encryption, DELETE.FILE, Detaching, DICT.MFS, Dictionary, problems, with+, current, Direction,READNEXT, function+, Dispatching+, Environmental, Bond, Example|
==== MFS's - PART VI ====
=== Accessing the Advanced Revelation File Name ===
When executing record-oriented calls such as READ.RECORD and WRITE.RECORD,
the MFS does not know the Advanced Revelation file name of the file it is accessing.
The only file information available to the MFS at the time is the file handle.
Some MFSs require access to the name of the file as seen by users. For instance, an
audit trail MFS will likely wish to stamp the Advanced Revelation file name on entries
in the log. Many MFSs must also use the file name, or information based on it, to open
and access related files. An example is SI.MFS, which must open the ! file associated
with a data file.
=== Examining the FILES File ===
There is no simple method to derive the file name from the file handle.
One method of fetching the name is to select the FILES file, examining
each entry until a match is made on the file handle. In effect, the MFS
must execute the equivalent of this R/LIST sentence in order to return
the file name:
"SELECT FILES WITH HANDLE = ":HANDLE
This method is acceptable for applications in which performance is not an
issue. The FILES file is memory-resident, and a SELECT ...
READNEXT ... READ loop to parse it is not as time-intensive as an
equivalent operation against a disk-based file. Nonetheless, applications
in which there is much record I/O will suffer unduly using this method.
=== Modifying the File Handle ===
A second method is to make the Advanced Revelation file name part of
the file handle. This guarantees that the file name is always available
whenever the file handle is passed to the MFS.
In this method, the MFS traps the OPEN.FILE call as the BFS is
returning the file handle back to R/BASIC. During an OPEN.FILE call,
the Advanced Revelation file name is available in the NAME argument.
The MFS simply concatenates the file name onto the file handle with a
delimiter before returning to the calling program. The R/BASIC program
itself is not affected; it merely stores the handle until the next statement
requiring it is executed.
When concatenating the two arguments, the MFS should avoid using
delimiter characters that might otherwise appear in either argument.
Characters to avoid include "!", "_", and "." (all of which frequently
appear in the Advanced Revelation file name), as well as subvalue and
value marks, which appear in the handle.
When subsequent file handle-oriented calls are made to the MFS, the
handle will be returned to the MFS exactly the way the MFS has
constructed it. The MFS must then strip the file name from the handle
before passing the handle on for further processing.
The following code fragment illustrates how the OPEN.FILE logic might
look in an MFS that is tracking the Advanced Revelation file handle:
OPEN.FILE:
FS = DELETE(BFS,1,1,1)
NEXTFS = FS<1,1,1>
CALL @NEXTFS(CODE, FS, HANDLE, NAME, FMC,RECORD,
STATUS)
* add filename onto front of file handle,
* delimit with special character
RECORD = NAME:@TM:RECORD
RETURN
In this example, the MFS delimits the file name and file handle with a
text mark (@TM).
The same MFS uses logic as illustrated below to parse the file name out
of the handle for the MFS calls that require a file handle:
* all following labels share the same logic
CLEARSELECT:
SELECT:
READNEXT:
READ.RECORD:
READO.RECORD:
WRITE.RECORD:
DELETE.RECORD:
LOCK.RECORD:
UNLOCK.RECORD:
* get clear file name, strip from file handle
FILE.NAME = FIELD(HANDLE, @TM , 1)
REAL.HANDLE = FIELD(HANDLE, @TM , 2)
FS = DELETE(BFS, 1, 1, 1)
NEXTFS = FS<1,1,1>
CALL @NEXTFS(CODE,FS,REAL.HANDLE,NAME,FMC,RECORD,
STATUS)
RETURN
=== Maintaining a File Name Table ===
Yet another means for tracking the Advanced Revelation file name is for
the MFS to maintain a table of file names and handles. This method is
useful if the MFS programmer does not wish to carry the filename on the
file handle for fear of interfering with other filing systems.
One strategy is to create a labelled common area in the MFS. In a
simple scenario, the common area contains two dynamic arrays, one for
file names and one for file handles.
When a file is first opened, the MFS traps both the file name and the file
handle after the BFS has returned these. The MFS stores the file name
in one array, and the file handle in the corresponding location in the
second array. When access to the file name is required, the MFS can
locate the file handle in its array, and extract the corresponding file
name.
Because the file handle can change during a session -- for example, if a
file has an MFS added and is reattached -- the file handle is updated in
the labelled common area each time the file is opened.
The following example code fragment illustrates a method to establish
the arrays. In this example, the file name is stored as passed to the
MFS, in the format filename*account.
COMMON /FILENAME/ FILES.ARRAY,HANDLES.ARRAY
(other processing here)
OPEN.FILE:
* call BFS in order to get file handle
FS = DELETE(BFS,1,1,1)
NEXTFS = FS<1,1,1>
CALL @NEXTFS(CODE, FS, HANDLE, NAME, FMC,RECORD,
STATUS)
* load handle and file name into labelled common
IF STATUS THEN
LOCATE NAME IN FILES.ARRAY USING @FM SETTING
POS THEN
HANDLES.ARRAY = RECORD
END ELSE
FILES.ARRAY<-1> = NAME
HANDLES.ARRAY<-1> = RECORD
END
END
RETURN
Once the arrays have been established, the MFS can extract the file
name at any time that it has the file handle available. The following
code fragment illustrates a method by which the READ.RECORD logic
might extract the file name:
READ.RECORD:
* search handle array to get position
LOCATE HANDLE IN HANDLES.ARRAY USING @FM SETTING
POS THEN
* extract corresponding file name
FILE.NAME = FILES.ARRAY
END
FS = DELETE(BFS,1,1,1)
NEXTFS = FS<1,1,1>
CALL @NEXTFS(CODE, FS, HANDLE, NAME,FMC, RECORD,
STATUS)
RETURN
=== Locks and Unlocks ===
In a network environment, an MFS should expect to receive calls that involve record
and file locks. As with other aspects of the system, however, an MFS programmer
must understand the underlying technology of locking in order to take full advantage of
this group of calls.
=== Lock Semaphores ===
In order to remain compatible with the variety of networks supported in
Advanced Revelation, the system uses a standard protocol for the
establishment of locks. This is based on lock semaphores.
When an R/BASIC LOCK statement is executed, the system uses the file
handle and record key information (if locking a record) to create a lock
semaphore. In order to accommodate all potential network locking
schemes, the semaphore is simplified by hashing the file and record
information into a reduced eight-byte format.
=== Local Lock Table ===
The resulting semaphore is then stored in a lock table local to the
workstation. This is done for several reasons.
First, Advanced Revelation supports the capability for programmers to
attempt multiple locks on the same record. In trapping these locks
locally, the system reduces lock overhead by avoiding extra lock calls
made to the network. If a record is already locked by the local station,
this can be detected without an additional call to the network.
Second, storing locks locally gives Advanced Revelation the ability to
report that a lock has already been set by that station. (This is done by
testing STATUS( ) after a lock has failed.) Some networks do not permit
a station to lock the same record twice, and do not report back the proper
error condition.
Finally, the hashing scheme Advanced Revelation uses to create the
semaphores allows the possibility that entirely different file and record
combinations can produce the same semaphore. By maintaining a local
lock table, Advanced Revelation can detect this and arbitrate conflicts
arising from duplicate semaphores. Only non-duplicated semaphores are
passed through to the filing system.
A lock is thus processed at two levels. The first is within the system
before a call is made to the filing system. Only after the internal lock
table has been examined -- and only if necessary -- is the lock call passed
through to the MFS.
As a result, not all lock calls can be trapped at the MFS level. For
example, if a station has a record locked, and attempts to lock it again
from a different program or level of execution, the MFS will never receive
a lock call. Instead, the system will have already detected a conflict
based on the local lock table, and will have returned the proper response
to R/BASIC.
The same is true of unlock calls. If the system can resolve an unlock call
by referencing only the local lock table, it will do so. In these cases, as
with the lock calls, the MFS will never receive the unlock call.
If the lock or unlock call does pass through to the MFS and down to the
BFS, the filing system will return information about the lock and its
status.
**Note**: Lock information returned by the BFS should never
be altered by an MFS, as it will be stored in the local lock
table, and be used to coordinate with other locks.