ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/experimental/agents/PeerHandler.java
Revision: 1.1
Committed: Fri May 4 02:04:35 2001 UTC (23 years, 6 months ago) by ajm
Branch: MAIN
Log Message:
Loads of new framework but far from complete.

The BasicAgent class is as it says, a basic agent, with ability to be run from the command line to fire it into an agentstation.

AgentStations now have support for adding and removing agents and support for multiple listeners.  Also initial support for peer agent stations.  Attempted support at peer -> peer agent transfer, but run into problems.

Still no bytecode transfer, but location and method has been figured out.

The AgentSystem class is now the bootstrap class for an agent station.  It brings up the AgentStation (which is now singleton) and the Logger (also singleton - using standard i-scream logging techniques).  It is possible to specify a peer station that the booting agent station should connect to.

Initial TODO:

	agent class loader
	agent bytecode transfer
	solve peer -> peer problems - possibly by creating extra socket to send agent, but shouldn't really be needed

File Contents

# Content
1 //---PACKAGE DECLARATION---
2
3 //---IMPORTS---
4 import java.io.ObjectInputStream;
5 import java.io.ObjectOutputStream;
6 import java.io.PrintWriter;
7 import java.io.BufferedReader;
8 import java.io.InputStreamReader;
9 import java.io.IOException;
10 import java.net.Socket;
11
12 /**
13 * Handles communication between this agent station and a peer
14 * agent stations.
15 *
16 * @author $Author: tdb1 $
17 * @version $Id: TemplateClass.java,v 1.11 2001/03/22 21:50:41 tdb1 Exp $
18 */
19 class PeerHandler extends Handler {
20
21 //---FINAL / FINAL STATIC ATTRIBUTES---
22
23 /**
24 * The current CVS revision of this class
25 */
26 public static final String REVISION = "$Revision: 1.11 $";
27
28 //---STATIC METHODS---
29
30 //---CONSTRUCTORS---
31
32 public PeerHandler(Socket socket) throws IOException {
33 super(socket);
34 // setup reader & writer
35 _socketIn = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
36 _logger.write(toString(), Logger.SYSINIT, "created");
37 }
38
39 //---PUBLIC METHODS---
40
41 public void run() {
42 _logger.write(toString(), Logger.SYSINIT, "started");
43 try {
44
45 while(_running) {
46 // VERY basic protocol, only allow sending of agents ;-)
47 getInBoundMessage("SENDAGENT");
48 receiveAgent();
49 }
50
51 } catch (IOException e) {
52 _logger.write(toString(), Logger.ERROR, "I/O ERROR - " + e);
53 }
54
55 shutdownSocket();
56 AgentStation.getInstance().removePeer(this);
57 _logger.write(toString(), Logger.SYSMSG, "finished");
58 }
59
60 public boolean sendAgent(Agent agent) {
61 boolean result = false;
62 _logger.write(toString(), Logger.SYSMSG, "starting agent transfer - outbound");
63 try {
64 // VERY basic protocol, only allow sending of agents ;-)
65
66 // INCOMPLETE - infact it needs to create a second socket as I don't believe multiple
67 // stream types (ie, objectstream and printwriter) can be used together
68 // needs investigating
69
70 PrintWriter socketOut = new PrintWriter(_socket.getOutputStream(), true);
71 socketOut.println("SENDAGENT");
72 socketOut.close();
73
74 // send agent bytecode
75
76 // TODO
77
78 // send agent state (serialized object)
79 ObjectOutputStream objectOutStream = new ObjectOutputStream(_socket.getOutputStream());
80 AgentStation.getInstance().removeAgent(agent);
81 objectOutStream.writeObject(agent);
82 objectOutStream.flush();
83 objectOutStream.close();
84
85 _logger.write(toString(), Logger.SYSMSG, "agent sent");
86 result = true;
87 } catch (IOException e) {
88 _logger.write(toString(), Logger.ERROR, "I/O ERROR - " + e);
89 }
90 return result;
91 }
92
93 /**
94 * Used to shutdown this thread
95 */
96 public void shutdown() {
97 _running = false;
98 }
99
100 /**
101 * Overrides the {@link java.lang.Object#toString() Object.toString()}
102 * method to provide clean logging (every class should have this).
103 *
104 * This uses the uk.ac.ukc.iscream.util.FormatName class
105 * to format the toString()
106 *
107 * @return the name of this class and its CVS revision
108 */
109 public String toString() {
110 return FormatName.getName(
111 _name,
112 getClass().getName(),
113 REVISION);
114 }
115
116 //---PRIVATE/PROTECTED METHODS---
117
118 /**
119 * Carry out functions to receive an Agent
120 * NOTE - duplicated code in DirectAgentHandler, solution? -
121 *
122 * @throws IOException on I/O error
123 */
124 private void receiveAgent() throws IOException {
125 _logger.write(toString(), Logger.SYSMSG, "starting agent transfer - inbound");
126 try {
127 // receive agent bytecode
128
129 // TODO
130
131 // receive agent state (serialized object)
132 ObjectInputStream objectInStream = new ObjectInputStream(_socket.getInputStream());
133 Agent agent = (Agent) objectInStream.readObject();
134 AgentStation.getInstance().addAgent(agent);
135
136 _logger.write(toString(), Logger.DEBUG, "Agent state received");
137 _logger.write(toString(), Logger.SYSMSG, "Agent name - " + agent.getName());
138 _logger.write(toString(), Logger.DEBUG, agent.getName() + "'s transmission count - " + agent.getTransmissionCount());
139
140 _logger.write(toString(), Logger.SYSMSG, "Welcoming agent");
141 agent.onArrival(AgentStation.getInstance());
142
143 _logger.write(toString(), Logger.SYSMSG, "Starting agent thread");
144
145 Thread thread = new Thread(agent);
146 thread.start();
147
148 objectInStream.close();
149 _logger.write(toString(), Logger.SYSMSG, "agent received");
150
151 } catch (ClassNotFoundException e) {
152 _logger.write(toString(), Logger.ERROR, "ERROR - possible error transferring agent bytecode - " + e);
153 }
154 }
155
156 /**
157 * Get the next inbound string from the socket and expect it
158 * to be the given text.
159 *
160 * @param expected the expected text
161 *
162 * @throws IOException on I/O error or protocol error
163 */
164 private String getInBoundMessage(String expected) throws IOException {
165 // grab the input
166 String inBound = getInBoundMessage();
167 // check if it's what we're expecting
168 if(!inBound.equals(expected)) {
169 throw new IOException("protocol error - expected:" + expected + " got:" + inBound);
170 }
171 // it should be ok then
172 return inBound;
173 }
174
175 /**
176 * Get the next inbound string from the socket.
177 *
178 * @throws IOException on I/O error or protocol error
179 */
180 private String getInBoundMessage() throws IOException {
181 // grab the input
182 String inBound = _socketIn.readLine();
183 // check for null's, likely disconnection
184 if(inBound == null) {
185 throw new IOException("got null from peer, maybe it died");
186 }
187 // it's a valid message it seems
188 return inBound;
189 }
190
191 //---ACCESSOR/MUTATOR METHODS---
192
193 //---ATTRIBUTES---
194
195 /**
196 * This is the friendly identifier of the
197 * component this class is running in.
198 * eg, a Filter may be called "filter1",
199 * If this class does not have an owning
200 * component, a name from the configuration
201 * can be placed here. This name could also
202 * be changed to null for utility classes.
203 */
204 private String _name = "PeerHandler";
205
206 /**
207 * This holds a reference to the
208 * system logger that is being used.
209 */
210 private Logger _logger = Logger.getInstance();
211
212 /**
213 * A "running" used by the main loop in the run() method to determine if
214 * it should continue running this thread.
215 */
216 private boolean _running = true;
217
218 /**
219 * Used for the input stream of this socket
220 */
221 private BufferedReader _socketIn;
222
223 //---STATIC ATTRIBUTES---
224
225 }