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, 2001
C3DS 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