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
~ BEGIN
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.