YodelSignalsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Yodel: Signal Handler
Last Edited by:
Bob Hagmann June 11, 1985 9:51:23 am PDT
DIRECTORY
AlpineEnvironment
USING[ NeededAccess, OperationFailure, Principal,
UnknownType],
AlpDirectory USING[ Error ],
AlpineDirectory USING[ ErrorType ],
AlpineInterimDirectory
USING[ DirectoryInconsistent,
Error, ErrorType],
AlpInstance  USING[ AccessFailed, Create, Handle, LockFailed, Failed,
OperationFailed, PossiblyDamaged, StaticallyInvalid, Unknown],
AlpTransaction USING[ Create, Finish, Handle, OperationFailed, Outcome],
AMTypes  USING[ IndexToName, Type],
FS    USING[ Error],
IO,
PrincOpsUtils USING[ IsBound ],
Rope,
RPC    USING[ CallFailed, CallFailure, EncryptionKey, MakeKey],
UserCredentials USING[ Get ],
YodelData;
YodelSignalsImpl: CEDAR PROGRAM
IMPORTS AlpDirectory, AlpineInterimDirectory, AlpInstance, AlpTransaction, AMTypes, FS, IO, PrincOpsUtils, Rope, RPC, UserCredentials
EXPORTS YodelData
=
BEGIN OPEN YodelData;
ROPE: TYPE = Rope.ROPE;
This procedure checks to be sure Alpine is bound, and then calls the PerformProc.
Most signals from Alpine are caught, and appropiate lists of ropes are returned.
PerformOp: PUBLIC PROC[ performProc: PerformProc, server: ROPE,
user: ROPENIL, password: ROPENIL]
RETURNS [LIST OF REF ANY] = {
failureName: ROPE ← "" ;
userName, userPassword, keyRope: ROPE;
caller: AlpineEnvironment.Principal ;
key: RPC.EncryptionKey;
inst: AlpInstance.Handle ← NIL;
trans: AlpTransaction.Handle ← NIL ;
outcome: AlpTransaction.Outcome ← unknown;
result: LIST OF REF ANYNIL ;
{
ENABLE BEGIN
RPC.CallFailed => {
type: AMTypes.Type ← CODE[RPC.CallFailure];
failure: RPC.CallFailure;
count: CARDINAL ← 1 ;
failureName ← "*unknown*";
FOR failure IN RPC.CallFailure DO
IF why = failure THEN {
failureName ← AMTypes.IndexToName[type: type, index: count];
};
count ← count + 1 ;
ENDLOOP;
GOTO RPCFailed;
};
AlpInstance.StaticallyInvalid => GOTO statInvalid ;
AlpInstance.Unknown =>{
type: AMTypes.Type ← CODE[AlpineEnvironment.UnknownType];
failure: AlpineEnvironment.UnknownType;
count: CARDINAL ← 1 ;
failureName ← "*unknown*";
IF what = AlpineEnvironment.UnknownType.owner THEN GOTO badOwner;
IF what = AlpineEnvironment.UnknownType.transID THEN GOTO badTransID;
FOR failure IN AlpineEnvironment.UnknownType DO
IF what = failure THEN {
failureName ← AMTypes.IndexToName[type: type, index: count];
};
count ← count + 1 ;
ENDLOOP;
GOTO alpUnknown;
};
AlpInstance.AccessFailed =>{
type: AMTypes.Type ← CODE[AlpineEnvironment.NeededAccess];
failure: AlpineEnvironment.NeededAccess;
count: CARDINAL ← 1 ;
failureName ← "*unknown*";
FOR failure IN AlpineEnvironment.NeededAccess DO
IF missingAccess = failure THEN {
failureName ← AMTypes.IndexToName[type: type, index: count];
};
count ← count + 1 ;
ENDLOOP;
GOTO accFail;
};
AlpInstance.OperationFailed => {
type: AMTypes.Type ← CODE[AlpineEnvironment.OperationFailure];
failure: AlpineEnvironment.OperationFailure;
count: CARDINAL ← 1 ;
failureName ← "*unknown*";
FOR failure IN AlpineEnvironment.OperationFailure DO
IF why = failure THEN {
failureName ← AMTypes.IndexToName[type: type, index: count];
};
count ← count + 1 ;
ENDLOOP;
GOTO opFail;
};
AlpineInterimDirectory.DirectoryInconsistent => GOTO dirInconsistent;
AlpineInterimDirectory.Error => {
type: AMTypes.Type ← CODE[AlpineInterimDirectory.ErrorType];
failure: AlpineInterimDirectory.ErrorType;
count: CARDINAL ← 1 ;
failureName ← "*unknown*";
FOR failure IN AlpineInterimDirectory.ErrorType DO
IF why = failure THEN {
failureName ← AMTypes.IndexToName[type: type, index: count];
};
count ← count + 1 ;
ENDLOOP;
GOTO interimDirError;
};
AlpDirectory.Error => {
typeCode: AMTypes.Type ← CODE[AlpineDirectory.ErrorType];
failure: AlpineDirectory.ErrorType;
count: CARDINAL ← 1 ;
failureName ← "*unknown*";
FOR failure IN AlpineDirectory.ErrorType DO
IF type = failure THEN {
failureName ← AMTypes.IndexToName[type: typeCode, index: count];
};
count ← count + 1 ;
ENDLOOP;
GOTO dirError;
};
AlpInstance.LockFailed => GOTO lockFail;
AlpInstance.PossiblyDamaged => GOTO possDamaged;
AlpTransaction.OperationFailed => GOTO alpineBusy;
AlpInstance.Failed => {
SELECT why FROM
alpineDownOrCommunications => {
failureName ← " alpine or communications are down";
GOTO alpineError ;
};
alpineDown => {
failureName ← " alpine server is down";
GOTO alpineError ;
};
authenticateFailed => {
failureName ← " of authentication error- suspect bad user name or password";
GOTO alpineError ;
};
badCallee => {
failureName ← " of bad server name";
GOTO alpineError ;
};
grapevineDownOrCommunications => {
failureName ← " communications or server are down";
GOTO alpineError ;
};
mismatch => {
failureName ← " mismatch (for example, version incompatibility)";
GOTO alpineError ;
};
ENDCASE ;
};
FS.Error => {
failureName ← error.explanation ;
GOTO FSError ;
};
IO.Error => {
SELECT ec FROM
SyntaxError => {
failureName ← "Syntax Error";
GOTO syntaxError ;} ;
ENDCASE ;
};
END;
TRUSTED BEGIN
IF NOT PrincOpsUtils.IsBound[link: LOOPHOLE[AlpInstance.Create]] THEN GOTO notBound ;
END;
[userName, userPassword] ← UserCredentials.Get[];
IF (Rope.Equal[user,""] OR Rope.Equal[user,NIL]) THEN caller ← userName
ELSE caller ← user ;
IF (Rope.Equal[password,""] OR Rope.Equal[password,NIL]) THEN keyRope ← userPassword
ELSE keyRope ← password ;
TRUSTED BEGIN key ← RPC.MakeKey[keyRope]; END;
IF Rope.Match[pattern: "*.alpine", object: server, case: FALSE] THEN {
inst ← AlpInstance.Create[fileStore: server, caller: caller, key: key];
trans ← AlpTransaction.Create[inst];
};
result ← performProc[trans: trans, serverForTrans: server, caller: caller, key: key];
IF trans # NIL THEN {
outcome ← AlpTransaction.Finish[trans, commit];
};
RETURN[result];
EXITS
RPCFailed => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;];
RETURN[CONS[IO.PutFR["RPC failure: %g", IO.rope[failureName]],NIL]];
};
alpineBusy => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;];
RETURN[CONS[NARROW["Alpine server is busy - please try again later", ROPE], NIL]];
};
dirInconsistent => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;];
RETURN[CONS[NARROW["Alpine Interim Directory: directory is inconsistent",ROPE], NIL]];
};
dirError => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;];
RETURN[CONS[IO.PutFR["Alpine Directory Error: %g",
IO.rope[failureName]],NIL]];
};
interimDirError => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;];
RETURN[CONS[IO.PutFR["Alpine Interim Directory Error: %g", IO.rope[failureName]],NIL]];
};
accFail => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;];
RETURN[CONS[IO.PutFR["Alpine denied access because client is not in the %g access control list", IO.rope[failureName]],NIL ]];
};
lockFail => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;];
RETURN[CONS[NARROW["Alpine server has a conflict or timed out a lock - please try again later", ROPE], NIL]];
};
opFail => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;];
RETURN[CONS[IO.PutFR["Alpine Instance Operation Failed: %g", IO.rope[failureName]],NIL]];
};
possDamaged => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;];
RETURN[CONS[NARROW["Alpine server reports possible damage", ROPE], NIL]];
};
alpUnknown => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;];
RETURN[CONS[IO.PutFR["Alpine Instance Unknown Type: %g", IO.rope[failureName]],NIL]];
};
badOwner => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;];
RETURN[CONS[NARROW["Alpine Unknown Type: owner -- suspect bad directory, owner or access list name", ROPE], NIL]];
};
badTransID => {
RETURN[CONS[
NARROW["Alpine Unknown Type: transID -- suspect transaction has aborted or that the server has crashed and restarted", ROPE], NIL]];
};
statInvalid => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;];
RETURN[CONS[NARROW["Alpine Statically Invalid error - suspect unreasonable property value or Yodel bug", ROPE], NIL]];
};
notBound => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;];
RETURN[CONS[NARROW["unbound error- suspect AlpineUserImpls has not been run", ROPE], NIL]];
};
alpineError => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;];
RETURN[CONS[IO.PutFR["Alpine error because %g",IO.rope[failureName]],NIL]];
};
FSError => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;];
RETURN[CONS[IO.PutFR["FS could not perform operation because %g", IO.rope[failureName]], NIL]];
};
syntaxError => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;];
RETURN[CONS[IO.PutFR["Syntax error in input: %g", IO.rope[failureName]],NIL]];
};
};
};
END.
Bob Hagmann June 10, 1985 4:57:53 pm PDT
reformatted
Bob Hagmann January 9, 1986 5:17:23 pm PST
Added catch phrases for RPC.CallFailed inside the EXIT clauses
changes to: PerformOp