DIRECTORY AccessControl, AlpineDebug, AlpineEnvironment, AlpineFile, AlpineInternal, AlpineOwner, AlpineVolume, FileInstance, FileMap, FilePrivate, Lock, LogMap, OpenFileMap, TransactionMap; FilePrivateImpl: MONITOR IMPORTS AccessControl, AlpineFile, FileInstance, FileMap, Lock, LogMap, OpenFileMap, TransactionMap EXPORTS FilePrivate = BEGIN OPEN FilePrivate; EstablishOpenFileContext: PUBLIC PROCEDURE [conversation: AlpineEnvironment.Conversation, openFileID: AlpineEnvironment.OpenFileID, work: OpenFileWork, workLevel: AlpineInternal.WorkLevel _ normal, concurrency: Concurrency _ normal] = BEGIN openFile: OpenFileMap.Handle = OpenFileMap.GetAndCheckHandle[conversation: conversation, openFileID: openFileID ! OpenFileMap.OpenFileIDNotFound, OpenFileMap.BadConversation => GOTO unknownOpenFileID]; fileInstance: FileInstance.Handle = OpenFileMap.GetFileInstanceHandle[openFile]; file: FileMap.Handle = FileInstance.GetFileHandle[fileInstance]; trans: TransactionMap.Handle = FileInstance.GetTransHandle[fileInstance]; updateCost: INT; lockFailure: AlpineEnvironment.LockFailure; operationFailure: AlpineEnvironment.OperationFailure; unknownType: AlpineEnvironment.UnknownType; DO IF concurrency=normal THEN BEGIN IF ~TransactionMap.StartWork[trans, workLevel] THEN ERROR AlpineFile.Unknown[transID]; -- trans must already have finished END ELSE StartExclusiveWork[file, trans, workLevel]; BEGIN ENABLE { AcquireInterlockAttempted => { IF ~failed THEN {concurrency _ exclusive; RESUME} ELSE GOTO acquireInterlockFailed}; AlpineFile.AccessFailed, AlpineFile.LockFailed, AlpineFile.OperationFailed, AlpineFile.StaticallyInvalid, AlpineFile.Unknown => { IF concurrency=normal THEN TransactionMap.StopWork[trans, updateCost] ELSE StopExclusiveWork[file, trans, updateCost]}}; description: LogMap.FileDescription = LogMap.DescribeFile[file, trans]; IF description.registered AND ~description.exists THEN ERROR AlpineFile.Unknown[openFileID]; -- most likely the file has been deleted by this transaction updateCost _ 0; BEGIN work[openFile: openFile, fileInstance: fileInstance, file: file, trans: trans, pUpdateCost: @updateCost ! AccessControl.LockFailed, Lock.Failed => {lockFailure _ why; GOTO lockFailed}; AccessControl.OperationFailed => {operationFailure _ why; GOTO operationFailed}; AccessControl.StaticallyInvalid => GOTO staticallyInvalid; AccessControl.Unknown => {unknownType _ why; GOTO unknown}; Lock.TransAborting => {unknownType _ transID; GOTO unknown}]; EXITS lockFailed => ERROR AlpineFile.LockFailed[lockFailure]; operationFailed => ERROR AlpineFile.OperationFailed[operationFailure]; staticallyInvalid => ERROR AlpineFile.StaticallyInvalid; unknown => ERROR AlpineFile.Unknown[unknownType]; END; GOTO finished; EXITS acquireInterlockFailed => BEGIN TransactionMap.StopWork[trans, updateCost]; AwaitExclusiveWorkCompleted[]; END; END; REPEAT finished => NULL; ENDLOOP; IF concurrency=normal THEN TransactionMap.StopWork[trans, updateCost] ELSE StopExclusiveWork[file, trans, updateCost]; EXITS unknownOpenFileID => ERROR AlpineFile.Unknown[openFileID]; END; AcquireFileInterlock: PUBLIC PROCEDURE [file: FileMap.Handle] = BEGIN SIGNAL AcquireInterlockAttempted[failed: FileMap.SetInterlock[file, TRUE]]; -- RESUMEd only if failed=FALSE END; EstablishTransactionContext: PUBLIC PROCEDURE [conversation: AlpineEnvironment.Conversation, transID: AlpineEnvironment.TransID, work: TransactionWork, workLevel: AlpineInternal.WorkLevel _ normal] = BEGIN trans: TransactionMap.Handle = TransactionMap.GetHandle[transID]; updateCost: INT; lockFailure: AlpineEnvironment.LockFailure; operationFailure: AlpineEnvironment.OperationFailure; unknownType: AlpineEnvironment.UnknownType; IF trans=TransactionMap.nullHandle OR ~TransactionMap.StartWork[trans, workLevel] THEN ERROR AlpineFile.Unknown[transID]; BEGIN ENABLE AlpineFile.AccessFailed, AlpineFile.LockFailed, AlpineFile.OperationFailed, AlpineFile.StaticallyInvalid, AlpineFile.Unknown => TransactionMap.StopWork[trans, updateCost]; updateCost _ 0; BEGIN -- extra nesting so errors raised from EXITS clause are caught by the ENABLE work[trans: trans, pUpdateCost: @updateCost ! AccessControl.LockFailed, Lock.Failed => {lockFailure _ why; GOTO lockFailed}; AccessControl.OperationFailed => {operationFailure _ why; GOTO operationFailed}; AccessControl.StaticallyInvalid => GOTO staticallyInvalid; AccessControl.Unknown => {unknownType _ why; GOTO unknown}; Lock.TransAborting => {unknownType _ transID; GOTO unknown}]; EXITS lockFailed => ERROR AlpineFile.LockFailed[lockFailure]; operationFailed => ERROR AlpineFile.OperationFailed[operationFailure]; staticallyInvalid => ERROR AlpineFile.StaticallyInvalid; unknown => ERROR AlpineFile.Unknown[unknownType]; END; END; TransactionMap.StopWork[trans, updateCost]; END; AcquireInterlockAttempted: SIGNAL [failed: BOOLEAN] = CODE; exclusiveWorkCompleted: CONDITION; AwaitExclusiveWorkCompleted: ENTRY PROCEDURE = {WAIT exclusiveWorkCompleted}; StartExclusiveWork: ENTRY PROCEDURE [file: FileMap.Handle, trans: TransactionMap.Handle, workLevel: AlpineInternal.WorkLevel] = BEGIN DO IF ~TransactionMap.StartWork[trans, workLevel] THEN RETURN WITH ERROR AlpineFile.Unknown[transID]; -- trans must already have finished IF ~FileMap.SetInterlock[file, TRUE] THEN EXIT; TransactionMap.StopWork[trans, 0]; WAIT exclusiveWorkCompleted; ENDLOOP; END; StopExclusiveWork: ENTRY PROCEDURE[file: FileMap.Handle, trans: TransactionMap.Handle, updateCost: INT] = BEGIN IF ~FileMap.SetInterlock[file, FALSE] THEN ERROR; TransactionMap.StopWork[trans, updateCost]; BROADCAST exclusiveWorkCompleted; END; END. FilePrivateImpl.mesa Last edited by: Taft on May 25, 1983 10:46 am MBrown on November 15, 1982 5:11 pm Kolling on March 9, 1983 12:05 pm FilePrivate. Informational signal from AcquireFileInterlock: Public error. Clean up local state and then allow signal to propagate. n.b. this does the right thing only for ERRORs, not SIGNALs. now loop back to "BEGIN ENABLE ..." Public error. Clean up local state and then allow signal to propagate. n.b. this does the right thing only for ERRORs, not SIGNALs. Internal stuff ! Unknown[transID] Κ4– "cedar" style˜Jšœ™šœ™Jšœ™Jšœ#™#Jšœ!™!—unitšΟk ˜ Icode˜L˜ L˜L˜ L˜L˜ L˜ L˜ L˜L˜ L˜L˜L˜ L˜—šœ˜Lšœ\˜cLšœ˜Lšœœ ˜—J˜šœ ™ šΟnœœ œΐ˜κLš˜˜qLšœ?œ˜W—L˜PL˜@L˜ILšœ œ˜L˜+L˜5L˜+š˜šœ˜Lš˜šœ-˜3LšœΟc#˜G—Lš˜—Lšœ,˜0šœœ˜Jšœ/™/˜Lšœ œœ˜1Lšœœ˜"—Jšœoœœ™ƒ˜Lšœœ+˜ELšœ.˜2—L˜Gšœœ˜6Lšœ!Ÿ<˜b—˜Lš˜˜iLšœ=œ ˜NLšœ:œ˜PLšœ#œ˜:Lšœ.œ ˜œŸΠckŸ ˜kLšœ˜—šžœœ œš˜ΗLš˜L˜ALšœ œ˜L˜+L˜5L˜+šœ!œ-˜VLšœ˜"—šœ˜ Jšœoœœ™ƒ˜Lšœ+˜+—˜LšœŸ' Ÿ ˜S˜-Lšœ=œ ˜NLšœ:œ˜PLšœ#œ˜:Lšœ.œ ˜