-- File: WalnutDBLockImpl.mesa
-- Contents:
-- procedures for locking access to Walnut's database & log
-- this file contains ALL of (and only) the ENTRY PROCs
-- Created by: Willie-Sue November 2, 1982
-- Last edited by:
-- Rick Cattell on XXX
-- Willie-Sue on April 13, 1983 12:27 pm
DIRECTORY
GVBasics USING [Timestamp],
GVRetrieve USING [Handle],
IO USING [STREAM],
DB,
WalnutDB,
WalnutDBAccess,
WalnutDBLock,
WalnutDBLog,
WalnutWindow;
WalnutDBLockImpl: CEDAR MONITOR
IMPORTS DB, WalnutDB, WalnutDBAccess, WalnutDBLog, WalnutWindow
EXPORTS WalnutDB, WalnutDBLock =
BEGIN OPEN WalnutDB;
databaseIsBusy: BOOL← FALSE;
databaseAvailable: CONDITION;
CheckForDatabaseBusy: INTERNAL PROC = INLINE
{ UNTIL ~databaseIsBusy DO WAIT databaseAvailable; ENDLOOP;};
-- ********************************************************
InitializeDBVars: PUBLIC ENTRY PROC =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
WalnutDBAccess.DoInitializeDBVars[];
END;
MsgRecToMsg: PUBLIC ENTRY PROC[mr: MsgRec] RETURNS[msg: Msg, existed: BOOL] =
-- Converts msg from record to entity form
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
[msg, existed]← WalnutDBAccess.DoMsgRecToMsg[mr];
END;
DeclareMsg: PUBLIC ENTRY PROC[mName: ROPE] RETURNS [msg: Msg, existed: BOOL] =
-- Creates a new Msg entity, and sets its name to be mName.
-- is called when messages have been read from the log or another file.
-- If the Msg already exists, returns it and returns existed=TRUE.
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
[msg, existed]← WalnutDBAccess.DoDeclareMsg[mName];
END;
DeclareMsgSet: PUBLIC ENTRY PROC[mName: ROPE] RETURNS[msgSet: MsgSet, existed: BOOL] =
-- Creates a new MsgSet entity, and sets its name to be mName.
-- is called when user creates a message set, or reads a log file
-- If the MsgSet already exists, returns it.
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
[msgSet, existed]← WalnutDBAccess.DoDeclareMsgSet[mName];
END;
-- ********************************************************
MGetPList: PUBLIC ENTRY PROC[m: Msg, prop: Attribute] RETURNS [LIST OF Value] =
-- Finds all the values of prop for m and returns them.
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[DB.GetPList[m, prop]]
END;
MGetP: PUBLIC ENTRY PROC[m: Msg, prop: Attribute] RETURNS [Value] =
-- Finds the one unique value for prop for m or NIL if none.
-- SIGNALs NonUniquePropertyValue if more than one value.
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[DB.GetP[m, prop]];
END;
MSetPList: PUBLIC ENTRY PROC[m: Msg, prop: Attribute, vl: LIST OF Value] =
-- Sets the values of prop for m to be those in vl.
-- Erases any previous property values.
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
WalnutWindow.SetWalnutUpdatesPending[TRUE];
DB.SetPList[m, prop, vl];
END;
MSetP: PUBLIC ENTRY PROC[m: Msg, prop: Attribute, v: Value] RETURNS [Relship]=
-- Sets the value of prop for m to be v.
-- Erase any previous property values if this is 2nd attribute of reln
-- (not on any attribute, so that props formed from N-aries will work).
-- Returns the relship used by the prop.
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
WalnutWindow.SetWalnutUpdatesPending[TRUE];
RETURN[DB.SetP[m, prop, v]];
END;
--MEraseP: PUBLIC ENTRY PROC[m: Msg, prop: Attribute, v: Entity] =
-- BEGIN ENABLE UNWIND => NULL;
-- CheckForDatabaseBusy[];
-- WalnutDBAccess.DoEraseP[m, prop, v];
-- END;
--MErasePList: PUBLIC ENTRY PROC[m: Msg, first: Attribute] =
-- BEGIN ENABLE UNWIND => NULL;
-- CheckForDatabaseBusy[];
-- WalnutDBAccess.DoErasePList[m, first];
-- END;
DomainOf: PUBLIC ENTRY PROC[e: Entity] RETURNS[Domain] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[DB.DomainOf[e]];
END;
RelationOf: PUBLIC ENTRY PROC[rel: Relship] RETURNS[Relation] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[DB.RelationOf[rel]];
END;
Null: PUBLIC ENTRY PROC[e: Entity] RETURNS[BOOL] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[DB.Null[e]];
END;
GetName: PUBLIC ENTRY PROC[e: Entity] RETURNS [ROPE] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[DB.GetName[e]];
END;
GetFE: PUBLIC ENTRY PROC[rel: Relship, a: Attribute] RETURNS [Entity] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[DB.V2E[DB.GetF[rel, a]]];
END;
GetFS: PUBLIC ENTRY PROC[rel: Relship, a: Attribute] RETURNS [ROPE] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[DB.GetFS[rel, a]];
END;
CreateEntity: PUBLIC ENTRY PROC[d: Domain, name: ROPE← NIL]
RETURNS[Entity] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[DB.DeclareEntity[d, name, NewOrOld]];
END;
NameToEntity: PUBLIC ENTRY PROC[d: Domain, name: ROPE, oldOnly: BOOL]
RETURNS[e: Entity] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[WalnutDBAccess.DoNameToEntity[d, name, oldOnly]];
END;
GetEntitiesInDomain: PUBLIC ENTRY PROC[d: Domain, alphaOrder: BOOL]
RETURNS[eL: LIST OF Entity] =
-- returns list of entities in given domain
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[WalnutDBAccess.DoGetEntitiesInDomain[d, alphaOrder]];
END;
NumInMsgSet: PUBLIC ENTRY PROC[msgSet: MsgSet] RETURNS[num: INT] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[WalnutDBAccess.DoNumInMsgSet[msgSet]];
END;
RelationSubsetList: PUBLIC ENTRY PROC[r: Relation, constraint: AttributeValueList← NIL]
RETURNS[relList: LIST OF Relship] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[WalnutDBAccess.DoRelationSubsetList[r, constraint]];
END;
-- ********************************************************
-- controlling access to the log file
InitializeLog: PUBLIC ENTRY PROC RETURNS [curLength: INT] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[WalnutDBLog.DoInitializeLog[]];
END;
CloseLogStream: PUBLIC ENTRY PROC =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
WalnutDBLog.DoCloseLogStream[];
END;
OpenWalnutTransaction: PUBLIC ENTRY PROC[trans: DB.Transaction, noLog: BOOL] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
WalnutDBLog.OpenWTransaction[trans, noLog];
END;
CloseWalnutTransaction: PUBLIC ENTRY PROC =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
WalnutDBLog.CloseWTransaction[];
END;
AbortWalnutTransaction: PUBLIC ENTRY PROC =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
WalnutDBLog.AbortWTransaction[];
END;
MarkWalnutTransaction: PUBLIC ENTRY PROC =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
WalnutDBLog.MarkWTransaction[];
END;
GetLogLength: PUBLIC ENTRY PROC[doFlush: BOOL← FALSE] RETURNS[INT] =
{ ENABLE UNWIND => NULL; RETURN[WalnutDBLog.LogLength[doFlush]]};
AddMsgToMsgSet: PUBLIC ENTRY PROC[msg: Msg, msgSet: MsgSet] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
WalnutDBLog.DoAddMsgToMsgSet[msg, msgSet]
END;
RemoveMsgFromMsgSet: PUBLIC ENTRY PROC[msg: Msg, msgSet: MsgSet, rel: Relship] =
-- Removes msg from msgSet and makes entry in log for this update.
-- adds msg to Deleted if necessary
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
WalnutDBLog.DoRemoveMsgFromMsgSet[msg, msgSet, rel, TRUE]
END;
-- this is entirely inside the monitor so no one can change msgSet while it is being archived
ArchiveMsgSet: PUBLIC ENTRY PROC[msgSet: MsgSet, strm: IO.STREAM]
RETURNS[num: INT] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[WalnutDBLog.DoArchiveMsgSet[msgSet, strm]]
END;
DestroyMsgSet: PUBLIC ENTRY PROC[msgSet: MsgSet] =
-- Destroys the given msgSet, removing any messages from it first
-- Makes an entry in the log that says this msgSet was destroyed.
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
WalnutDBLog.DoDestroyMsgSet[msgSet];
END;
ReadGVMessageItems: PUBLIC ENTRY PROC
[gvH: GVRetrieve.Handle, timeStamp: GVBasics.Timestamp, gvSender: RName]
RETURNS[BOOL] =
-- reads message items from Grapevine & makes a log entry for this message
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[WalnutDBLog.GVMessageToLog[gvH, timeStamp, gvSender]];
END;
AddMessageToLog: PUBLIC ENTRY PROC [entryText, prefix: ROPE] =
-- makes a message LogEntryType on log (used by old mial file reader)
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
WalnutDBLog.DoAddMessageToLog[entryText, prefix];
END;
AddMsgReadEntryToLog: PUBLIC ENTRY PROC[msg: Msg] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
WalnutDBLog.WriteMsgReadEntryToLog[msg];
END;
DumpMsgs: PUBLIC ENTRY PROC[tempLog: IO.STREAM, doUpdates, tailRewrite: BOOL]
RETURNS[ok: BOOL] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[WalnutDBLog.ExpungeMsgs[tempLog, doUpdates, tailRewrite]];
END;
-- ********************************************************
-- operations that read the log
GetOneMessageFromLog: PUBLIC ENTRY PROC[startOfNextMessage: INT]
RETURNS[endPos: INT, anymore: BOOL, msgRec: MsgRec, msgWasNew: BOOL] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
[endPos, anymore, msgRec, msgWasNew]← WalnutDBLog.OneMsgFromLog[startOfNextMessage];
END;
-- ********************************************************
-- EXPORTed to WalnutDBLock (private access)
GetWalnutInfo: PUBLIC ENTRY PROC[attr: Attribute] RETURNS[INT] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[DB.V2I[DB.GetF[walnutInfoRelship, attr]]];
END;
SetWalnutInfo: PUBLIC ENTRY PROC[attr: Attribute, i: INT] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
DB.SetF[walnutInfoRelship, attr, DB.I2V[i]];
WalnutWindow.SetWalnutUpdatesPending[TRUE];
END;
IsCopyInProgress: PUBLIC ENTRY PROC RETURNS[BOOL] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[DB.V2B[DB.GetF[walnutInfoRelship, wCopyInProgress]]];
END;
ReadLogFile: PUBLIC ENTRY PROC[startPos: INT] RETURNS[ok: BOOL] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
RETURN[WalnutDBLog.AddLogEntriesToDB[startPos]];
END;
AcquireDBLock: PUBLIC ENTRY PROC[procToCall: PROC] =
BEGIN ENABLE UNWIND => NULL;
CheckForDatabaseBusy[];
procToCall[];
END;
END.