XlDBImpl.mesa
Copyright Ó 1989, 1990, 1991, 1992 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, October 6, 1989 12:58:15 pm PDT
Christian Jacobi, January 11, 1993 11:41 am PST
DIRECTORY Customize, Rope, Xl, XlDB, XlPredefinedAtoms;
XlDBImpl:
CEDAR
MONITOR
LOCKS mr USING mr: REF MyRec
IMPORTS Customize, Rope, Xl
EXPORTS XlDB
SHARES Customize
MyRec:
TYPE =
MONITORED
RECORD [
val: Rope.ROPE ¬ NIL,
db: Customize.DB ¬ NIL,
errors: Rope.ROPE,
invalidation: LIST OF InvalidationRec ¬ NIL
];
myKey: REF ATOM ¬ NEW[ATOM ¬ $XlDB];
propertyEvents: Xl.EventFilter = Xl.CreateEventFilter[propertyNotify];
ResetProc: Xl.EventProcType = {
--Flushes the cached shared data base
WITH event
SELECT
FROM
pne: Xl.PropertyNotifyEvent =>
IF pne.atom=XlPredefinedAtoms.resourceManager
THEN {
mr: REF MyRec ¬ NARROW[clientData]; mr.val ¬ NIL; mr.db ¬ NIL;
FOR l:
LIST
OF InvalidationRec ¬ mr.invalidation, l.rest
WHILE l#
NIL
DO
Xl.Enqueue[l.first.tq, l.first.proc, l.first.data, event];
ENDLOOP;
};
ENDCASE => {};
};
InitializeProp: Xl.InitializeProcType = {
--Set up connection so that shared data base is flushed from cache
--when the corresponding property value is set.
rootWindow: Xl.Window ¬ Xl.FirstRoot[c];
mr: REF MyRec ¬ NEW[MyRec];
match: Xl.Match ¬ NEW[Xl.MatchRep ¬ [proc: ResetProc, handles: propertyEvents, tq: Xl.CreateTQ[], data: mr]];
Xl.AddDispatch[c, rootWindow, match, [propertyChange: TRUE]];
RETURN [mr];
};
ReloadDBCache:
ENTRY
PROC [c: Xl.Connection, mr:
REF MyRec, readonly:
BOOL]
RETURNS [db: Customize.
DB ¬
NIL] = {
--Reread the database; if not readonly put it into the cache atomically
db ¬ mr.db;
IF ~readonly
OR db=
NIL
THEN {
val: Rope.ROPE ¬ mr.val;
IF val=
NIL
THEN {
pr: Xl.PropertyReturnRec;
pr ¬ Xl.GetProperty[c: c, w: Xl.FirstRoot[c], property: XlPredefinedAtoms.resourceManager ! Xl.XError => {
mr.errors ¬ Rope.Concat["failed reading resource←manager property: ", err.explanation];
GOTO Oops;
}];
IF pr.type = XlPredefinedAtoms.string
AND
ISTYPE[pr.value, Rope.
ROPE]
THEN mr.val ¬ val ¬ NARROW[pr.value]
ELSE mr.errors ¬ "bad resource←manager property";
EXITS Oops => {};
};
db ¬ Customize.CreateDB[];
IF val#NIL THEN mr.errors ¬ Customize.UpdateDBString[db, val];
IF readonly THEN mr.db ¬ db;
};
};
GetStandardDBReadWrite:
PUBLIC
PROC [c: Xl.Connection]
RETURNS [db: Customize.
DB] = {
--Returns a modifiable copy of the default data base of the connection
WITH Xl.GetConnectionPropAndInit[c, myKey, InitializeProp]
SELECT
FROM
mr:
REF MyRec => {
db ¬ ReloadDBCache[c, mr, FALSE];
};
ENDCASE => ERROR;
};
GetStandardDB:
PUBLIC
PROC [c: Xl.Connection]
RETURNS [db: Customize.DBreadonly] = {
--Returns the shared default data base of the connection
WITH Xl.GetConnectionPropAndInit[c, myKey, InitializeProp]
SELECT
FROM
mr:
REF MyRec => {
db ¬ mr.db;
IF db=NIL THEN db ¬ ReloadDBCache[c, mr, TRUE];
};
ENDCASE => ERROR;
};
InvalidationRec: TYPE = RECORD [proc: Xl.EventProcType, tq: Xl.TQ, data: REF];
ConsInvalidator:
ENTRY
PROC [mr:
REF MyRec, ir: InvalidationRec] = {
mr.invalidation ¬ CONS[ir, mr.invalidation];
};
RegisterDBInvalidator:
PUBLIC
PROC [c: Xl.Connection, proc: Xl.EventProcType, tq: Xl.
TQ, data:
REF ¬
NIL] = {
WITH Xl.GetConnectionPropAndInit[c, myKey, InitializeProp]
SELECT
FROM
mr:
REF MyRec => {
IF proc=NIL THEN RETURN;
IF tq=NIL THEN tq ¬ Xl.CreateTQ[];
ConsInvalidator[mr, [proc, tq, data]];
};
ENDCASE => ERROR;
};
QueryStandardDB:
PUBLIC
PROC [c: Xl.Connection, query: Rope.
ROPE]
RETURNS [answer: Rope.
ROPE] = {
db: Customize.DBreadonly = GetStandardDB[c];
WITH Customize.DoQueryString[db, query]
SELECT
FROM
r: Rope.ROPE => RETURN [r];
ENDCASE => RETURN [NIL];
};
END.