DEFINITION MODULE DatFraUsage;
(*******************************************************************
Module DatFraUsage (Version 1.0)
Copyright (c) 1998-2006 by Andreas Fischlin and ETH Zurich.
Purpose Supports efficient data usage on behalf of
complex systems with large data requirements. It
supports selective loading and unloading of a
segment of the data, such as all data needed by a
subsystem, yet to share commonly needed data as
well. The techniques gives such a subsystem full
and efficient control over its data in a situation
where many such subsystems have to coexist.
Remarks Uses data frames. The latter are analyzed as
currently present in memory and updated according to
needs and interests. Only those data frames are
loaded which need some updating, e.g. because they
have been changed. Interest in particular data
frames can be announced by the callee by using
routines such as AnnounceDataInterest from this
module.
Programming
o Design
Andreas Fischlin 03/05/1998
o Implementation
Andreas Fischlin 03/05/1998
ETH Zurich
Systems Ecology
CHN E 35.1
Universitaetstrasse 16
8092 Zurich
SWITZERLAND
URLs:
<mailto:RAMSES@env.ethz.ch>
<http://www.sysecol.ethz.ch>
<http://www.sysecol.ethz.ch/SimSoftware/RAMSES>
Last revision of definition: 20/06/1998 AF
*******************************************************************)
FROM DMLanguage IMPORT userBase;
FROM DataFrames IMPORT ReadingFilter;
(*****************************************)
(*##### Managing Data Interests #####*)
(*****************************************)
(*===== Announcing Data Interests =====*)
TYPE
DataInterest;
VAR
noDataInterest: DataInterest; (* read only *)
PROCEDURE AnnounceDataInterest(VAR di: DataInterest);
(*
Initiates a particular data interest. An intantiation of a data
interest di is required in order to add to it particular data
frames via routine AddDFToDataInterest. Such a "package" of data
interests in a series of data frames can then be referenced, in
particular loaded, in one, simple step (see routine ReadyData).
*)
PROCEDURE DataInterestExists(di: DataInterest): BOOLEAN;
(*
Returns wether data interest di currently exists, i.e. has been
announced lately by a call to AnnounceDataInterest.
*)
PROCEDURE AddDFToDataInterest(di: DataInterest; dfIdent: ARRAY OF CHAR);
(*
Adds your interest in the data of the data frame denoted by the
name dfIdent to the data interest package di. As a consequence
when calling ReadyData (see below), a loading process will be
triggered as soon as that particular data frame is not in memory
or has changed since last use via di. Note, AddDFToDataInterest
can be called repeatedly for the same dfIdent without triggering
error messages. See also explanations of formal parameter
autoExtendInterest of procedure SetDataInterestKind for handy
alternatives to calls to AddDFToDataInterest.
*)
(*===== Denaouncing Data Interests =====*)
PROCEDURE DelDFInDataInterest(di: DataInterest; dfIdent: ARRAY OF CHAR);
(*
Reverts the effect of AddDFToDataInterest by removing your
interest in the data frame of name dfIdent from di.
*)
PROCEDURE DenounceDataInterest(VAR di: DataInterest);
(*
Reverts the effect of AnnounceDataInterest by denouncing your
interest in the data package di. Of course it also implicitely
discards all your interests in particular data frames you have
announced by calling AddDFToDataInterest.
*)
(**************************************************)
(*##### Data Insterest Specific Settings #####*)
(**************************************************)
(*===== Auto Data Interest =====*)
PROCEDURE SetDataInterestKind(di: DataInterest; autoExtendInterest: BOOLEAN);
PROCEDURE GetDataInterestKind(di: DataInterest; VAR autoExtendInterest: BOOLEAN);
(*
It may convenient to let this module extend your data interest
automatically during the loading process (see routine ReadyData).
If autoExtendInterest is TRUE for the data interest di, any data
frame encountered during the loading process is automatically
added to the data interest (like if you would have called
AddDFToDataInterest). The advantage of this method is that you
don't need to know ahead all names of the data frames involved in
a particular data interest.
*)
(*===== Reading Filters =====*)
PROCEDURE SetDataInterestReadFilters(di: DataInterest;
minLoadFilter,maxLoadFilter,
minSharedFilter, maxSharedFilter: ReadingFilter);
PROCEDURE GetDataInterestReadFilters(di: DataInterest;
VAR minLoadFilter,maxLoadFilter,
minSharedFilter, maxSharedFilter: ReadingFilter);
(*
Loading data interest di occurrs with reading filter range
[minLoadFilter..maxLoadFilter] (cf. module DataFrames) if only
data frames in non-shared mode are to be loaded (see routines
ReadyData and SetDFInterestKind). In case at least one shared
data frame is involved in the loading process, instead the filter
range [minSharedFilter..maxSharedFilter] is used to load data
into memory. If this routine is never called for di, loading by
ReadyData is done with the default filter range
[minFilter..maxFilter] available from module DataFrames.
*)
(**********************************************)
(*##### Data Frame Specific Settings #####*)
(**********************************************)
PROCEDURE SetDFInterestKind(di: DataInterest; dfIdent: ARRAY OF CHAR;
shared: BOOLEAN);
PROCEDURE GetDFInterestKind(di: DataInterest; dfIdent: ARRAY OF CHAR;
VAR shared: BOOLEAN);
(*
Above routine tell this module that a particular data
frame denoted by 'dfIdent' contains shared data. This
means that the data interest is not an exclusive one and
that the callee is willing to accept the data in the given
data frame, regardless who has actually loaded them. Such
a use is called a shared data use.
Note, that by default, i.e. without calling routine
SetDFInterestKind, it is assumed that the data interest is
exclusive. Consequently, in such a non-shared data use mode, it is
not tolerated, that another callee of ReadyData has loaded the data
frame. For instance, in a non-shared mode, ReadyData reloads the
data, despite the fact that they might already be in memory, since
the callee has never loaded them herself. The latter behvarior is
in general needed to have proper control over data, since the
presence of a data frame in memory is not a sufficient condition to
know that its data are actually the wanted ones (it is not
sufficient because data frames can be loaded along practically
infinite path-ways, due to filtering and the use of different
anchors, see also module DataFrames). The disadvantage of the
non-shared mode is that in case of actually shared data, the same
data would be relaoded each time by each callee, who is interested
in them and wants to use the data. To avoid the resulting
inefficiency, you should declare your interest in such data frames
containing shared data as shared by calling SetDFInterestKind with
shared = TRUE.
Finally note, when a data interest contains at least one
shared data frame, and that data frame triggers a need to
reload the data interest, the loading does not necessary use
the same reading filters, but uses the filtering range
[minSharedFilter..maxSharedFilter] (cf. routine
SetDataInterestReadFilters).
*)
(**********************************************)
(*##### Readying and Discarding Data #####*)
(**********************************************)
PROCEDURE LoadDataFramesWithDlg( prompt: ARRAY OF CHAR;
fromFilter, tillFilter: ReadingFilter;
VAR startOnFileWithName: ARRAY OF CHAR;
VAR resCode: INTEGER);
(*
Same as LoadDataFrames from module DataFrames, but always
offers a file selection dialog explaining the user via the
prompt what needs to be done. startOnFileWithName returns
path and filename of the file which has been selected or
the empty string if the user cancelled the dialog. For
all other arguments see comments on procedure
LoadDataFrames from module DataFrames.
*)
PROCEDURE ReadyData(di: DataInterest; overWriteAll: BOOLEAN;
anchor: ARRAY OF CHAR;
VAR isready, newData: BOOLEAN;
VAR resCode: INTEGER);
(*
Core routine of this module which loads any data frames for which
interest has been announced into memory as intelligently as
possible. If flag overWriteAll is TRUE, loading takes place
unconditionally; otherwise, loading occurrs only conditionally,
i.e. either when the needed data frames have never been loaded
or if they have been changed since last loading. If loading is
necessary, it occurrs starting from anchor file 'anchor'.
ReadyData returns in isready whether the loading process has been
completed successfully and all data frames in which interest has
been announced are now ready in memory for retrieval. Parameter
newData returns wether the data have actually changed since last
use, i.e. are new, and consequently indicateds the need to
actually (re)assign the data to models and model objects. The
main purpose of this all is to avoid unnecessary reloading of
large data files and to avoid unnecessary, lengthy recalculations
during assigning data to model objects, for instance, such as
matrix inversions during computation of initial conditions of a
model etc. Finally note, if the data interest di is set to
autoExtendInterest = TRUE (see routine SetDataInterestKind),
all data frames which are loaded are automatically added to the
data interest di, as if you would have called AddDFToDataInterest
yourself (happens only if the data frame has not been added to di
previously). Any subsequent ReadyData call will then operate on
the extended data interest, unless you call DiscardData (see
below).
*)
PROCEDURE DiscardData(di: DataInterest; sharedToo: BOOLEAN);
(*
Core routine of this module which discards selectively all data
associated with the data interest di (calls DropDataFrame from
module DatFraAux). This routine is typically called in response
to a request by a master to reload and reassign all data in
control by the callee prior to a call to procedure ReadyData.
Parameter sharedToo determines wether shared data frames (see
routine SetDFInterestKind) are to be skipped from the dropping or
discarded as well. Finally note, for any data frames
automatically added due to autoExtendInterest (see routine
SetDataInterestKind) DiscardData calls internally
DelDFInDataInterest. Thus, as a result the data interest di is
shrinked to its original state it was after the last, explicit
declaration made by the callee by calls to AnnounceDataInterest,
and to AddDFToDataInterest.
*)
(********************************)
(*##### Error Messages #####*)
(********************************)
CONST
dfUsageMsgOffset = userBase + 240; (* constants used for resCode *)
dfUsageMsgMaxCode = dfUsageMsgOffset + 10-1;
(* Values in range [dfUsageMsgOffset..dfUsageMsgOffset] are reserved *)
tooManyDFIdents = dfUsageMsgOffset + 0; (* only internally used *)
couldntLoadDF = dfUsageMsgOffset + 1; (* insert Δ (=306C) - data frame's identifier *)
unknownDatInt = dfUsageMsgOffset + 2; (* insert Δ (=306C) - empty *)
unknownDatIntWhile = dfUsageMsgOffset + 3; (* inserts Δ (=306C) - operation, data frame's identifier *)
datIntDefTwice = dfUsageMsgOffset + 4; (* insert Δ (=306C) - empty *)
dFIntDefTwice = dfUsageMsgOffset + 5; (* insert Δ (=306C) - data frame's identifier *)
undknownDFInterest = dfUsageMsgOffset + 6; (* insert Δ (=306C) - data frame's identifier *)
missingDataFrame = dfUsageMsgOffset + 7; (* insert Δ (=306C) - data frame's identifier *)
PROCEDURE GetDFUErrMsg( msgnr: INTEGER; VAR msg: ARRAY OF CHAR );
(*
Returns error messages for the entire data fram package.
*)
END DatFraUsage.