Modeling Agent-based Applications with LTSA - February 13, 2001
←
→
Page content transcription
If your browser does not render page correctly, please read the page content below
Modeling Agent-based
Applications with LTSA
- February 13, 2001C3DS Report - A3 & LTSA
This document describes an example application built with the
C3DS Agent platform. The application is a data-flow centered
distributed service that transforms raw text files into an HTML
format. The example application is used to illustrate the
construction and modeling of a C3DS agent-based application
rather than to give a real world application of agent technology.
The primary objective of this report is to investigate the issues
involved in model checking A3 systems.
The document is divided into 3 sections:
• Section 1 presents the application and its functional
decomposition
• Section 2 details the operation of each agent-based
software component.
• Section 3 presents the model of each component and the
overall application using LTSA.
• Section 4 evaluates the modeling approach and presents
some conclusions
1 The Format converter Application
The goal of this example is to design and model a C3DS agent-based application which goal is to
read continuously files in order to convert them into another format. We will consider input files as
raw text files that will be converted into HTML files, following some simple rules.
The conversion process will follow the following steps:
1. Periodic reading of an input file,
2. Each line of the input file is sent to conversion components,
3. Each line is analyzed in order to determine what the conversion should be,
4. Lines are transformed according to configurable rules,
5. The converted file (a new file) is written to disk and signaled as done.
The design and implementation approach of the C3DS development environment is used for this
application: each functionally related software is grouped into a component, and C3DS agents are
used as the distributed object technology. The application is described through the C3DS Architecture
Description Language and the behavior of software components is defined and analyzed using the
LTSA syntax.
1.1 Overview of the Application and decomposition Principles
The application is designed with a small set of components. Each of these can be configured and
assembled to form a particular version of the application – also called a configuration. The individual
components are:
February 13, 2001 - 2 -C3DS Report - A3 & LTSA
1. FileMonitor in charge of controlling and reading the input file, in order to distribute lines to
the transformation process
2. OutputAgent, in charge of creating a new file from the transformed lines
3. FilterAgent in charge of matching the content of the lines according to a pattern matching
expression
4. TranformerAgent in charge of converting a line to another format
2 Components of the Converter Application
In this section, we will detail each of the software components that are currently implemented with
Agents. All components are thus following the implementation rules of agent-based applications:
interactions are asynchronous, communications are reliable and individual components are
recoverable – while the application recovery must be carefully examined -.
2.1 FileMonitor
This component has two output services : lineListener transfers lines for transformation and control
information for the final FileWriter ; fileControlListener transmits notification for the control of the
reading of the raw file. FileMonitor has also configurable properties that can be set at design stage,
deployment time or runtime.
lineListener : sends LineNotification or
LineCtrlNotification
fileControlListener :
sends FileControlNotification
FileMonitor :
Reacts to FileControlNotification for the
control of the file
Reacts to Condition when activated by the
Scheduler
rawFileName : raw file name
streamingWindow : nb of lines simultaneously sent
pollingPeriod : period in between two transformations of raw
file
Figure 1. FileMonitor component
February 13, 2001 - 3 -C3DS Report - A3 & LTSA
The FileMonitor component internal and interaction behavior can be modeled as the following state
machine. Transitions from one state to another can fired because of an internal event or because of an
external notification.
ScheduleEvent Initial Restarting
(to Scheduler)
Initial Recovery
Condition LineCtrlNotification State State State
(from Scheduler) [RESTART] to lineListener
Notification
Start sending
Reaction to
FileControlNotification
Notification
[OPEN]
Nb of notifications depending on the Internal state
Open value of streamingWindow transition
LineNotification
LineNotification
LineNotification
LineNotification
(to lineListenerRole)
Role) External state
LineNotification
(to lineListener
LineNotification
FileControlNotification (to(to lineListener
lineListener Role)
Role) transition because
[READNEXT] (to(to lineListener
lineListener Role)
Role) of Notifications
Read LineCtrlNotification
lines [SYNC] to lineListener
FileControlNotification
[CLOSE]
Close
LineCtrlNotification
[FLUSH]
ScheduleEvent
(to Scheduler)
Figure 2. File Monitor state machine
The state machine starts at the Initial State, whenever the FileMonitor component is deployed for the
first time. Initial state change will be fired by an external event from the Scheduling service so that the
reading process of the initial raw file starts, line by line. Eventually, the component signals through
the transformation chain some control information associated to the flow of lines, like syncing the
output files can be done or stopping the writing of the output file. An additional state is also provided
in case of a recovery, i.e. a fault has occurred and the component is restarted. Then of line control
notification signals that the process of reading the raw file is restarted.
2.2 OutputAgent
This component receives lines in order to write them into the output file. The output file will contain
the final transformation of lines. Additionally, the OutputAgent can reacts to LineCtrlNotification in order
to apply some actions on the final file itself: syncing previous writing so that even though a fault
might occur, some partial results are stored on disk ; flushing all current lines and closing the output
file because the transformation process has finished ; restarting the current writing process because
some fault has occurred.
February 13, 2001 - 4 -C3DS Report - A3 & LTSA
OutputAgent : Properties :
Reacts to LineNotification when receiving OutputFileName : name of the
lines output file
Reacts to LineCtrlNotification for the
control of the ouput to a file
Figure 3. OutputAgent Component
The Output component use the following state machine as the specification of its behavior. Lines
received are written one by one into the output file. Sometimes, a syncing can be required, file a Flush
command asks for the termination of the writing into the output file. A restart command may stop the
current writing in order to start a new writing process without keeping the non finished output file.
Initial Recovery
LineNotification LineCtrlNotification
[RESTART]
Open
Initial Recovery
State State State
LineNotification LineCtrlNotification
LineCtrlNotification
LineCtrlNotification
[SYNC]
[SYNC]
[SYNC]
Write Sync Notification
lines file sending
LineCtrlNotification
LineCtrlNotification
LineCtrlNotification
LineCtrlNotification
[FLUSH] Reaction to
[FLUSH]
[FLUSH] Notification
[FLUSH]
Close
Internal state
file
transition
External state
transition because
of Notifications
Figure 4. OutputAgent state machine
February 13, 2001 - 5 -C3DS Report - A3 & LTSA
2.3 Filter Agent
The FilterAgent is able to receive lines through its input service. Lines are then matched according to
the pattern defined in the filterExp property. If the line matches the expression, it is then send through
the acceptListener output service, otherwise it is transmitted through the rejectListener. If a
LineCtrlNotification is received, it is sent on both output services, either acceptListener and rejectListener.
This behavior enables to flush all communications channels of LineNotification in order to take an action
on the final output file.
acceptListener : sends line if matched
rejectListener : sends line if not matched
FilterAgent :
Reacts to LineNotification when receiving
lines
Reacts to LineCtrlNotification for the
control of the ouput to a file
Properties :
filterExp : pattern matching expression
Figure 5. FilterAgent Component
The FilterAgent behaves following the below state machine. The component is receiving lines, and
sends it back to an external component with one of its two output service.
Initial Recovery
Initial Recovery State State State
LineCtrlNotification
or
Notification
LineNotification
sending
Matching Reaction to
Notification
2 LineCtrlNotifications
or Internal state
LineNotification transition
External state
transition because
of Notifications
February 13, 2001 - 6 -C3DS Report - A3 & LTSA
Figure 6. FilterAgent state machine
2.4 Transformer Agent
The final agent of this application is a transformer. It takes a line as an input and format the line into a
valid HTML line. The new line is build using properties containing the string to be inserted before the
line and the string to be inserted after. Then the line is transmitted to the lineListener output service.
LineCtrlNotification don’t affect the component, they are just retransmitted to the output service.
lineListener : sends transformed line or
LineCtrlNotification
TransformerAgent :
Reacts to LineNotification when receiving
lines
Reacts to LineCtrlNotification for the
control of the ouput to a file
Properties :
header : initial string to be inserted
footer: string to be inserted at end of the line
Figure 7. TransformerAgent Component
Initial Recovery
Initial Recovery State State State
LineCtrlNotification
or
Notification
LineNotification
sending
Transfor
Reaction to
ming Notification
LineCtrlNotification
or Internal state
LineNotification transition
External state
transition because
of Notifications
February 13, 2001 - 7 -C3DS Report - A3 & LTSA
Figure 8. TransformerAgent state machine
2.5 An example Configuration using XOlan
The following figure shows an example configuration. This application uses component FileMonitor to
read a raw text file. Each line of this file is then transferred to a set of filtering component, which
according to a pattern matching expression, sends the line to TransformerAgent in order to produce an
HTML formatted line. The transformed lines are then send, one by one, to the OutputAgent which stores
the HTML text into a new file on disk.
lineListener : sends LineNotification
fileControlListener :
sends FileControlNotification to itself
Figure 9. Example Configuration of a Transformer
February 13, 2001 - 8 -C3DS Report - A3 & LTSA
3 Modeling Agents with LTSA
This section presents a model of the A3 Format Converter example presented in the preceding
sections using the LTSA modeling tools. The objective is to investigate the feasibility of modeling
and checking the behavior of A3 systems. The difficulty that is addressed is the large state spaces of
systems such as A3 that utilize asynchronous communication. Some tactics and techniques for
ameliorating the problem are discussed in the context of the example system.
3.1 Modeling Communication in A3
Agent interaction in A3 is provided by a communication system that supports asynchronous causally
ordered reliable message communication. Once a send operation is complete, a message is stable with
respect to failures. The A3 preserves ordering properties using a matrix clock mechanism. For
modeling purposes, it is sufficient to consider the communication system as a single queue that
imposes FIFO order on all inter-agent communication. The LTSA model of the system of Figure 9 is
depicted diagrammatically in Figure 10 below.
send recv
o[3] t[3]
TRANSFORMER
o[2] t[2]
TRANSFORMER
o[1] t[1]
TRANSFORMER
t[1],t[2] h[2]
FILTER
h[2],t[1] h[1]
FILTER
fm
QUEUE
FILEMONITOR h[1] o[1],o[2],o[3] OUTPUTAGENT
Figure 10 – Model Structure of Format Converter Example
Figure 10 is labelled with the destination to which messages are sent and from which they are
received. Thus the first filter agent receives messages from the label “h[1]” which is the label to which
the FILEMONITOR sends lines. Thus, communication in Figure 10 is structured exactly as specified
by the configuration of Figure 9.
February 13, 2001 - 9 -C3DS Report - A3 & LTSA
The structure of Figure 10 is encoded in the LTSA input language FSP by the parallel composition of
the processes representing the agents in the system and the composite QUEUE process representing
the A3 communication system. The configuration for the example system is thus:
||CONVERTER
= ( FILEMONITOR(’h[1])
|| FILTER(’h[1],’t[1],’h[2])
|| FILTER(’h[2],’t[2],’t[3])
|| TRANSFORMER(’t[1],’o[1])
|| TRANSFORMER(’t[2],’o[2])
|| TRANSFORMER(’t[3],’o[3])
|| OUTPUTAGENT(’o,3)
|| QUEUE(7)
).
QUEUE model
The QUEUE is modeled as a composition of ELEMENT processes, each of which can buffer a single
message. We must specify the maximum capacity of the QUEUE to ensure a finite sized model. We
will see later how to check whether the QUEUE has sufficient capacity for the application in which it
is placed. A message placed in the QUEUE consists of the destination address for the message and the
data contents it carries. We abstract from the detailed contents of messages in the actual system and
represent a message as carrying either a line number or a “flush” control.
const Max = 2
range LineNo = 1..Max
set Dest = {h[1..2],t[1..3],o[1..3]} // Message destinations
set Message = {[Dest][{[LineNo],flush}]}
ELEMENT = (send[m:Message] -> recv[m] -> ELEMENT).
||QUEUE(N=5) = (q[1..N]:ELEMENT)/{
forall[i:1..N-1]{q[i].recv/q[i+1].send},
send/q[1].send,
recv/q[N].recv}.
Although the model of the QUEUE is succinctly specified, it can lead to intractably large models if
care is not taken. For example, with a range of only two line numbers and five buffer slots in the
queue, composition leads to a process with approximately 4 * 106 states. We will see that we can
avoid explicitly building QUEUE and as a result deal with much larger systems.
The implementation of the A3 communication system ensures that messages once entered in the
communication system are stable and are not lost either as a result of link or node failure. We model
this by the simple expedient of not including failure action in the alphabet of the QUEUE process –
i.e. failures do not modify the state of the queue.
February 13, 2001 - 10 -C3DS Report - A3 & LTSA
3.2 Modeling A3 Agents
In the following, we present the FSP behavioral specifications for each of the agent types
FILEMONITOR, FILTER, TRANSFORMER and OUTPUT AGENT. We have not introduced a
separate model for the Paragraph agent of Figure 9 since its abstract behavior is the same as
TRANSFORMER. In section 2, the behavior of each agent component was described using an
informal state machine diagram. It is simple to translate this description into an FSP process.
FILTER agent model
The FSP model for this agent is listed below:
FILTER(I=’h,O1=’o1,O2=’o2)
= (recv[I][i:LineNo]->
(match -> send[O1][i] -> FILTER
|match -> send[O2][i] -> FILTER
)
|recv[I].flush -> send[O1].flush -> send[O2].flush -> end -> FILTER
)\{match}.
The process abstracts the matching operation on lines made by a filter as a non-deterministic choice
that decides whether a line is output to O1 or O2. A “flush” control message is sent to both outputs.
The Labeled Transition System below is an instantiation of the FILTER model with a single line
number and outputs to “t[1]” and “h[2]”.
recv.h[1][1]
tau
recv.h[1].flush send.t[1].flush send.h[2].flush tau
FILTER(h.1,t.1,h.2)
0 1 2 3 4 5 6
end
send.h[2][1]
send.t[1][1]
February 13, 2001 - 11 -C3DS Report - A3 & LTSA
Modeling Failure
We now examine, how to model failure in A3 systems using FILTER as an example. The A3 platform
ensures that in the presence of failures, either one of two outcomes is possible for an agent execution.
A message that is being processed by an agent is only removed from the communication system when
the output messages that result from processing that message are safely committed to the
communication system. If an agent fails before committing its outputs, then the input message
remains in the queue. Consequently, the two outcomes are that either a received message is
successfully processed or the state of the system remains at the state it was in before the failed
execution started. In essence, agent execution is atomic with respect to failures, either it completes or
has no effect. To model the failure of FILTER we add the actions “fail” and “restart” as shown below:
FILTER(I=’h,O1=’o1,O2=’o2)
= (recv[I][i:LineNo]->
(match -> send[O1][i] -> FILTER
|match -> send[O2][i] -> FILTER
)
|recv[I].flush -> send[O1].flush -> send[O2].flush -> end -> FILTER
|fail -> FAILED
),
FAILED
= (restart -> FILTER)\{match}.
To model the atomic failure of FILTER, the “fail” action is only enabled before (and after) a message
is received and the corresponding outputs sent. We can regard the “fail” and “restart” actions as
internal to FILTER. If we do so and minimize, the resulting process is exactly equivalent to the
previous version of FILTER in which we took no account of failures. In other words, the A3 platform
makes failure transparent.
If we make the restart action external, i.e. controlled by some other part of the system, the only effect
is to stop the FILTER process receiving and sending messages until the restart action occurs. Because
of the A3 communication semantics – which we modeled as a queue – if the filter process was about
to process a message and fails, no other process can proceed until the filter succeeds in removing its
input message from the queue and the next message becomes available. In other words, failure only
affects the speed with which an agent executes. Since the LTS behavioral model abstracts from
execution speed, including failure actions in line with A3 implementation semantics has no effect on
the overall application behavior. Consequently, we can safely omit consideration of failure in
modeling the remaining agents.
February 13, 2001 - 12 -C3DS Report - A3 & LTSA
FILEMONITOR agent model
The FILEMONITOR agent once started send a message to itself to read the first line of the logfile. On
receiving this message, the agent reads a line from the log file and then sends the line to its output
together with a message to read the next line. When the last line has been read, the agent sends a flush
message to itself and on receiving it sends it on to the output. We have abstracted all the file control
operations into the “flush” message.
FILEMONITOR(O=’o) = OPEN,
OPEN = (send.fm[1] -> READ),
READ = (recv.fm[i:1..Max-1] -> read[i] -> send[O][i] -> send.fm[i+1] ->READ
|recv.fm[Max] -> read[Max] -> send[O][Max] -> send.fm.flush ->READ
|recv.fm.flush -> send[O].flush -> CLOSE
),
CLOSE = (end -> OPEN).
Note that since we are interested only in modeling interaction the addition of additional actions to
represent opening and closing have been omitted in the interests of making the model compact.
It should also be noted that as with FILTER, FILEMONITOR has no persistent state. The line number
it has reached is made persistent by storing it as a message in QUEUE which as discussed previously
enables messages to survive crashes.
TRANSFORMER agent model
The TRANSFORMER agent since we have abstracted from the date contained in each line simply
reacts to receiving a message on its input by sending the same message to its output:
TRANSFORMER(I=’inp,O=’outp)
= (recv[I][i:LineNo]->send[O][i] -> TRANSFORMER
|recv[I].flush ->send[O].flush -> end -> TRANSFORMER
).
OUTPUTAGENT model
The OUTPUTAGENT writes lines in the messages it receives. The file is closed when the agent
receives a flush message from each of the transformer agents that sends to it, since it then knows that
there are no more lines in the communication system queue.
OUTPUTAGENT(I=’inp,N=3)
= OPEN[3],
OPEN[c:1..3]
= (recv[I][1..N][i:LineNo] -> write[i] ->OPEN[c]
|recv[I][1..N].flush -> if c>1 then OPEN[c-1] else CLOSE
),
CLOSE = (end -> OUTPUTAGENT).
February 13, 2001 - 13 -C3DS Report - A3 & LTSA
3.3 Analysis
The first analysis that is performed is a general check for deadlock and for progress violations. A
progress violation would mean that the system has some internal cyclic behavior. The overall system
behavior has been specified as a major cycle in which the “end” action signals that a logfile has been
both read and written. Both of these analyses reveal no problem. The reachable state spaces for a
range of model parameters are:
Logfile lines QUEUE buffers Reachable States
2 5 63544
2 6 123328
2 7 223422
3 6 1256531
3 7 2533306
Reachable State Space for CONVERTER model
Note that we have avoided the intermediate state space explosion that would have occurred if we had
explicitly constructed the QUEUE process. As discussed in section 3.1, this would have required us
for the smallest system with only 2 lines and 5 buffers to store a process with 4,000,000 states when
the final state space is 63544. The reduction occurs because only a subset of the possible queue states
are reachable when we compose it with the agent processes and consequently it is not sensible to
explicitly construct the queue. However, it is noticeable that the state space doubles with each
additional buffer.
State Space Reduction using Action priority
The normal state space reduction technique used in LTSA is to compose sub-components of the
model and then minimize these sub-components using observational equivalence – this is known as
Compositional Reachability Analysis. However, as pointed out in the above, it is not sensible to build
an explicit queue, since all of its states are not reachable. As a result, we are left with the internal
states and transitions of QUEUE that increase the size of the model. We can address this problem by
removing some of these unnecessary states and transitions by a partial order reduction using action
priority. Instead of the original CONVERTER system, we can analyze the system:
||PCONVERTER = CONVERTER >>{send,recv}.
This gives internal queue actions priority over send and receive actions and substantially reduces the
overall state space as shown in the table below. The reason why this system is behaviorally equivalent
to the original system is beyond the scope of this report.
Logfile lines QUEUE buffers Reachable States
2 5 28207
2 6 33427
2 7 38647
3 6 360930
3 7 414462
Reachable State Space for PCONVERTER model
February 13, 2001 - 14 -C3DS Report - A3 & LTSA
Communication buffers
An interesting question about the example system is – precisely how many buffers are required. To
ascertain this property, we use a property that asserts that the number of outstanding buffers is less
than some constant CB:
property
BUFFER_OVERFLOW(CB=1) = B[0],
B[i:0..CB] = (send[Message] -> B[i+1]
|recv[Message] -> B[i-1]
).
If the number of buffers required exceeds CB then analysis detects a violation of the property
BUFFER_OVERFLOW. Using this, we can show that the number of buffers required by the system is
exactly Max + 3 where Max is the number of lines in the logfile.
Write Order
Does the example system write lines to the output file in the same order that they where read from the
logfile? The following property asserts that write actions occurs in line number order:
property
ORDER = ORDER[1],
ORDER[i:LineNo] = (write[i] -> ORDER[i+1]),
ORDER[Max+1] = (end->ORDER).
In fact the Converter application does not preserve this property:
// internal QUEUE actions q… have been elided
Trace to property violation in ORDER:
send.fm.1 // FILEMONITOR send message to start reading file
recv.fm.1
read.1
send.h.1.1 // line 1 sent to filter 1
send.fm.2
recv.h.1.1 // line 1 received by filter 1
tau
recv.fm.2
read.2
send.h.1.2 // line 2 sent to filter 1
send.h.2.1 // filter 1 sends line 1 to filter 2
recv.h.1.2 // line 2 received by filter 1
tau
send.t.1.2 // filter 1 sends line 2 to transformer 1
recv.h.2.1 // line 1 received by filter 2
tau
recv.t.1.2 // line 2 received by transformer 1
send.o.1.2 // transformer 1 sends line 2 to output agent
recv.o.1.2 // line 2 received output agent
write.2 // line 2 written first !
Analysed in: 60ms
February 13, 2001 - 15 -C3DS Report - A3 & LTSA
The property that is preserved with respect to writing is that all lines are written to the output file
before the “end” action occurs:
property
WRITEALL = W[0],
W[c:0..Max-1] = (write[LineNo] -> W[c+1]),
W[Max] = (end->WRITEALL).
We can assert that the action “end” always eventually occurs by means of the progress property:
progress ALWAYS_END = {end}
The model satisfies this progress property.
____________________________________________
February 13, 2001 - 16 -C3DS Report - A3 & LTSA 4 Conclusion We have successfully modeled the example Convertor system and determined some interesting properties of the system. The overall model structure and the techniques used are generally applicable to A3 systems. As with all model-checking endeavors, the actual program must be abstracted to achieve tractable models. In the example, we abstracted the details of line transformation and concentrated on agent interaction. Characteristic of behavior modeling and analysis is the need to reduce the size of the problem being modeled. We achieved this by considering logfiles with small numbers of lines. Naïve or inexperienced readers will consider this an insurmountable objection to the applicability of tools such as LTSA. In fact, using large logfiles adds little or no additional information to the model and we needed only two lines to investigate all the properties of interest. We where able to determine the precise number of buffers required by the system and using a larger number again does not add to the information we can extract from the model. A more serious problem is that it is difficult to automatically translate an A3 system into a tractable behavior model. The mechanical translation from C3DS workflow notation to model is feasible as reported earlier in the project. This difficult arises for two reasons: firstly A3 agents are at the level of program units with all the attendant implementation detail while workflow descriptions are abstract control flow specifications, and secondly, as discussed in the previous section, A3 asynchronous communication requires careful treatment. Asynchronous communication has another impact on the applicability of modeling tools such as LTSA to A3. With workflow, we were able to use Compositional Reachability Analysis (CRA) such that when the properties of a workflow system had been investigated, we could minimize it with respect to interface actions and use the result in as a component in a larger system. In this way, we could deal with large systems. Systems such as A3 using asynchronous communication are more amenable to “on-the-fly” analysis using partial order reduction to ameliorate the state space explosion caused by asynchronous communication queues. However this form of analysis, while supported by LTSA in addition to CRA, does not have the desirable compositional property. In conclusion, while it is reasonable to automate analysis of workflow descriptions using model checking tools such as LTSA, the same cannot be said of A3 systems. The place of behavior modeling with respect to A3 is at the design phase where it can be focused on critical parts of a system and used to determine problem areas in advance of implementation. A3 configuration diagrams can be used to mechanical generate the structure of the model, however, again it is likely that abstraction and problem size reduction will be required. For example, modeling a system with two or three filters rather than hundreds. Finally, we believe a significant outcome of this work is the use of action priority to reduce state- space as outlined in the previous section. We believe this is both novel and shows the promise of more general application. February 13, 2001 - 17 -
C3DS Report - A3 & LTSA
Appendix – Agents source Code
Source Code of a simplified FileMonitor
import fr.dyade.aaa.agent.*;
import java.io.*;
import java.util.*;
import fr.dyade.aaa.task.*;
/**
* Cette classe contrôle la lecture de lignes depuis un fichier
* Ce fichier contient des lignes de texte séparées par un retour chariot
* Chaque ligne est ensuite transmise à l'extérieur pour être utilisée
* L'Agent FileMonitor s'auto alimente avec des notifications permettant
* de passer à la lecture de la ligne suivante d'un fichier.
*
* @author Luc Bellissard
* @version v1.0
*/
public class FileMonitor extends Agent {
private static final boolean DEBUG = false;
/**
* propriété contenant le nom du fichier devant être
* tranformé
**/
public String rawFileName = null;
/**
* propriété entière indiquant le nombre de lignes envoyés bout à bout
**/
public int streamingWindow = 4; // no of line sent each time
/**
* propriété contenant la période de vérification de la présence d'un
* nouveau fichier, période en millisecondes
**/
public int pollingPeriod=15000;
/** Attribut privé non configurable **/
protected long lastPoll=0;
/**
* Role vers un agent traitant les lignes
**/
public Role lineListener = new Role("lineListener");
public void setLineListener(AgentId ag) {
lineListener.setListener(ag);
}
/** Role vers l'agent contrôlant la lecture du fichier
* il est positionné initialement vers lui-même
**/
private Role fileControlListener = new Role("fileControlListener");
public void setFileControlListener(AgentId ag) {
February 13, 2001 - 18 -C3DS Report - A3 & LTSA
fileControlListener.setListener(ag);
}
/** Protected variables **/
transient protected File rawFile;
transient protected FileInputStream fin;
protected int nbLine = 0;
/**
* Creates an agent to be deployed remotely.
*
* @param to id of agent server to deploy the agent to
* @param name agent name
*/
public FileMonitor(short to, String name) {
super(to, name);
}
/**
* Initializes this agent.
* @param firstTime true when first called by the factory
*/
protected void initialize(boolean firstTime) throws Exception {
super.initialize(firstTime);
if (firstTime) {
setFileControlListener(this.getId());
initScheduler();
}
}
/**
* Demarre le Scheduler afin qu’il envoie dans
* pollingPeriod ms une notification d’ouverture de fichier
* Le Service Scheduler doit être activé au lancement des machines
* à agents, c.f. le fichier a3servers.xml
**/
protected void initScheduler() throws Exception {
AgentId schedulerId = Scheduler.getDefault();
// Register open condition inside the Scheduler service
sendTo(schedulerId, new AddConditionListener(getOpenCondition()));
lastPoll = System.currentTimeMillis();
sendTo(schedulerId, new ScheduleEvent(getOpenCondition(), new Date(lastPoll+pollingPeriod)));
}
/**
* Relance une condition d'activiation du Scheduler
**/
protected void restartScheduler() throws Exception {
long now = System.currentTimeMillis();
if (now >= ( lastPoll + pollingPeriod)) {
now = lastPoll;
}
February 13, 2001 - 19 -C3DS Report - A3 & LTSA
sendTo(Scheduler.getDefault(),
new ScheduleEvent(getOpenCondition(), new Date(now+pollingPeriod)));
}
protected final String getOpenCondition() { return ("Open file "+rawFileName);}
/**
* Ouvre le fichier rawFileName
*
**/
protected void openFile() throws Exception {
rawFile = new File(rawFileName);
nbLine =0;
try{
fin = new FileInputStream(rawFile);
FileControlNotification not = new FileControlNotification(
FileControlNotification.READNEXT);
sendTo(fileControlListener, not);
} catch (Exception e) {
System.out.println("En Attente du fichier "+rawFileName);
restartScheduler();
}
}
/**
* Lit le streamingWindow lignes du fichier courant
* et envoie pour chaque ligne une LineNotification
* vers le Role lineListener
* S’il n’y a plus de ligne disponible, une FileControlNotification est
* envoyé vers le Role fileControlListener avec un code CLOSE, sinon
* le code est READNETX afin de lire les lignes suivantes
* En cas d'erreur, on reactive le scheduler afin de recommencer la lecture depuis
* le début
* Il faudra par la suite traiter les cas d'erreurs, et éventuellement signaler
* à qui de droit que le fichier n'a pu être lu en entier
**/
protected void readNext() {
StringBuffer line = new StringBuffer();
int ch,i;
int streamCounter=0;
try {
do {
ch = fin.read();
if (ch == '\n') ch=fin.read();
if (ch == -1) {
break;
}
while ( (ch >0) && (ch!='\n') && (ch!='\r')){
line.append((char) ch);
February 13, 2001 - 20 -C3DS Report - A3 & LTSA
ch = fin.read();
}
nbLine++;
if (DEBUG) System.out.println("Ligne "+nbLine+" :"+line);
if (DEBUG) {
for (i=0; i0) && (streamCounter < streamingWindow));
if (ch == -1) {
// C’est la fin du fichier
sendTo(fileControlListener,
new FileControlNotification(FileControlNotification.CLOSE));
} else
sendTo(fileControlListener,
new FileControlNotification(FileControlNotification.READNEXT));
} catch (Exception e) {
System.out.println(e);
sendTo(fileControlListener,
new FileControlNotification(FileControlNotification.CLOSE));
}
};
/**
* Ferme le fichier en cours de lecture et réactive le Scheduler
* afin de recommencer un cycle de lecture
**/
protected void closeFile() throws Exception {
try {
System.out.println("Closing "+rawFileName);
fin.close();
} catch (Exception e) {
System.out.println(e);
}
restartScheduler();
}
/**
* Process Notification of type FileControlNotification
* required to control the access and operations onto the file
* @param not notification de type FileControlNotification
*
* @see FileControlNotification
**/
public void doReact(FileControlNotification not) throws Exception {
February 13, 2001 - 21 -C3DS Report - A3 & LTSA
switch (not.type) {
case FileControlNotification.OPEN:
openFile();
break;
case FileControlNotification.READNEXT:
readNext();
break;
case FileControlNotification.CLOSE:
closeFile();
break;
default:
}
}
/**
* Process Condition Notification coming from the Scheduler Service
*
* @param not condition en provenance du Scheduler
**/
public void doReact(Condition not) throws Exception {
if (! not.name.equals(getOpenCondition()))
return;
long now = System.currentTimeMillis();
if ( now >= (lastPoll + pollingPeriod)) {
// Envoi une notification de OPEN sans réarmer le scheduler
FileControlNotification fnot = new FileControlNotification(
FileControlNotification.OPEN);
sendTo(fileControlListener, fnot);
} else {
restartScheduler();
}
}
/**
* Process any notification
* @param not notification reçu par l'agent
* @param from identifiant de l'agent ayant envoyé la notification
**/
public void react(AgentId from, Notification not) throws Exception {
if (not instanceof FileControlNotification) {
doReact((FileControlNotification) not);
} else if (not instanceof Condition) {
doReact( (Condition) not);
} else super.react(from, not);
}
}
February 13, 2001 - 22 -C3DS Report - A3 & LTSA
Source Code of a simplified OutputAgent
import fr.dyade.aaa.agent.*;
import java.util.*;
/**
* Agent qui reçoit des notification de type LineNotification
* afin de les afficher à l'écran. Il faudra modifier cet agent
**/
public class OutputAgent extends Agent {
/**
* Creates an agent to be deployed remotely.
*
* @param to id of agent server to deploy the agent to
* @param name agent name
*/
public OutputAgent(short to, String name) {
super(to, name);
}
/**
* Process Notification of type LineNotification
* and creates a new Notification with a different format, i.e.
* with header and footer appended before and
* after the line
* @param not notification de type LineNotification
*
* @see LineNotification
**/
public void doReact(LineNotification not) throws Exception {
String newLine;
System.out.println(" "+not.line);
}
/**
* Process any notification
* @param not notification reçu par l'agent
* @param from identifiant de l'agent ayant envoyé la notification
**/
public void react(AgentId from, Notification not) throws Exception {
super.react(from, not);
if (not instanceof LineNotification) {
doReact((LineNotification) not);
}
}
} // Class OutputAgent
February 13, 2001 - 23 -You can also read