Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • Access files directly, by using MFS calls.

  • Execute BASIC+ file I/O commands such as READ and WRITE.

Different circumstances dictate the choice of one option or another. Briefly stated, direct calls are necessary when accessing the current file -- the file for which the MFS has trapped a file operation. Access to files other than the current file is best handled using BASIC+ commands.

...

Instead of using BASIC+ commands, the MFS can generate direct calls to the next MFS or the BFS. The following code fragment illustrates how an MFS might execute read-before-write logic using direct calls to the next filing system.  Note that the MFS must preserve any values that might be changed by the direct call (such as the value of the RECORD argument).

 

Code Block
WRITE.RECORD:
* read-before-write logic here
READ.RECORD = 1
OLD.RECORD = ''
NEXTFS = BFS<1,1,2>
CALL @NEXTFS(READ.RECORD, FS, HANDLE,NAME, FMC, OLD.RECORD, STATUS)
IF STATUS THEN
  IF OLD.RECORD NE RECORD THEN
    CALL MSG(@window, "Record ":NAME:" has changed.")
  END ELSE
    CALL MSG(@window, "Record ":NAME:" has not changed.")
  END
END ELSE
  CALL MSG(@window, "Record ":NAME:" is a new record.")
END
* continue normal processing
GOSUB NEXT.MFS
RETURN

...

If the MFS needs to update a file other than the current file, it is best to use BASIC+ file I/O commands (OPEN, READ, WRITE, DELETE) rather than a direct call. If a direct call is used, the MFS will pass a call to the next filing system (MFS or BFS) for the current file. This may cause problems in two ways.

...

The standard method for disabling a function is for the MFS to set the STATUS argument to false, and to execute a RETURN statement immediately. The MFS should normally not call subsequent filing systems, since these may proceed with the operation (such as creating a file or updating a record), reset the value of STATUS, or set the value of other variables used in detecting the success of an operation.

In many cases, the BASIC+ command that generated the MFS call will fall through its ELSE logic when detecting a status of false. This is the case, for instance, for the BASIC+  Read_Row subroutine. Many System Monitor commands will also post a message indicating that the command could not be executed.

The program fragment below illustrates a simple method for disabling the READ.RECORD code:

...

Code Block
READ.RECORD:
  GOSUB CHECK.SECURITY
  IF SECURITY.CHECK = PASSED$ THEN
    GOSUB NEXT.MFS
  END ELSE
    STATUS = 0
  END
  RETURN

 

...

This method of disabling functions means that a subsequent MFS does not have an opportunity to act upon the code being called. This has implications for the ordering of MFSs. For example, if an audit trail MFS is required to log an attempt to read, write or delete all records -- even if these functions are not successful -- the audit trail MFS must precede any security MFS that might abort the record operation.

Not all functions translate a status value of false directly into a failure. For example, a BASIC+ SELECT statement does not look at the return value of STATUS. Instead, the SELECT statement examines the value of RECORD to determine whether a select condition is active. The value of RECORD is translated into the value of the system variable @LIST.ACTIVE, which is in turn read by subsequent READNEXT statements. If RECORD (and by extension, @LIST.ACTIVE) is false, a READNEXT statement will fall through its ELSE logic.