blob: d5b49305d8d0750d8312d782d0e0a81de9bed6e5 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24import java.rmi.RemoteException;
25import java.rmi.Naming;
26import java.rmi.server.UnicastRemoteObject;
27import java.rmi.registry.LocateRegistry;
28import java.util.Random;
29import java.util.ArrayList;
30import java.util.Date;
31import java.util.logging.Logger;
32import java.util.logging.Level;
33
34/**
35 * The AppleUserImpl class implements the behavior of the remote
36 * "apple user" objects exported by the server. The application server
37 * passes each of its remote "apple" objects to an apple user, and an
38 * AppleUserThread is created for each apple.
39 */
40public class AppleUserImpl
41 extends UnicastRemoteObject
42 implements AppleUser
43{
44 private static Logger logger = Logger.getLogger("reliability.appleuser");
45 private static int threadNum = 0;
46 private static long testDuration = 0;
47 private static int maxLevel = 7;
48 private static Thread server = null;
49 private static Exception status = null;
50 private static Random random = new Random();
51
52 public AppleUserImpl() throws RemoteException {
53 }
54
55 /**
56 * Allows the other server process to indicate that it is ready
57 * to start "juicing".
58 */
59 public synchronized void startTest() throws RemoteException {
60 this.notifyAll();
61 }
62
63 /**
64 * Allows the other server process to report an exception to this
65 * process and thereby terminate the test.
66 */
67 public void reportException(Exception status) throws RemoteException {
68 synchronized (AppleUserImpl.class) {
69 this.status = status;
70 AppleUserImpl.class.notifyAll();
71 }
72 }
73
74 /**
75 * "Use" supplied apple object. Create an AppleUserThread to
76 * stress it out.
77 */
78 public synchronized void useApple(Apple apple) throws RemoteException {
79 String threadName = Thread.currentThread().getName();
80 logger.log(Level.FINEST,
81 threadName + ": AppleUserImpl.useApple(): BEGIN");
82
83 AppleUserThread t =
84 new AppleUserThread("AppleUserThread-" + (++threadNum), apple);
85 t.start();
86
87 logger.log(Level.FINEST,
88 threadName + ": AppleUserImpl.useApple(): END");
89 }
90
91 /**
92 * The AppleUserThread class repeatedly invokes calls on its associated
93 * Apple object to stress the RMI system.
94 */
95 class AppleUserThread extends Thread {
96
97 Apple apple;
98
99 public AppleUserThread(String name, Apple apple) {
100 super(name);
101 this.apple = apple;
102 }
103
104 public void run() {
105 int orangeNum = 0;
106 long stopTime = System.currentTimeMillis() + testDuration;
107 Logger logger = Logger.getLogger("reliability.appleuserthread");
108
109 try {
110 do { // loop until stopTime is reached
111
112 /*
113 * Notify apple with some apple events. This tests
114 * serialization of arrays.
115 */
116 int numEvents = Math.abs(random.nextInt() % 5);
117 AppleEvent[] events = new AppleEvent[numEvents];
118 for (int i = 0; i < events.length; ++ i) {
119 events[i] = new AppleEvent(orangeNum % 3);
120 }
121 apple.notify(events);
122
123 /*
124 * Request a new orange object be created in
125 * the application server.
126 */
127 Orange orange = apple.newOrange(
128 "Orange(" + getName() + ")-" + (++orangeNum));
129
130 /*
131 * Create a large message of random ints to pass to orange.
132 */
133 int msgLength = 1000 + Math.abs(random.nextInt() % 3000);
134 int[] message = new int[msgLength];
135 for (int i = 0; i < message.length; ++ i) {
136 message[i] = random.nextInt();
137 }
138
139 /*
140 * Invoke recursive call on the orange. Base case
141 * of recursion inverts messgage.
142 */
143 OrangeEchoImpl echo = new OrangeEchoImpl(
144 "OrangeEcho(" + getName() + ")-" + orangeNum);
145 int[] response = orange.recurse(echo, message,
146 2 + Math.abs(random.nextInt() % (maxLevel + 1)));
147
148 /*
149 * Verify message was properly inverted and not corrupted
150 * through all the recursive method invocations.
151 */
152 if (response.length != message.length) {
153 throw new RuntimeException(
154 "ERROR: CORRUPTED RESPONSE: " +
155 "wrong length of returned array " + "(should be " +
156 message.length + ", is " + response.length + ")");
157 }
158 for (int i = 0; i < message.length; ++ i) {
159 if (~message[i] != response[i]) {
160 throw new RuntimeException(
161 "ERROR: CORRUPTED RESPONSE: " +
162 "at element " + i + "/" + message.length +
163 " of returned array (should be " +
164 Integer.toHexString(~message[i]) + ", is " +
165 Integer.toHexString(response[i]) + ")");
166 }
167 }
168
169 try {
170 Thread.sleep(Math.abs(random.nextInt() % 10) * 1000);
171 } catch (InterruptedException e) {
172 }
173
174 } while (System.currentTimeMillis() < stopTime);
175
176 } catch (Exception e) {
177 status = e;
178 }
179 synchronized (AppleUserImpl.class) {
180 AppleUserImpl.class.notifyAll();
181 }
182 }
183 }
184
185 private static void usage() {
186 System.out.println("Usage: AppleUserImpl [-hours <hours> | " +
187 "-seconds <seconds>]");
188 System.out.println(" [-maxLevel <maxLevel>]");
189 System.out.println(" hours The number of hours to run the juicer.");
190 System.out.println(" The default is 0 hours.");
191 System.out.println(" seconds The number of seconds to run the juicer.");
192 System.out.println(" The default is 0 seconds.");
193 System.out.println(" maxLevel The maximum number of levels to ");
194 System.out.println(" recurse on each call.");
195 System.out.println(" The default is 7 levels.");
196 //TestLibrary.bomb("Bad argument");
197 }
198
199 /**
200 * Entry point for the "juicer" server process. Create and export
201 * an apple user implementation in an rmiregistry running on localhost.
202 */
203 public static void main(String[] args)
204
205 {
206 //TestLibrary.suggestSecurityManager("java.rmi.RMISecurityManager");
207 long startTime = 0;
208 String durationString = null;
209
210 // parse command line args
211 try {
212 for (int i = 0; i < args.length ; i++ ) {
213 String arg = args[i];
214 if (arg.equals("-hours")) {
215 if (durationString != null) {
216 usage();
217 }
218 i++;
219 int hours = Integer.parseInt(args[i]);
220 durationString = hours + " hours";
221 testDuration = hours * 60 * 60 * 1000;
222 } else if (arg.equals("-seconds")) {
223 if (durationString != null) {
224 usage();
225 }
226 i++;
227 long seconds = Long.parseLong(args[i]);
228 durationString = seconds + " seconds";
229 testDuration = seconds * 1000;
230 } else if (arg.equals("-maxLevel")) {
231 i++;
232 maxLevel = Integer.parseInt(args[i]);
233 } else {
234 usage();
235 }
236 }
237 if (durationString == null) {
238 durationString = testDuration + " milliseconds";
239 }
240 } catch (Throwable t) {
241 usage();
242 }
243
244 AppleUserImpl user = null;
245 try {
246 user = new AppleUserImpl();
247 } catch (RemoteException e) {
248 //TestLibrary.bomb("Failed to create AppleUser", e);
249 }
250
251 synchronized (user) {
252 // create new registry and bind new AppleUserImpl in registry
253 try {
254 LocateRegistry.createRegistry(1099); //TestLibrary.REGISTRY_PORT);
255 Naming.rebind("rmi://localhost:1099/AppleUser",user);
256 //TestLibrary.REGISTRY_PORT + "/AppleUser", user);
257 } catch (RemoteException e) {
258 //TestLibrary.bomb("Failed to bind AppleUser", e);
259 } catch (java.net.MalformedURLException e) {
260 //TestLibrary.bomb("Failed to bind AppleUser", e);
261 }
262
263 // start the other server if available
264 try {
265 Class app = Class.forName("ApplicationServer");
266 server = new Thread((Runnable) app.newInstance());
267 logger.log(Level.INFO, "Starting application server " +
268 "in same process");
269 server.start();
270 } catch (ClassNotFoundException e) {
271 // assume the other server is running in a separate process
272 logger.log(Level.INFO, "Application server must be " +
273 "started in separate process");
274 } catch (Exception ie) {
275 //TestLibrary.bomb("Could not instantiate server", ie);
276 }
277
278 // wait for other server to call startTest method
279 try {
280 logger.log(Level.INFO, "Waiting for application server " +
281 "process to start");
282 user.wait();
283 } catch (InterruptedException ie) {
284 //TestLibrary.bomb("AppleUserImpl interrupted", ie);
285 }
286 }
287
288 startTime = System.currentTimeMillis();
289 logger.log(Level.INFO, "Test starting");
290
291 // wait for exception to be reported or first thread to complete
292 try {
293 logger.log(Level.INFO, "Waiting " + durationString + " for " +
294 "test to complete or exception to be thrown");
295
296 synchronized (AppleUserImpl.class) {
297 AppleUserImpl.class.wait();
298 }
299
300 if (status != null) {
301 //TestLibrary.bomb("juicer server reported an exception", status);
302 } else {
303 logger.log(Level.INFO, "TEST PASSED");
304 }
305 } catch (Exception e) {
306 logger.log(Level.INFO, "TEST FAILED");
307 //TestLibrary.bomb("unexpected exception", e);
308 } finally {
309 logger.log(Level.INFO, "Test finished");
310 long actualDuration = System.currentTimeMillis() - startTime;
311 logger.log(Level.INFO, "Test duration was " +
312 (actualDuration/1000) + " seconds " +
313 "(" + (actualDuration/3600000) + " hours)");
314 }
315 }
316}