source: simplerunner/src/main/java/geniusweb/simplerunner/NegoRunner.java@ 42

Last change on this file since 42 was 42, checked in by bart, 2 years ago

Fix for IssueValue hashcode.

File size: 5.5 KB
Line 
1package geniusweb.simplerunner;
2
3import java.io.IOException;
4import java.nio.charset.StandardCharsets;
5import java.nio.file.Files;
6import java.nio.file.Paths;
7import java.util.List;
8import java.util.logging.Level;
9
10import com.fasterxml.jackson.core.JsonProcessingException;
11import com.fasterxml.jackson.databind.ObjectMapper;
12
13import geniusweb.events.ProtocolEvent;
14import geniusweb.protocol.CurrentNegoState;
15import geniusweb.protocol.NegoProtocol;
16import geniusweb.protocol.NegoSettings;
17import geniusweb.protocol.NegoState;
18import geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory;
19import tudelft.utilities.logging.Reporter;
20
21/**
22 * A simple tool to run a negotiation stand-alone, without starting the servers.
23 * All referred files and classes need to be stored locally (or be in the
24 * dependency list if you use maven).
25 * <p>
26 * <em>IMPORTANT</em> SimpleRunner has a number of restrictions, compared to a
27 * run using a runserver and partyserver
28 * <ul>
29 * <li>With stand-alone runner, your parties are run together in a single
30 * classloader. The main implication is that there may arise version conflicts
31 * between parties.
32 * <li>Stand-alone runner does NOT enforce the time deadline. Parties may
33 * continue running indefinitely and thus bog down the JVM and stalling
34 * tournaments.
35 * </ul>
36 */
37public class NegoRunner implements Runnable {
38 private final static ObjectMapper jackson = new ObjectMapper();
39
40 private final NegoSettings settings;
41 private final NegoProtocol protocol;
42 private final ClassPathConnectionFactory connectionfactory;
43 protected final Reporter log;
44 private boolean properlyStopped = false;
45 private final int LOOPTIME = 200;// ms
46 private final int FINALWAITTIME = 5000;// ms
47 private long maxruntime;
48
49 /**
50 *
51 * @param settings the {@link NegoSettings}
52 * @param connectionfactory the {@link ProtocolToPartyConnFactory}
53 * @param logger the {@link Reporter} to log problems
54 * @param maxruntime limit in millisecs. Ignored if 0
55 */
56 public NegoRunner(NegoSettings settings,
57 ClassPathConnectionFactory connectionfactory, Reporter logger,
58 long maxruntime) {
59 if (settings == null || connectionfactory == null) {
60 throw new NullPointerException("Arguments must be not null");
61 }
62 this.settings = settings;
63 this.log = logger;
64 this.protocol = settings.getProtocol(log);
65 this.connectionfactory = connectionfactory;
66 this.maxruntime = maxruntime;
67 }
68
69 /**
70 *
71 * @return true if the runner has finished
72 */
73 public boolean isProperlyStopped() {
74 return properlyStopped;
75 }
76
77 @Override
78 public void run() {
79 protocol.addListener(evt -> handle(evt));
80 protocol.start(connectionfactory);
81 long remainingtime = maxruntime;
82 while (!properlyStopped && (maxruntime == 0 || remainingtime > 0)) {
83 try {
84 Thread.sleep(LOOPTIME);
85 remainingtime -= LOOPTIME;
86 } catch (InterruptedException e) {
87 e.printStackTrace();
88 }
89 }
90 log.log(Level.INFO, "Waiting for connection closure");
91
92 remainingtime = FINALWAITTIME;
93 while (remainingtime > 0
94 && !connectionfactory.getOpenConnections().isEmpty()) {
95 try {
96 Thread.sleep(LOOPTIME);
97 remainingtime -= LOOPTIME;
98 } catch (InterruptedException e) {
99 e.printStackTrace();
100 }
101 }
102 List<BasicConnection> openconn = connectionfactory.getOpenConnections();
103 if (!openconn.isEmpty())
104 log.log(Level.WARNING, "Connections " + openconn
105 + " did not close properly at end of run");
106 log.log(Level.INFO, "end run");
107 }
108
109 private void handle(ProtocolEvent evt) {
110 if (evt instanceof CurrentNegoState && ((CurrentNegoState) evt)
111 .getState().isFinal(System.currentTimeMillis())) {
112 stop();
113 }
114 }
115
116 protected void stop() {
117 logFinal(Level.INFO, protocol.getState());
118 properlyStopped = true;
119 }
120
121 /**
122 * Separate so that we can intercept this when mocking, as this will crash
123 * on mocks because {@link #jackson} can not handle mocks.
124 *
125 * @param level the log {@link Level}
126 * @param state the {@link NegoState} to log
127 */
128 protected void logFinal(Level level, NegoState state) {
129 try {
130 log.log(level, "protocol ended normally: "
131 + jackson.writeValueAsString(protocol.getState()));
132 } catch (JsonProcessingException e) {
133 e.printStackTrace();
134 }
135 }
136
137 /**
138 * The main runner
139 *
140 * @param args should have 1 argument, the settings.json file to be used.
141 * @throws IOException if problem occurs
142 */
143 public static void main(String[] args) throws IOException {
144 if (args.length != 1) {
145 showusage();
146 return;
147 }
148 String serialized = new String(Files.readAllBytes(Paths.get(args[0])),
149 StandardCharsets.UTF_8);
150 NegoSettings settings = jackson.readValue(serialized,
151 NegoSettings.class);
152
153 NegoRunner runner = new NegoRunner(settings,
154 new ClassPathConnectionFactory(), new StdOutReporter(), 0);
155 runner.run();
156 }
157
158 private static void showusage() {
159 System.err.println("GeniusWeb stand-alone runner.");
160 System.err.println("first argument should be <settings.json>.");
161 System.err.println(
162 "The settings.json file should contain the NegoSettings.");
163 System.err.println(
164 "See the settings.json example file and the GeniusWeb wiki pages. ");
165
166 }
167
168 /**
169 * @return protocol that runs/ran the session.
170 */
171 public NegoProtocol getProtocol() {
172 return protocol;
173 }
174}
175
176class StdOutReporter implements Reporter {
177 @Override
178 public void log(Level level, String msg) {
179 if (level == Level.WARNING || level == Level.SEVERE)
180 System.err.println(level + ":" + msg);
181 else
182 System.out.println(level + ":" + msg);
183 }
184
185 @Override
186 public void log(Level arg0, String msg, Throwable arg2) {
187 log(arg0, msg);
188 }
189
190}
Note: See TracBrowser for help on using the repository browser.