FSLockTableImpl.mesa
Last Edited by: Schroeder, November 15, 1983 1:29 pm
Last Edited by: Levin, August 9, 1983 11:39 am
DIRECTORY
Ascii USING [Upper],
Basics USING [BITOR, BITSHIFT, BITXOR],
FSLock USING [ActiveFile, ActiveFileObject],
FSBackdoor USING [Version],
Rope USING [Concat, Equal, InlineFetch, Length, ROPE];
FSLockTableImpl: CEDAR MONITOR
IMPORTS Ascii, Basics, Rope
EXPORTS FSLock
= BEGIN
Exported to FSLock
LookupLock: PUBLIC ENTRY PROC [prefix, nameBody: Rope.ROPE, version: FSBackdoor.Version] RETURNS [a: FSLock.ActiveFile] =
BEGIN
hash: CARDINAL;
IF Rope.InlineFetch[nameBody, 0] # '[ AND prefix # NIL
THEN nameBody ← Rope.Concat[prefix, nameBody];
hash ← Hash[nameBody, version];
lookups ← lookups + 1;
FOR a ← lockTbl[hash], a.next UNTIL a = NIL DO
IF version = a.version AND Rope.Equal[nameBody, a.nameBody, FALSE]
THEN RETURN;
ENDLOOP;
newActiveFiles ← newActiveFiles + 1;
a ← NEW [FSLock.ActiveFileObject];
a.nameBody ← nameBody;
a.version ← version;
a.h ← NIL;
a.fileLock ← none;
a.recordLock ← FALSE;
a.fileLockCount ← 0;
a.attachedTo ← NIL;
a.next ← lockTbl[hash];
lockTbl[hash] ← a;
END;
RemoveLock: PUBLIC ENTRY PROC [a: FSLock.ActiveFile] =
BEGIN
hash: CARDINAL = Hash[a.nameBody, a.version];
aPrev: FSLock.ActiveFile ← lockTbl[hash];
removals ← removals + 1;
IF aPrev = a
THEN lockTbl[hash] ← a.next
ELSE DO
IF aPrev.next = a THEN {aPrev.next ← a.next; EXIT};
aPrev ← aPrev.next;
ENDLOOP;
a.nameBody ← NIL;
END;
Statistics
lookups: INT ← 0;
newActiveFiles: INT ← 0;
removals: INT ← 0;
Lock Table
buckets: CARDINAL = 509;
LockTable: TYPE = ARRAY [0..buckets) OF FSLock.ActiveFile;
lockTbl: REF LockTable ← NEW [LockTable ← ALL[NIL]];
Hash: PROC [name: Rope.ROPE, v: FSBackdoor.Version] RETURNS [hash: CARDINAL] = TRUSTED
BEGIN
OPEN Basics;
len: CARDINAL = Rope.Length[name];
hash ← len + v;
FOR i: CARDINAL ← 0, i+ 2 WHILE i < len DO
hash ← BITOR[BITSHIFT[hash, 1], BITSHIFT[hash, -15]];
hash ← BITXOR[BITSHIFT[CHAR[Ascii.Upper[Rope.InlineFetch[name, i]]].ORD, 8], hash];
IF i+1 < len THEN hash ← BITXOR[CHAR[Ascii.Upper[Rope.InlineFetch[name, i+1]]].ORD, hash];
ENDLOOP;
hash ← hash MOD buckets;
END;
AFT statistics
Stats: ENTRY PROC RETURNS [items, longestChain: INT, chains: ARRAY [0..10] OF CARDINAL] =
BEGIN
items ← 0;
longestChain ← 0;
chains ← ALL[0];
FOR i: CARDINAL IN [0 .. buckets) DO
chainLength: INT ← 0;
cIndex: CARDINAL;
FOR a: FSLock.ActiveFile ← lockTbl[i], a.next UNTIL a = NIL DO
chainLength ← chainLength + 1;
ENDLOOP;
items ← items + chainLength;
IF chainLength > longestChain THEN longestChain ← chainLength;
cIndex ← MIN [chainLength, 10];
chains[cIndex] ← chains[cIndex] + 1;
ENDLOOP;
END;
END.