MODULE PrevalenceSystem;
IMPORT XML, XMLObjects, XMLScanner, XMLParser, TFClasses,
Strings, Modules, Kernel, Files, Streams, KernelLog, Configuration;
CONST
DEBUG = FALSE;
ConfigurationSupperSectionName = "PrevalenceSystem";
ConfigurationSubSectionName = "PersistentObjectModules";
ProcNameGetDescriptors = "GetPersistentObjectDescriptors";
SnapShotIntervall = 15 * 60 * 100;
StandardPrevSystemName = "StandardPrevalenceSystem";
StandardSnapShotFileName = "PrevalenceSnapShot.XML";
StandardLogFileName = "PrevalenceLog.XML";
XMLProlog = '<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>';
XMLRootElemName = "instances";
XMLOidCounterAttrName = "oidcounter";
XMLInstanceElemName = "instance";
XMLAttrModuleName = "module";
XMLAttrObjectName = "object";
XMLAttrOidName = "oid";
XMLAttrIsRootName = "isroot";
XMLAttrSavingCounter ="time";
XMLLogRootElemName = "log";
XMLLogDelInstElemName = "deleted";
TermTimeout = 1000*1000;
TYPE
PersistentObject* = OBJECT
VAR
oid*: LONGINT;
inModification, takingSnapShot: BOOLEAN;
registeredAt*: PrevalenceSystem;
PROCEDURE &Init*;
BEGIN oid := 0; inModification := FALSE; takingSnapShot := FALSE; registeredAt := NIL
END Init;
PROCEDURE BeginModification*;
BEGIN {EXCLUSIVE}
AWAIT((~takingSnapShot) & (~inModification));
inModification := TRUE;
END BeginModification;
PROCEDURE EndModification*;
BEGIN {EXCLUSIVE}
IF (registeredAt # NIL) THEN
registeredAt.Log(SELF)
ELSE
HALT(9999);
END;
inModification := FALSE
END EndModification;
PROCEDURE Externalize*() : XML.Content;
BEGIN HALT(309);
RETURN NIL;
END Externalize;
PROCEDURE Internalize*(xml: XML.Content);
BEGIN HALT(309)
END Internalize;
PROCEDURE GetReferrencedObjects*() : PersistentObjectList;
BEGIN RETURN NIL
END GetReferrencedObjects;
END PersistentObject;
PersistentObjectList* = POINTER TO ARRAY OF PersistentObject;
PersistentObjectFactory* = PROCEDURE (): PersistentObject;
PersistentObjectDescriptor* = OBJECT
VAR
moduleName*, objectName*: Strings.String;
factory*: PersistentObjectFactory;
PROCEDURE &Init*(CONST modName, objName: ARRAY OF CHAR; factoryProc: PersistentObjectFactory);
BEGIN
NEW(moduleName, LEN(modName)); NEW(objectName, LEN(objName));
COPY(modName, moduleName^); COPY(objName, objectName^);
factory := factoryProc
END Init;
END PersistentObjectDescriptor;
PersistentObjectDescSet* = OBJECT
VAR
descriptors*: POINTER TO ARRAY OF PersistentObjectDescriptor;
PROCEDURE &Init*(CONST descs: ARRAY OF PersistentObjectDescriptor);
VAR i: LONGINT;
BEGIN
NEW(descriptors, LEN(descs));
FOR i := 0 TO LEN(descs)-1 DO
descriptors[i] := descs[i]
END
END Init;
PROCEDURE GetCount*() : LONGINT;
BEGIN
RETURN LEN(descriptors^)
END GetCount;
PROCEDURE GetItem*(i: LONGINT) : PersistentObjectDescriptor;
BEGIN
RETURN descriptors[i]
END GetItem;
END PersistentObjectDescSet;
PersistentObjectDescSetFactory = PROCEDURE() : PersistentObjectDescSet;
FilterPredicate* = PROCEDURE {DELEGATE} (obj: PersistentObject) : BOOLEAN;
PersistentObjectWrapper = OBJECT
VAR
prevalenceSystem: PrevalenceSystem;
instance: PersistentObject;
descriptor: PersistentObjectDescriptor;
savingCounter: LONGINT;
isRoot: BOOLEAN;
isMarked: BOOLEAN;
PROCEDURE &Init*(prevSys: PrevalenceSystem; obj: PersistentObject; desc: PersistentObjectDescriptor);
BEGIN
ASSERT(prevSys # NIL); ASSERT(obj # NIL); ASSERT(desc # NIL);
prevalenceSystem := prevSys;
IF (obj.oid = 0) THEN obj.oid := prevalenceSystem.GetNewOid() END;
instance := obj; descriptor := desc;
isMarked := TRUE
END Init;
END PersistentObjectWrapper;
SnapShotManager = OBJECT
VAR timer: Kernel.Timer; alive, terminated: BOOLEAN;
i: LONGINT; p: ANY; prevSys: PrevalenceSystem;
BEGIN {ACTIVE}
IF (DEBUG) THEN KernelLog.String("Prevalence System: Snapshot Manager started."); KernelLog.Ln END;
NEW(timer); alive := TRUE; terminated := FALSE;
timer.Sleep(SnapShotIntervall);
WHILE (alive) DO
prevSystemList.Lock;
FOR i := 0 TO prevSystemList.GetCount()-1 DO
p := prevSystemList.GetItem(i); prevSys := p(PrevalenceSystem);
IF (DEBUG) THEN
KernelLog.String("Prevalence System '"); KernelLog.String(prevSys.SystemName^);
KernelLog.String("': Storing a snapshot."); KernelLog.Ln
END;
prevSys.PersistAllObjects;
IF (DEBUG) THEN
KernelLog.String("Prevalence System '"); KernelLog.String(prevSys.SystemName^);
KernelLog.String("': Snapshot done."); KernelLog.Ln
END
END;
prevSystemList.Unlock;
timer.Sleep(SnapShotIntervall)
END;
IF (DEBUG) THEN KernelLog.String("Prevalence System: Snapshot Manager terminated."); KernelLog.Ln END;
terminated := TRUE;
END SnapShotManager;
TYPE PrevalenceSystem* = OBJECT
VAR
SnapShotFileName*: Strings.String;
LogFileName*: Strings.String;
SystemName*: Strings.String;
persistentObjectList: TFClasses.List;
oidCounter: LONGINT;
lockSnapShotFile: BOOLEAN;
lockLogFile: BOOLEAN;
lockPersList: BOOLEAN;
PROCEDURE &Init*(CONST name, snapShotFn, logFn: ARRAY OF CHAR);
VAR i: LONGINT; p: ANY; prevSys: PrevalenceSystem;
BEGIN
LockPrevSystemList;
prevSystemList.Lock;
FOR i := 0 TO prevSystemList.GetCount()-1 DO
p := prevSystemList.GetItem(i); prevSys := p(PrevalenceSystem);
IF ((prevSys.SystemName^ = name) OR (prevSys.SnapShotFileName^ = snapShotFn)
OR (prevSys.LogFileName^ = logFn)) THEN
prevSystemList.Unlock;
UnlockPrevSystemList;
HALT(9999)
END
END;
prevSystemList.Unlock;
NEW(SystemName, LEN(name)+1); COPY(name, SystemName^);
NEW(SnapShotFileName, LEN(snapShotFn)+1); COPY(snapShotFn, SnapShotFileName^);
NEW(LogFileName, LEN(logFn)+1); COPY(logFn, LogFileName^);
NEW(persistentObjectList); oidCounter := 1;
lockSnapShotFile := FALSE; lockLogFile := FALSE; lockPersList := FALSE;
RestoreAllObjects;
prevSystemList.Add(SELF);
UnlockPrevSystemList;
END Init;
PROCEDURE AddPersistentObject*(obj: PersistentObject; desc: PersistentObjectDescriptor);
VAR wrapper : PersistentObjectWrapper;
BEGIN
LockPersistentObjList;
IF ((desc # NIL) & (FindRegisteredDescriptor(desc.moduleName^, desc.objectName^) # NIL)) THEN
IF ((obj # NIL) & (GetRegisteredWrapper(obj) = NIL)) THEN
IF (obj.registeredAt = NIL) THEN
obj.registeredAt := SELF
ELSIF (obj.registeredAt # SELF) THEN
UnlockPersistentObjList;
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': Cannot add objects which are alreaduy registered in another prevalence system.");
KernelLog.Ln; HALT(9999)
END;
NEW(wrapper, SELF, obj, desc);
persistentObjectList.Add(wrapper);
UnlockPersistentObjList;
Log(obj)
ELSE
UnlockPersistentObjList
END
ELSE
UnlockPersistentObjList;
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': Cannot add objects with an unregistered descriptor to the prevelance system");
KernelLog.Ln; HALT(9999)
END
END AddPersistentObject;
PROCEDURE AddPersistentObjectToRootSet*(obj: PersistentObject; desc: PersistentObjectDescriptor);
VAR wrapper : PersistentObjectWrapper;
BEGIN
LockPersistentObjList;
IF ((desc # NIL) & (FindRegisteredDescriptor(desc.moduleName^, desc.objectName^) # NIL)) THEN
IF (obj # NIL) THEN
wrapper := GetRegisteredWrapper(obj);
IF (wrapper = NIL) THEN
IF (obj.registeredAt = NIL) THEN
obj.registeredAt := SELF
ELSIF (obj.registeredAt # SELF) THEN
UnlockPersistentObjList;
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': Cannot add objects which are alreaduy registered in another prevalence system.");
KernelLog.Ln; HALT(9999)
END;
NEW(wrapper, SELF, obj, desc);
wrapper.isRoot := TRUE;
persistentObjectList.Add(wrapper)
ELSE
wrapper.isRoot := TRUE
END;
UnlockPersistentObjList;
Log(obj)
END
ELSE
UnlockPersistentObjList;
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': Cannot add objects with an unregistered descriptor to the prevelance system");
KernelLog.Ln; HALT(9999)
END
END AddPersistentObjectToRootSet;
PROCEDURE RemovePersistentRootObject*(obj: PersistentObject);
VAR wrapper: PersistentObjectWrapper;
BEGIN
LockPersistentObjList;
wrapper := GetRegisteredWrapper(obj);
IF ((wrapper # NIL) & (wrapper.isRoot)) THEN
wrapper.isRoot := FALSE;
UnlockPersistentObjList;
LogRemovalFromRootSet(wrapper)
ELSE
UnlockPersistentObjList
END
END RemovePersistentRootObject;
PROCEDURE GetPersistentObject*(oid: LONGINT): PersistentObject;
VAR wrapper: PersistentObjectWrapper;
BEGIN
wrapper := GetRegisteredWrapperByOid(oid);
IF (wrapper # NIL) THEN
RETURN wrapper.instance
ELSE
RETURN NIL
END
END GetPersistentObject;
PROCEDURE GetDescriptorByObject*(obj: PersistentObject) : PersistentObjectDescriptor;
VAR wrapper: PersistentObjectWrapper;
BEGIN
wrapper := GetRegisteredWrapper(obj);
IF (wrapper # NIL) THEN
RETURN wrapper.descriptor
END
END GetDescriptorByObject;
PROCEDURE FindPersistentObjects*(pred: FilterPredicate) : PersistentObjectList;
VAR i: LONGINT; p: ANY; wrapper: PersistentObjectWrapper; obj: PersistentObject;
list: TFClasses.List; persList: PersistentObjectList;
BEGIN
NEW(list);
persistentObjectList.Lock;
FOR i := 0 TO persistentObjectList.GetCount()-1 DO
p := persistentObjectList.GetItem(i); wrapper := p(PersistentObjectWrapper);
obj := wrapper.instance;
IF (pred(obj)) THEN
list.Add(obj)
END
END;
persistentObjectList.Unlock;
IF (list.GetCount() > 0) THEN
NEW(persList, list.GetCount());
FOR i := 0 TO list.GetCount()-1 DO
p := list.GetItem(i); obj := p(PersistentObject);
persList[i] := obj
END;
RETURN persList
ELSE
RETURN NIL
END
END FindPersistentObjects;
PROCEDURE GetNewOid() : LONGINT;
BEGIN {EXCLUSIVE}
INC(oidCounter); RETURN oidCounter-1
END GetNewOid;
PROCEDURE GetXMLDocument(file: Files.File) : XML.Document;
VAR scanner: XMLScanner.Scanner; parser: XMLParser.Parser; doc: XML.Document;
reader: Files.Reader;
BEGIN
NEW(reader, file, 0);
NEW(scanner, reader);
NEW(parser, scanner);
LockParsingScanning;
scanner.reportError := ReportXMLParserScannerError;
parser.reportError := ReportXMLParserScannerError;
doc := parser.Parse();
UnlockParsingScanning;
IF (xmlParserErrorOccurred) THEN
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': "); KernelLog.String(xmlParserErrorMsg); KernelLog.Ln;
RETURN NIL
ELSE
RETURN doc
END
END GetXMLDocument;
PROCEDURE LockSnapShotFile;
BEGIN {EXCLUSIVE}
AWAIT(~lockSnapShotFile);
lockSnapShotFile := TRUE
END LockSnapShotFile;
PROCEDURE UnlockSnapShotFile;
BEGIN {EXCLUSIVE}
lockSnapShotFile := FALSE
END UnlockSnapShotFile;
PROCEDURE LockLoggingFile;
BEGIN {EXCLUSIVE}
AWAIT(~lockLogFile);
lockLogFile := TRUE
END LockLoggingFile;
PROCEDURE UnlockLoggingFile;
BEGIN {EXCLUSIVE}
lockLogFile := FALSE
END UnlockLoggingFile;
PROCEDURE LockPersistentObjList;
BEGIN {EXCLUSIVE}
AWAIT(~lockPersList);
lockPersList := TRUE
END LockPersistentObjList;
PROCEDURE UnlockPersistentObjList;
BEGIN {EXCLUSIVE}
lockPersList := FALSE
END UnlockPersistentObjList;
PROCEDURE CompactLogFile;
VAR file, newfile: Files.File; doc: XML.Document; root, elem: XML.Element; enum: XMLObjects.Enumerator;
p: ANY; oidString, savingCounterString: Strings.String; i, oid, savingCounter: LONGINT;
wrapper: PersistentObjectWrapper; removeList: TFClasses.List; fwriter: Files.Writer; writer: Streams.Writer;
elemName, rootName: Strings.String;
BEGIN
LockLoggingFile;
file := Files.Old(LogFileName^);
IF (file # NIL) THEN
newfile := Files.New(LogFileName^);
IF (newfile # NIL) THEN
NEW(removeList);
doc := GetXMLDocument(file);
IF (doc # NIL) THEN
root := doc.GetRoot();
rootName := root.GetName();
IF (rootName^ = XMLLogRootElemName) THEN
enum := root.GetContents();
WHILE (enum.HasMoreElements()) DO
p := enum.GetNext();
IF (p IS XML.Element) THEN
elem := p(XML.Element);
elemName := elem.GetName();
IF ((elemName^ = XMLInstanceElemName) OR (elemName^ = XMLLogDelInstElemName)) THEN
oidString := elem.GetAttributeValue(XMLAttrOidName);
savingCounterString := elem.GetAttributeValue(XMLAttrSavingCounter);
IF ((oidString # NIL) & (savingCounterString # NIL)) THEN
Strings.StrToInt(oidString^, oid); Strings.StrToInt(savingCounterString^, savingCounter);
wrapper := GetRegisteredWrapperByOid(oid);
IF (((wrapper # NIL) & (savingCounter < wrapper.savingCounter)) OR (wrapper = NIL)) THEN
removeList.Add(elem)
END
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': In the snapshot file '"); KernelLog.String(SnapShotFileName^);
KernelLog.String("' is an instance without oid or without saving time."); KernelLog.Ln
END
END
END
END;
FOR i := 0 TO removeList.GetCount()-1 DO
p := removeList.GetItem(i); elem := p(XML.Element);
root.RemoveContent(elem)
END;
Files.OpenWriter(fwriter, newfile, 0); writer := fwriter;
doc.Write(writer, NIL, 0);
fwriter.Update;
Files.Register(newfile);
IF (DEBUG) THEN
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': Log file compacted."); KernelLog.Ln
END
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': Cannot overwrite the log file '"); KernelLog.String(SnapShotFileName^);
KernelLog.String("' while compacting the log file."); KernelLog.Ln
END
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': In the log file '"); KernelLog.String(LogFileName^);
KernelLog.String("' must be a root defined as '"); KernelLog.String(XMLLogRootElemName);
KernelLog.String("'."); KernelLog.Ln
END;
END
END;
UnlockLoggingFile
END CompactLogFile;
PROCEDURE GarbageCollect*;
VAR i: LONGINT; pObj: ANY; wrapper: PersistentObjectWrapper; removeList: TFClasses.List;
PROCEDURE GetWrapperForObj(obj: PersistentObject) : PersistentObjectWrapper;
VAR k: LONGINT; ptr: ANY; wpr: PersistentObjectWrapper;
BEGIN
FOR k := 0 TO persistentObjectList.GetCount()-1 DO
ptr := persistentObjectList.GetItem(k); wpr := ptr(PersistentObjectWrapper);
IF (wpr.instance = obj) THEN
RETURN wpr
END
END;
RETURN NIL
END GetWrapperForObj;
PROCEDURE MarkReachableObjects(obj: PersistentObject);
VAR k: LONGINT; list: PersistentObjectList; wpr: PersistentObjectWrapper;
BEGIN
list := obj.GetReferrencedObjects();
IF (list # NIL) THEN
FOR k := 0 TO LEN(list)-1 DO
wpr := GetWrapperForObj(list[k]);
IF (wpr # NIL) THEN
IF (~wpr.isMarked) THEN
wpr.isMarked := TRUE;
MarkReachableObjects(wpr.instance)
ELSE
wpr.isMarked := TRUE
END
END
END
END
END MarkReachableObjects;
BEGIN
LockPersistentObjList;
persistentObjectList.Lock;
FOR i := 0 TO persistentObjectList.GetCount()-1
pObj := persistentObjectList.GetItem(i); wrapper := pObj(PersistentObjectWrapper);
wrapper.isMarked := FALSE
END;
FOR i := 0 TO persistentObjectList.GetCount()-1 DO
pObj := persistentObjectList.GetItem(i); wrapper := pObj(PersistentObjectWrapper);
IF (wrapper.isRoot) THEN
wrapper.isMarked := TRUE;
MarkReachableObjects(wrapper.instance)
END
END;
NEW(removeList);
FOR i := 0 TO persistentObjectList.GetCount()-1 DO
pObj := persistentObjectList.GetItem(i); wrapper := pObj(PersistentObjectWrapper);
IF (~wrapper.isMarked) THEN
IF (DEBUG) THEN
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': Garbage collector: Free object with oid "); KernelLog.Int(wrapper.instance.oid, 0); KernelLog.String(" ");
KernelLog.String(wrapper.descriptor.moduleName^); KernelLog.String("."); KernelLog.String(wrapper.descriptor.objectName^); KernelLog.Ln
END;
removeList.Add(wrapper)
END
END;
persistentObjectList.Unlock;
FOR i := 0 TO removeList.GetCount()-1 DO
pObj := removeList.GetItem(i);
persistentObjectList.Remove(pObj)
END;
UnlockPersistentObjList
END GarbageCollect;
PROCEDURE PersistAllObjects;
VAR fw: Files.Writer; w: Streams.Writer; newFile: Files.File; newRoot, elem: XML.Element;
i: LONGINT; pObj: ANY; wrapper: PersistentObjectWrapper; instance: PersistentObject;
oldDocument: XML.Document; oidCounterString: ARRAY 14 OF CHAR;
PROCEDURE GetPreviousSnapShotState(oid: LONGINT) : XML.Element;
VAR file: Files.File; oldRoot: XML.Element; enum: XMLObjects.Enumerator; pOldElem: ANY; oldElem: XML.Element;
oidValue: Strings.String; oldOid: LONGINT; oldRootName, oldElemName: Strings.String;
BEGIN
IF (oldDocument = NIL) THEN
file := Files.Old(SnapShotFileName^);
IF (file # NIL) THEN
oldDocument := GetXMLDocument(file)
END;
END;
IF (oldDocument # NIL) THEN
oldRoot := oldDocument.GetRoot();
oldRootName := oldRoot.GetName();
IF ((oldRoot # NIL) & (oldRootName^ = XMLRootElemName)) THEN
enum := oldRoot.GetContents();
WHILE (enum.HasMoreElements()) DO
pOldElem := enum.GetNext();
IF (pOldElem IS XML.Element) THEN
oldElem := pOldElem(XML.Element);
oldElemName := oldElem.GetName();
IF (oldElemName^ = XMLInstanceElemName) THEN
oidValue := oldElem.GetAttributeValue(XMLAttrOidName);
IF (oidValue # NIL) THEN
Strings.StrToInt(oidValue^, oldOid);
IF (oldOid = oid) THEN
RETURN oldElem
END
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': In the snapshot file '"); KernelLog.String(SnapShotFileName^);
KernelLog.String("' is an instance without attribute 'oid'."); KernelLog.Ln
END
END
END
END
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': In the snapshot file '"); KernelLog.String(SnapShotFileName^);
KernelLog.String("' must be a root defined as '"); KernelLog.String(XMLRootElemName);
KernelLog.String("'."); KernelLog.Ln
END
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': Could not parse the snapshot file '"); KernelLog.String(SnapShotFileName^);
KernelLog.String("' during taking a snapshot of the system."); KernelLog.Ln
END;
RETURN NIL
END GetPreviousSnapShotState;
BEGIN
oldDocument := NIL;
LockSnapShotFile;
newFile := Files.New(SnapShotFileName^);
IF (newFile # NIL) THEN
Strings.IntToStr(oidCounter, oidCounterString);
NEW(newRoot); newRoot.SetName(XMLRootElemName);
newRoot.SetAttributeValue(XMLOidCounterAttrName, oidCounterString);
GarbageCollect;
persistentObjectList.Lock;
FOR i := 0 TO persistentObjectList.GetCount()-1 DO
pObj := persistentObjectList.GetItem(i); wrapper := pObj(PersistentObjectWrapper);
IF (IsModuleLoaded(wrapper.descriptor.moduleName^)) THEN
instance := wrapper.instance;
instance.takingSnapShot := TRUE;
IF (~instance.inModification) THEN
INC(wrapper.savingCounter);
elem := GetSerializedXMLInstance(wrapper);
instance.takingSnapShot := FALSE;
newRoot.AddContent(elem)
ELSE
instance.takingSnapShot := FALSE;
elem := GetPreviousSnapShotState(instance.oid);
IF (elem # NIL) THEN
newRoot.AddContent(elem)
END
END
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': module '"); KernelLog.String(wrapper.descriptor.moduleName^);
KernelLog.String("' has been freed. Taking snapshot is no further possible, the system uses now only logging.");
snapShotMgr.alive := FALSE;
RETURN
END
END;
persistentObjectList.Unlock;
Files.OpenWriter(fw, newFile, 0); w := fw;
w.String(XMLProlog); w.Ln;
newRoot.Write(w, NIL, 0);
fw.Update;
Files.Register(newFile);
IF (DEBUG) THEN
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': Snapshot stored to "); KernelLog.String(SnapShotFileName^); KernelLog.Ln
END
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': Cannot create or overwrite file '"); KernelLog.String(SnapShotFileName^);
KernelLog.String("' for storing the snapshot."); KernelLog.Ln
END;
UnlockSnapShotFile;
CompactLogFile;
END PersistAllObjects;
PROCEDURE GetSerializedXMLInstance(wrapper: PersistentObjectWrapper) : XML.Element;
VAR content: XML.Content; elem: XML.Element; savingCounterString, oidString: ARRAY 14 OF CHAR;
container: XML.Container; instance: PersistentObject; desc: PersistentObjectDescriptor;
enum: XMLObjects.Enumerator; pChild: ANY; child: XML.Content;
BEGIN
instance := wrapper.instance;
desc := wrapper.descriptor;
content := instance.Externalize();
Strings.IntToStr(wrapper.savingCounter, savingCounterString);
Strings.IntToStr(instance.oid, oidString);
NEW(elem); elem.SetName(XMLInstanceElemName);
elem.SetAttributeValue(XMLAttrModuleName, desc.moduleName^);
elem.SetAttributeValue(XMLAttrObjectName, desc.objectName^);
elem.SetAttributeValue(XMLAttrOidName, oidString);
elem.SetAttributeValue(XMLAttrSavingCounter, savingCounterString);
IF (wrapper.isRoot) THEN
elem.SetAttributeValue(XMLAttrIsRootName, "true")
END;
IF ((content # NIL) & (content IS XML.Container) & (~(content IS XML.Element))) THEN
container := content(XML.Container);
enum := container.GetContents();
WHILE (enum.HasMoreElements()) DO
pChild := enum.GetNext(); child := pChild(XML.Content);
elem.AddContent(child)
END
ELSIF (content # NIL) THEN
elem.AddContent(content)
END;
RETURN elem
END GetSerializedXMLInstance;
PROCEDURE GetXMLInstanceDeletion(wrapper: PersistentObjectWrapper) : XML.Element;
VAR instance: PersistentObject; desc: PersistentObjectDescriptor; elem: XML.Element;
savingCounterString, oidString: ARRAY 14 OF CHAR;
BEGIN
instance := wrapper.instance;
desc := wrapper.descriptor;
Strings.IntToStr(wrapper.savingCounter, savingCounterString);
Strings.IntToStr(instance.oid, oidString);
NEW(elem); elem.SetName(XMLLogDelInstElemName);
elem.SetAttributeValue(XMLAttrModuleName, desc.moduleName^);
elem.SetAttributeValue(XMLAttrObjectName, desc.objectName^);
elem.SetAttributeValue(XMLAttrOidName, oidString);
elem.SetAttributeValue(XMLAttrSavingCounter, savingCounterString);
RETURN elem
END GetXMLInstanceDeletion;
PROCEDURE LogXMLElement(elem: XML.Element);
VAR file: Files.File; fwriter: Files.Writer; writer: Streams.Writer; endPos, endTagLength: LONGINT;
BEGIN
LockLoggingFile;
file := Files.Old(LogFileName^);
IF (file = NIL) THEN
file := Files.New(LogFileName^);
Files.Register(file)
END;
IF (file # NIL) THEN
endTagLength := Strings.Length(XMLLogRootElemName)+5;
IF (file.Length()-endTagLength-Strings.Length(XMLProlog)-2 <= 0) THEN
Files.OpenWriter(fwriter, file, 0); writer := fwriter;
writer.String(XMLProlog); writer.Ln;
writer.String("<"); writer.String(XMLLogRootElemName);
writer.String(">"); writer.Ln;
ELSE
endPos := file.Length()-endTagLength;
ASSERT(endPos >= 0, 9999);
Files.OpenWriter(fwriter, file, endPos); writer := fwriter
END;
elem.Write(writer, NIL, 0);
writer.Ln;
writer.String("</");
writer.String(XMLLogRootElemName);
writer.String(">"); writer.Ln;
writer.Update
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': Cannot open or create file '"); KernelLog.String(LogFileName^);
KernelLog.String("'."); KernelLog.Ln;
UnlockLoggingFile; HALT(9999);
END;
UnlockLoggingFile
END LogXMLElement;
PROCEDURE Log(obj: PersistentObject);
VAR elem: XML.Element; wrapper: PersistentObjectWrapper;
BEGIN
wrapper := GetRegisteredWrapper(obj);
IF (wrapper # NIL) THEN
elem := GetSerializedXMLInstance(wrapper);
LogXMLElement(elem)
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': The object with oid '"); KernelLog.Int(obj.oid, 0);
KernelLog.String("' is not stored in the prevalence system and will therefore not be logged."); KernelLog.Ln
END
END Log;
PROCEDURE LogRemovalFromRootSet(wrapper: PersistentObjectWrapper);
VAR elem: XML.Element;
BEGIN
IF (wrapper # NIL) THEN
elem := GetXMLInstanceDeletion(wrapper);
LogXMLElement(elem)
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': The object with is not stored in the prevalence system and will therefore not be logged.");
KernelLog.Ln
END
END LogRemovalFromRootSet;
PROCEDURE RestoreAllObjects;
VAR snapShotFile, logFile: Files.File; snapShotDoc, logDoc: XML.Document;
snapShotRoot, logRoot, elem: XML.Element; enum: XMLObjects.Enumerator; p: ANY;
moduleName, objectName, oidString, savingCounterString, isRootString: Strings.String;
oid, savingCounter: LONGINT; isRoot: BOOLEAN;
snapShotRootName, logRootName, elemName, oidCounterString: Strings.String;
desc: PersistentObjectDescriptor; objWrapper: PersistentObjectWrapper;
PROCEDURE CreatePersistentObject;
VAR persObj: PersistentObject; wrapper: PersistentObjectWrapper;
BEGIN
IF (desc # NIL) THEN
IF (GetPersistentObject(oid) = NIL) THEN
persObj := desc.factory();
IF (persObj # NIL) THEN
persObj.oid := oid;
NEW(wrapper, SELF, persObj, desc);
wrapper.savingCounter := savingCounter;
wrapper.isRoot := isRoot;
persistentObjectList.Add(wrapper);
persObj.registeredAt := SELF
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': cannot create an instance of the persistent object '");
KernelLog.String(objectName^); KernelLog.String("' in module '"); KernelLog.String(moduleName^);
KernelLog.String("'."); KernelLog.Ln;
HALT(9999)
END
END
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': persistent object '"); KernelLog.String(objectName^);
KernelLog.String("' in module '"); KernelLog.String(moduleName^);
KernelLog.String("' must be installed because it is stored in the snapshot or log file."); KernelLog.Ln;
HALT(9999)
END
END CreatePersistentObject;
PROCEDURE RestorePersistentObject;
VAR pContent: ANY; content: XML.Content; contentEnum: XMLObjects.Enumerator; contentList: TFClasses.List;
persObj: PersistentObject; container: XML.Container; j: LONGINT;
BEGIN
persObj := GetPersistentObject(oid);
IF (persObj # NIL) THEN
contentEnum := elem.GetContents();
NEW(contentList);
WHILE (contentEnum.HasMoreElements()) DO
pContent := contentEnum.GetNext();
contentList.Add(pContent)
END;
IF (contentList.GetCount() = 0) THEN
content := NIL
ELSIF (contentList.GetCount() = 1) THEN
pContent := contentList.GetItem(0);
content := pContent(XML.Content)
ELSE
NEW(container);
FOR j := 0 TO contentList.GetCount()-1 DO
pContent := contentList.GetItem(j); content := pContent(XML.Content);
container.AddContent(content)
END;
content := container
END;
persObj.Internalize(content);
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': Recovery process: there is no object with oid '"); KernelLog.Int(oid, 0);
KernelLog.String("' present."); KernelLog.Ln
END
END RestorePersistentObject;
PROCEDURE AllocatePersistentObjects(root: XML.Element);
VAR contentEnum: XMLObjects.Enumerator;
BEGIN
contentEnum := root.GetContents();
WHILE (contentEnum.HasMoreElements()) DO
p := contentEnum.GetNext();
IF (p IS XML.Element) THEN
elem := p(XML.Element);
elemName := elem.GetName();
IF (elemName^ = XMLInstanceElemName) THEN
moduleName := elem.GetAttributeValue(XMLAttrModuleName);
objectName := elem.GetAttributeValue(XMLAttrObjectName);
oidString := elem.GetAttributeValue(XMLAttrOidName);
savingCounterString := elem.GetAttributeValue(XMLAttrSavingCounter);
isRootString := elem.GetAttributeValue(XMLAttrIsRootName);
IF ((moduleName # NIL) & (objectName # NIL) & (oidString # NIL) & (savingCounterString # NIL)) THEN
Strings.StrToInt(oidString^, oid); Strings.StrToInt(savingCounterString^, savingCounter);
IF ((isRootString # NIL) & (isRootString^ = "true")) THEN
isRoot := TRUE
ELSE
isRoot := FALSE
END;
IF (oid >= oidCounter) THEN
oidCounter := oid + 1
END;
desc := FindRegisteredDescriptor(moduleName^, objectName^);
CreatePersistentObject
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': There are instances with missing attributes in the snapshot or log file.");
KernelLog.Ln;
UnlockLoggingFile;
UnlockSnapShotFile;
UnlockPersistentObjList;
HALT(9999)
END
END
END
END
END AllocatePersistentObjects;
BEGIN
LockPersistentObjList;
LockSnapShotFile;
LockLoggingFile;
snapShotFile := Files.Old(SnapShotFileName^);
IF (snapShotFile # NIL) THEN
snapShotDoc := GetXMLDocument(snapShotFile);
IF (snapShotDoc # NIL) THEN
snapShotRoot := snapShotDoc.GetRoot();
snapShotRootName := snapShotRoot.GetName();
IF (snapShotRootName^ = XMLRootElemName) THEN
oidCounterString := snapShotRoot.GetAttributeValue(XMLOidCounterAttrName);
IF (oidCounterString # NIL) THEN
Strings.StrToInt(oidCounterString^, oidCounter);
AllocatePersistentObjects(snapShotRoot)
ELSE
snapShotRoot := NIL;
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': In the snapshot file '"); KernelLog.String(SnapShotFileName^);
KernelLog.String("' the root '"); KernelLog.String(XMLRootElemName);
KernelLog.String("' must have an attribute named'"); KernelLog.String(XMLOidCounterAttrName);
KernelLog.String("'."); KernelLog.Ln
END
ELSE
snapShotRoot := NIL;
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': In the snapshot file '"); KernelLog.String(SnapShotFileName^);
KernelLog.String("' must be a root defined as '"); KernelLog.String(XMLRootElemName);
KernelLog.String("'."); KernelLog.Ln
END
ELSE
UnlockLoggingFile;
UnlockSnapShotFile;
UnlockPersistentObjList;
HALT(9999)
END
END;
logFile := Files.Old(LogFileName^);
IF (logFile # NIL) THEN
logDoc := GetXMLDocument(logFile);
IF (logDoc # NIL) THEN
logRoot := logDoc.GetRoot();
logRootName := logRoot.GetName();
IF (logRootName^ = XMLLogRootElemName) THEN
AllocatePersistentObjects(logRoot)
ELSE
logRoot := NIL;
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': In the log file '"); KernelLog.String(LogFileName^);
KernelLog.String("' must be a root defined as '"); KernelLog.String(XMLLogRootElemName);
KernelLog.String("'."); KernelLog.Ln
END
ELSE
UnlockLoggingFile;
UnlockSnapShotFile;
UnlockPersistentObjList;
HALT(9999)
END
END;
IF (snapShotRoot # NIL) THEN
enum := snapShotRoot.GetContents();
WHILE (enum.HasMoreElements()) DO
p := enum.GetNext();
IF (p IS XML.Element) THEN
elem := p(XML.Element);
elemName := elem.GetName();
IF (elemName^ = XMLInstanceElemName) THEN
oidString := elem.GetAttributeValue(XMLAttrOidName);
IF (oidString # NIL) THEN
Strings.StrToInt(oidString^, oid);
RestorePersistentObject
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': There are object instances with missing oid in the snapshot file.");
KernelLog.Ln
END
END
END
END;
IF (DEBUG) THEN
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': Recovery from snapshot done."); KernelLog.Ln
END
END;
IF (logRoot # NIL) THEN
enum := logRoot.GetContents();
WHILE (enum.HasMoreElements()) DO
p := enum.GetNext();
IF (p IS XML.Element) THEN
elem := p(XML.Element);
elemName := elem.GetName();
IF ((elemName^ = XMLInstanceElemName) OR (elemName^ = XMLLogDelInstElemName)) THEN
oidString := elem.GetAttributeValue(XMLAttrOidName);
savingCounterString := elem.GetAttributeValue(XMLAttrSavingCounter);
IF ((oidString # NIL) & (savingCounterString # NIL)) THEN
Strings.StrToInt(oidString^, oid); Strings.StrToInt(savingCounterString^, savingCounter);
objWrapper := GetRegisteredWrapperByOid(oid);
IF ((objWrapper # NIL) & (elemName^ = XMLInstanceElemName)) THEN
isRootString := elem.GetAttributeValue(XMLAttrIsRootName);
IF ((isRootString # NIL) & (isRootString^ = "true")) THEN
isRoot := TRUE
ELSE
isRoot := FALSE
END;
IF (savingCounter >= objWrapper.savingCounter) THEN
objWrapper.savingCounter := savingCounter;
objWrapper.isRoot := isRoot;
RestorePersistentObject
END
ELSIF ((objWrapper # NIL) & (elemName^ = XMLLogDelInstElemName)) THEN
IF (savingCounter >= objWrapper.savingCounter) THEN
objWrapper.isRoot := FALSE
END
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': Recovery phase: Object with oid '"); KernelLog.Int(oid, 0);
KernelLog.String("' is not present."); KernelLog.Ln
END
ELSE
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': There are object instances with missing oid or saving counter in the log file.");
KernelLog.Ln
END
END
END
END;
IF (DEBUG) THEN
KernelLog.String("Prevalence System '"); KernelLog.String(SystemName^);
KernelLog.String("': Recovery from log file done."); KernelLog.Ln
END
END;
UnlockLoggingFile;
UnlockSnapShotFile;
UnlockPersistentObjList
END RestoreAllObjects;
PROCEDURE GetRegisteredWrapperByOid(oid: LONGINT) : PersistentObjectWrapper;
VAR i: LONGINT; p: ANY; wrapper: PersistentObjectWrapper;
BEGIN
persistentObjectList.Lock;
FOR i := 0 TO persistentObjectList.GetCount()-1 DO
p := persistentObjectList.GetItem(i); wrapper := p(PersistentObjectWrapper);
IF (wrapper.instance.oid = oid) THEN
persistentObjectList.Unlock;
RETURN wrapper
END
END;
persistentObjectList.Unlock;
RETURN NIL
END GetRegisteredWrapperByOid;
PROCEDURE GetRegisteredWrapper(obj: PersistentObject) : PersistentObjectWrapper;
VAR i: LONGINT; p: ANY; wrapper: PersistentObjectWrapper;
BEGIN
IF (obj # NIL) THEN
persistentObjectList.Lock;
FOR i := 0 TO persistentObjectList.GetCount()-1 DO
p := persistentObjectList.GetItem(i); wrapper := p(PersistentObjectWrapper);
IF (wrapper.instance = obj) THEN
persistentObjectList.Unlock;
RETURN wrapper
END
END;
persistentObjectList.Unlock
END;
RETURN NIL
END GetRegisteredWrapper;
END PrevalenceSystem;
VAR
prevSystemList: TFClasses.List;
standardPrevalenceSystem*: PrevalenceSystem;
persistentObjectDescs: TFClasses.List;
snapShotMgr: SnapShotManager;
xmlParserErrorMsg: ARRAY 1024 OF CHAR;
xmlParserErrorOccurred: BOOLEAN;
lockParsingScanning: BOOLEAN;
lockPrevSystemList: BOOLEAN;
PROCEDURE GetPrevalenceSystem*(CONST name: ARRAY OF CHAR) : PrevalenceSystem;
VAR i: LONGINT; p: ANY; prevSys: PrevalenceSystem;
BEGIN
prevSystemList.Lock;
FOR i := 0 TO prevSystemList.GetCount()-1 DO
p := prevSystemList.GetItem(i); prevSys := p(PrevalenceSystem);
IF (prevSys.SystemName^ = name) THEN
prevSystemList.Unlock;
RETURN prevSys
END
END;
prevSystemList.Unlock;
RETURN NIL
END GetPrevalenceSystem;
PROCEDURE AddPersistentObject*(obj: PersistentObject; desc: PersistentObjectDescriptor);
BEGIN
standardPrevalenceSystem.AddPersistentObject(obj, desc)
END AddPersistentObject;
PROCEDURE AddPersistentObjectToRootSet*(obj: PersistentObject; desc: PersistentObjectDescriptor);
BEGIN
standardPrevalenceSystem.AddPersistentObjectToRootSet(obj, desc)
END AddPersistentObjectToRootSet;
PROCEDURE RemovePersistentRootObject*(obj: PersistentObject);
BEGIN
standardPrevalenceSystem.RemovePersistentRootObject(obj)
END RemovePersistentRootObject;
PROCEDURE GetPersistentObject*(oid: LONGINT): PersistentObject;
BEGIN
RETURN standardPrevalenceSystem.GetPersistentObject(oid)
END GetPersistentObject;
PROCEDURE GetDescriptorByObject*(obj: PersistentObject) : PersistentObjectDescriptor;
BEGIN
RETURN standardPrevalenceSystem.GetDescriptorByObject(obj)
END GetDescriptorByObject;
PROCEDURE FindPersistentObjects*(pred: FilterPredicate) : PersistentObjectList;
BEGIN
RETURN standardPrevalenceSystem.FindPersistentObjects(pred)
END FindPersistentObjects;
PROCEDURE LockPrevSystemList;
BEGIN {EXCLUSIVE}
AWAIT(~lockPrevSystemList);
lockPrevSystemList := TRUE
END LockPrevSystemList;
PROCEDURE UnlockPrevSystemList;
BEGIN {EXCLUSIVE}
lockPrevSystemList := FALSE
END UnlockPrevSystemList;
PROCEDURE LockParsingScanning;
BEGIN {EXCLUSIVE}
AWAIT(~lockParsingScanning);
lockParsingScanning := TRUE
END LockParsingScanning;
PROCEDURE UnlockParsingScanning;
BEGIN {EXCLUSIVE}
lockParsingScanning := FALSE
END UnlockParsingScanning;
PROCEDURE ReportXMLParserScannerError(pos, line, row: LONGINT; CONST msg: ARRAY OF CHAR);
VAR w: Streams.StringWriter;
BEGIN
xmlParserErrorOccurred := TRUE;
NEW(w, LEN(xmlParserErrorMsg));
w.String(msg); w.String(" pos "); w.Int(pos, 0);
w.String("line "); w.Int(line, 0);
w.String("row "); w.Int(row, 0); w.Ln;
w.Get(xmlParserErrorMsg)
END ReportXMLParserScannerError;
PROCEDURE IsModuleLoaded(CONST modName: ARRAY OF CHAR) : BOOLEAN;
VAR module: Modules.Module;
BEGIN
module := Modules.ModuleByName(modName);
RETURN (module # NIL)
END IsModuleLoaded;
PROCEDURE FindRegisteredDescriptor(CONST moduleName, objectName: ARRAY OF CHAR) : PersistentObjectDescriptor;
VAR p: ANY; i: LONGINT; desc: PersistentObjectDescriptor;
BEGIN
persistentObjectDescs.Lock;
FOR i := 0 TO persistentObjectDescs.GetCount()-1 DO
p := persistentObjectDescs.GetItem(i); desc := p(PersistentObjectDescriptor);
IF ((desc.moduleName^ = moduleName) & (desc.objectName^ = objectName)) THEN
persistentObjectDescs.Unlock;
RETURN desc
END
END;
persistentObjectDescs.Unlock;
RETURN NIL
END FindRegisteredDescriptor;
PROCEDURE RegisterDescriptor(desc: PersistentObjectDescriptor);
VAR pos: LONGINT;
BEGIN {EXCLUSIVE}
IF (desc # NIL) THEN
persistentObjectDescs.Lock;
pos := persistentObjectDescs.IndexOf(desc);
persistentObjectDescs.Unlock;
IF (pos = -1) THEN
persistentObjectDescs.Add(desc)
END
END
END RegisterDescriptor;
PROCEDURE ReadRegisteredModules;
VAR elem, child: XML.Element; enum: XMLObjects.Enumerator; p: ANY; childName, moduleName: Strings.String;
attr: XML.Attribute;
BEGIN
IF (Configuration.config # NIL) THEN
elem := Configuration.config.GetRoot();
elem := Configuration.GetNamedElement(elem, "Section", ConfigurationSupperSectionName);
IF (elem # NIL) THEN
elem := Configuration.GetNamedElement(elem, "Section", ConfigurationSubSectionName);
IF (elem # NIL) THEN
enum := elem.GetContents();
WHILE (enum.HasMoreElements()) DO
p := enum.GetNext();
IF (p IS XML.Element) THEN
child := p(XML.Element); childName := child.GetName();
IF (childName^ = "Setting") THEN
attr := child.GetAttribute("value");
IF (attr # NIL) THEN
moduleName := attr.GetValue();
RegisterModuleByName(moduleName)
END
END
END
END
ELSE
KernelLog.String("Prevalence System: In Configuration.XML under '");
KernelLog.String(ConfigurationSupperSectionName); KernelLog.String("' is no section '");
KernelLog.String(ConfigurationSubSectionName); KernelLog.String(" defined."); KernelLog.Ln
END
ELSE
KernelLog.String("Prevalence System: In Configuration.XML is no section '");
KernelLog.String(ConfigurationSupperSectionName); KernelLog.String("' defined."); KernelLog.Ln
END
ELSE
KernelLog.String("Prevalence System: Cannot open Configuration.XML"); KernelLog.Ln
END
END ReadRegisteredModules;
PROCEDURE RegisterModuleByName(moduleName: Strings.String);
VAR module: Modules.Module; factory : PersistentObjectDescSetFactory; i, res: LONGINT;
msg: ARRAY 1024 OF CHAR; desc: PersistentObjectDescriptor;
descList: PersistentObjectDescSet;
BEGIN
module := Modules.ThisModule(moduleName^, res, msg);
IF ((res = 0) & (module # NIL)) THEN
GETPROCEDURE(moduleName^, ProcNameGetDescriptors, factory);
IF (factory # NIL) THEN
descList := factory();
IF (descList # NIL) THEN
FOR i := 0 TO descList.GetCount()-1 DO
desc := descList.GetItem(i);
RegisterDescriptor(desc)
END
ELSE
KernelLog.String("System pervalence: Wrong result type from procedure '");
KernelLog.String(ProcNameGetDescriptors); KernelLog.String("' in module '");
KernelLog.String(moduleName^); KernelLog.String("'"); KernelLog.Ln
END
ELSE
KernelLog.String("System prevalence: Procedure '"); KernelLog.String(ProcNameGetDescriptors);
KernelLog.String("' in module '"); KernelLog.String(moduleName^); KernelLog.String("' is not present."); KernelLog.Ln
END
ELSE
KernelLog.String("System prevalence: Module '"); KernelLog.String(moduleName^);
KernelLog.String("' is not present."); KernelLog.Ln;
KernelLog.String(msg); KernelLog.Ln
END
END RegisterModuleByName;
PROCEDURE Terminator;
VAR counter: LONGINT;
BEGIN
IF (snapShotMgr # NIL) THEN
snapShotMgr.alive := FALSE;
snapShotMgr.timer.Wakeup;
counter := 0;
WHILE ((~snapShotMgr.terminated) & (counter < TermTimeout)) DO INC(counter) END
END
END Terminator;
BEGIN
NEW(persistentObjectDescs); NEW(prevSystemList);
lockParsingScanning := FALSE;
ReadRegisteredModules;
NEW(standardPrevalenceSystem, StandardPrevSystemName, StandardSnapShotFileName, StandardLogFileName);
NEW(snapShotMgr);
Modules.InstallTermHandler(Terminator)
END PrevalenceSystem.