MODULE; IMPORT ClientClass, ErrMsg, FileAttr, Logger, OSError, OSErrorPosix, Pathname, Rd, Text, Thread, Time, Uerror; PROCEDURE ClassDB Init (fn: Pathname.T; logger: Logger.T := NIL) RAISES {Rd.Failure, Thread.Alerted} = BEGIN LOCK mu DO RealInit(fn, logger); END; END Init; PROCEDURERealInit (fn: Pathname.T; logger: Logger.T := NIL) RAISES {Rd.Failure, Thread.Alerted} = BEGIN IF db = NIL THEN db := NEW(ClientClass.DB); dbPath := fn; dbLogger := logger; dbModTime := GetModTime(fn, logger); dbRefreshTime := Time.Now(); END; EVAL db.init(fn); END RealInit; PROCEDUREGetClass (name: TEXT) : ClientClass.T = BEGIN LOCK mu DO RETURN db.getClass(name); END; END GetClass; PROCEDUREGet (path: Pathname.T; maxAge: Time.T; logger: Logger.T := NIL): ClientClass.DB RAISES {Rd.Failure, Thread.Alerted} = VAR now := Time.Now(); fileTime := GetModTime(path, logger); BEGIN LOCK mu DO IF fileTime < 0.0d0 THEN RETURN ClientClass.FreeAccessDB(); END; IF Text.Equal(path, dbPath) AND dbModTime = fileTime AND dbRefreshTime >= now - maxAge THEN RETURN db; END; db := NIL; RealInit(path, logger); RETURN db; END; END Get; PROCEDUREGetModTime (fn: Pathname.T; logger: Logger.T) : Time.T =
Returns the modification time of fn
, or -1.0d0 if that information
cannot be gotten. In the latter case, a warning is logged unless the
file simply doesn't exist.
VAR attr: FileAttr.T; fileTime: Time.T; BEGIN TRY attr := FileAttr.FromPathname(fn, follow := TRUE); fileTime := FileAttr.GetModTime(attr); EXCEPT OSError.E(list) => IF list.head # EnoentAtom THEN Log(logger, Logger.Priority.Warning, "Cannot get attributes for \"" & fn & "\": " & ErrMsg.StrError(list)); END; fileTime := -1.0d0; END; RETURN fileTime; END GetModTime; PROCEDURELog (logger: Logger.T; priority: Logger.Priority; msg: TEXT) = BEGIN IF logger # NIL THEN Logger.Put(logger, priority, msg); END; END Log; VAR (* CONST *) EnoentAtom := OSErrorPosix.ErrnoAtom(Uerror.ENOENT); VAR mu:= NEW(MUTEX); db: ClientClass.DB; dbPath: Pathname.T; dbLogger: Logger.T; dbModTime: Time.T; dbRefreshTime: Time.T; BEGIN db := NIL; dbPath := ""; dbLogger := NIL; dbModTime := -1.0d0; dbRefreshTime := -1.0d0; END ClassDB.