DIRECTORY
FSBackdoor USING [Version],
File USING [Handle],
FS USING [Lock, OpenFile],
Rope USING [ROPE];
Locking - implemented in FSLockImpl
ActiveFile: TYPE = REF ActiveFileObject;
ActiveFileObject:
TYPE =
MONITORED
RECORD [
nameBody: Rope.ROPE, -- first part of key; if NIL then this object is dead
version: FSBackdoor.Version, -- second part of key
h: File.Handle, -- initialized to NIL
fileLock: {none, read, write}, -- initialized to none
recordLock: BOOLEAN, -- TRUE means set
fileLockCount: CARDINAL, -- greater than 1 only for read locks; initialized to 0
attachedTo: ActiveFile, -- NIL unless this is an LName attached to a GName
next: ActiveFile -- hash chain for lock table implementation
];
A "nameBody" in an ActiveFileObject never includes the verison part. For an LName from the default volume the "[]<>" prefix also is omitted from the "nameBody".
Whenever there exists an FS.OpenFile refering to an ActiveFile "a", i.e. "a.fileLockCount" is known to be greater than 0, then code in FSOpenFileImpl may directly read "nameBody", "version", "h", and "fileLock". These fields will not change.
A client that obtains the record lock on an ActiveFileObject can read all fields. In order to alter any fields, the record lock also must be held. Even then there are constraints. "nameBody", "version" and "next" never may be changed outside of the FSLock implementation. "h" can be written only if there are no FS.OpenFile's refering to this ActiveFile yet (it will be NIL in this case). The "fileLock" and "fileLockCount" fields should be changed by calling FSLock.LockFile and FSLock.ReleaseFile. The "attachedTo" can be changed anytime the record lock is held, but should only need to be written if it is NIL.
Locking ActiveFile records (for use from FSDir only) - implemented in FSLockImpl
LockRecord:
PROCEDURE [volumePrefix, nameBody: Rope.
ROPE, version: FSBackdoor.Version]
RETURNS [a: ActiveFile, ok:
BOOLEAN];
Finds the ActiveFileObject for the specified "volumePrefix", "nameBody" and "version" and tries to set it's "recordLock". Always returns an ActiveFile. If "ok" returns FALSE then locking failed: in this case the client can either call FSLock.WaitFortRecord[a] and then call FSLock.LockRecord again, or just go away. If "ok" returns TRUE then locking succeeded and the client must arrange for FSLock.ReleaseRecord[a] to be called eventually.
WaitForRecord:
PROCEDURE [a: ActiveFile];
WAIT's until "a.recordLock" is FALSE, then returns. The client should not reference "a" after the return, as it may no longer reference the ActiveFileObject that controls the named file: call FSLock.LockRecord again to get the new valid ActiveFile.
Locking and releasing ActiveFile records, locking files - implemented in FSLockImpl
LockAttachedToRecord:
PROCEDURE [a: ActiveFile];
WAIT's for then sets the record lock on "a.attachedTo". Raises ERROR if "a.recordLock" is FALSE or if a.attachedTo is dead.
ReleaseRecord:
PROCEDURE [a: ActiveFile];
Releases the internal lock by setting "a.recordLock" to FALSE. If "a.fileLockCount" is 0 then the ActiveFileObject is made dead and removed from the lock table. Calling FSLock.ReleaseRecord on NIL is a no-op. Calling FSLock.ReleaseRecord when "a.recordLock" is FALSE is a no-op.
LockFile:
PROCEDURE [a: ActiveFile, lock:
FS.Lock]
RETURNS [ok:
BOOLEAN];
Sets the specified file lock in the specified ActiveFileObject. Returns FALSE when the lock cannot be set, i.e., when a "write" lock is specified and any lock is held, or when a "read" lock is specified and a "write" lock is held. Should be called only by a client that holds the recordLock: raises ERROR if "a.recordLock" is FALSE.
For implementing operations on FS.OpenFIle's (for use from FSOpenFileImpl) - implemented in FSLockImpl
GetAttachment:
PROCEDURE [a: ActiveFile]
RETURNS [ActiveFile];
Returns "a.attachedTo". For use from FSOpenFileImpl whenever "a.fileLockCount" is known to be greater than 0, i.e., whenever there exists an FS.OpenFile refering to "a". WAIT's when the internal lock in "a" is set.
ReportClose:
PROCEDURE [a: ActiveFile];
Call to report the close an FS.OpenFile. Takes care of releasing the file lock in "a" and in any global file attached to "a". Raises ERROR if a "fileLockCount" of 0 is encountered. WAIT's for record locks.
Lock Table (for use from FSLockImpl only) - implemented in FSLockTableImpl
LookupLock:
PROCEDURE [prefix, nameBody: Rope.
ROPE, version: FSBackdoor.Version]
RETURNS [ActiveFile];
The "prefix", "nameBody" and "version" are looked up in the lock table. Any ActiveFile found is returned. If none is found then a new one is created, inserted in the table, and returned. A new ActiveFile has "fileLockCount" set to 0, and "h" and "attachedTo" set to NIL.
RemoveLock:
PROCEDURE [a: ActiveFile];
The ActiveFile is removed from the lock table.