package com.ibm.jactors.test; import java.math.BigInteger; import java.util.Date; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Random; import java.util.concurrent.ConcurrentHashMap; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import com.ibm.jactors.AbstractActor; import com.ibm.jactors.Actor; import com.ibm.jactors.DefaultActorManager; import com.ibm.jactors.DefaultMessage; import com.ibm.jactors.Message; import com.ibm.jactors.logging.DefaultLogger; import com.ibm.jactors.utils.Utils; /** * A set of runtime services for testing actors and a test case driver. * * @author BFEIGENB * */ public class DefaultActorTest extends Utils { public static final int MAX_IDLE_SECONDS = 10; // public static final int STEP_COUNT = 3 * 60; public static final int TEST_VALUE_COUNT = 1000; // TODO: make bigger public DefaultActorTest() { super(); } private Map<String, Actor> testActors = new ConcurrentHashMap<String, Actor>(); static Random rand = new Random(); public static int nextInt(int limit) { return rand.nextInt(limit); } protected DefaultActorManager getManager() { DefaultActorManager am = actorManager != null ? actorManager : new DefaultActorManager(); return am; } protected int stepCount = 120; public void setStepCount(int stepCount) { this.stepCount = stepCount; } public int getStepCount() { return stepCount; } protected int threadCount = 10; public int getThreadCount() { return threadCount; } public void setThreadCount(int threadCount) { this.threadCount = threadCount; } public void setTestActors(Map<String, Actor> testActors) { this.testActors = testActors; } public Map<String, Actor> getTestActors() { return testActors; } public static final int COMMON_ACTOR_COUNT = 10; public static final int TEST_ACTOR_COUNT = 25; public static final int PRODUCER_ACTOR_COUNT = 25; public static void sleeper(int seconds) { int millis = seconds * 1000 + -50 + nextInt(100); // a little // variation // logger.trace("sleep: %dms", millis); sleep(millis); } public static void dumpMessages(List<DefaultMessage> messages) { synchronized (messages) { if (messages.size() > 0) { for (DefaultMessage m : messages) { logger.info("%s", m); } } } } protected List<ChangeListener> listeners = new LinkedList<ChangeListener>(); public void addChangeListener(ChangeListener l) { if (!listeners.contains(l)) { listeners.add(l); } } public void removeChangeListener(ChangeListener l) { listeners.remove(l); } protected void fireChangeListeners(ChangeEvent e) { for (ChangeListener l : listeners) { l.stateChanged(e); } } protected static String[] types = new String[] { "widget", "framit", "frizzle", "gothca", "splat" }; public static String[] getItemTypes() { return types; } public static void main(String[] args) { DefaultActorTest at = new DefaultActorTest(); at.run(args); logger.trace("Done"); } protected String title; public String getTitle() { return title; } public class ActorX extends AbstractActor { public ActorX() { super(); // TODO Auto-generated constructor stub } @Override protected void loopBody(Message m) { // logger.trace("ActorX:%s loopBody %s: %s", getName(), m, this); sleeper(1); String subject = m.getSubject(); if ("repeat".equals(subject)) { int count = (Integer) m.getData(); logger.trace("ActorX:%s repeat(%d) %s: %s", getName(), count, m, this); if (count > 0) { m = new DefaultMessage("repeat", count - 1); // logger.trace("TestActor loopBody send %s: %s", m, this); String toName = "actor" + nextInt(TEST_ACTOR_COUNT); Actor to = getTestActors().get(toName); if (to != null) { getManager().send(m, this, to); } else { logger.warning("repeat:%s to is null: %s", getName(), toName); } } } else if ("init".equals(subject)) { int count = (Integer) m.getData(); count = nextInt(count) + 1; logger.trace("ActorX:%s init(%d): %s", getName(), count, this); for (int i = 0; i < count; i++) { sleeper(1); m = new DefaultMessage("repeat", count); // logger.trace("TestActor runBody send %s: %s", m, this); String toName = "actor" + nextInt(TEST_ACTOR_COUNT); Actor to = getTestActors().get(toName); if (to != null) { getManager().send(m, this, to); } else { logger.warning("init:%s to is null: %s", getName(), toName); } DefaultMessage dm = new DefaultMessage("repeat", count); dm.setDelayUntil(new Date().getTime() + (nextInt(5) + 1) * 1000); getManager().send(dm, this, this.getClass().getSimpleName()); } } else { logger.warning("ActorX:%s loopBody unknown subject: %s", getName(), subject); } } } volatile protected boolean done; public void terminateRun() { done = true; } public static String[] getTestNames() { return new String[] { "Countdown", "Producer Consumer", /* "Quicksort", */"MapReduce", "Virus Scan", "All" }; } DefaultActorManager actorManager; public DefaultActorManager getActorManager() { return actorManager; } public void setActorManager(DefaultActorManager actorManager) { this.actorManager = actorManager; } public void run(String[] args) { done = false; // DefaultLogger.getDefaultInstance().setIncludeDate(false); DefaultLogger.getDefaultInstance().setIncludeContext(false); DefaultLogger.getDefaultInstance().setIncludeCaller(false); // DefaultLogger.getDefaultInstance().setIncludeThread(false); DefaultLogger.getDefaultInstance().setLogToFile(false); DefaultLogger.getDefaultInstance().setThreadFieldWidth(10); int sc = stepCount; int tc = threadCount; boolean doTest = false, doProduceConsume = false, doQuicksort = false, doMapReduce = false, doVirusScan = false; title = ""; for (int i = 0; i < args.length; i++) { String arg = args[i].toLowerCase(); if (arg.startsWith("-")) { arg = arg.substring(1); if (arg.toLowerCase().startsWith("stepcount:")) { sc = Integer.parseInt(arg.substring("stepcount:".length())); } else if (arg.startsWith("sc:")) { sc = Integer.parseInt(arg.substring("sc:".length())); } else if (arg.toLowerCase().startsWith("threadcount:")) { tc = Integer.parseInt(arg.substring("threadcount:".length())); } else if (arg.startsWith("tc:")) { tc = Integer.parseInt(arg.substring("tc:".length())); } else { System.out.printf("Unknown switch: %s%n", arg); } } else { if (arg.equalsIgnoreCase("test") || arg.equalsIgnoreCase("countdown") || arg.equalsIgnoreCase("cd")) { doTest = true; } else if (arg.equalsIgnoreCase("producerconsumer") || arg.equalsIgnoreCase("pc")) { doProduceConsume = true; } else if (arg.equalsIgnoreCase("quicksort") || arg.equalsIgnoreCase("qs")) { doQuicksort = true; } else if (arg.equalsIgnoreCase("mapreduce") || arg.equalsIgnoreCase("mr")) { doMapReduce = true; } else if (arg.equalsIgnoreCase("virusscan") || arg.equalsIgnoreCase("vs")) { doVirusScan = true; } else if (arg.equalsIgnoreCase("all")) { doProduceConsume = true; doTest = true; doMapReduce = true; doQuicksort = true; doVirusScan = true; } else { System.out.printf("Unknown parameter: %s%n", arg); } } } if (!doTest && !doProduceConsume && !doQuicksort && !doMapReduce && !doVirusScan) { doTest = true; } if (doTest) { if (title.length() > 0) { title += " "; } title += "(Countdown Test)"; } if (doProduceConsume) { if (title.length() > 0) { title += " "; } title += "(Producer+Consumer)"; } if (doQuicksort) { if (title.length() > 0) { title += " "; } title += "(Quicksort)"; } if (doMapReduce) { if (title.length() > 0) { title += " "; } title += "(MapReduce)"; } if (doVirusScan) { if (title.length() > 0) { title += " "; } title += "(VirusScan)"; } DefaultActorManager am = getManager(); try { Map<String, Object> options = new HashMap<String, Object>(); options.put(DefaultActorManager.ACTOR_THREAD_COUNT, tc); am.initialize(options); if (doTest) { for (int i = 0; i < COMMON_ACTOR_COUNT; i++) { Actor a = am.createActor(TestActor.class, String.format("common%02d", i)); if (a instanceof TestableActor) { TestableActor ta = (TestableActor) a; ta.setActorTest(this); } a.setCategory(TestActor.class.getSimpleName()); getTestActors().put(a.getName(), a); // logger.trace("created: %s", a); } for (int i = 0; i < TEST_ACTOR_COUNT; i++) { Actor a = am.createActor(TestActor.class, String.format("actor%02d", i)); if (a instanceof TestableActor) { TestableActor ta = (TestableActor) a; ta.setActorTest(this); } getTestActors().put(a.getName(), a); // logger.trace("created: %s", a); } } if (doProduceConsume) { for (int i = 0; i < PRODUCER_ACTOR_COUNT; i++) { Actor a = am.createActor(ProducerActor.class, String.format("producer%02d", i)); getTestActors().put(a.getName(), a); // logger.trace("created: %s", a); } } if (doVirusScan) { VirusScanActor.createVirusScanActor(am); DefaultMessage dm = new DefaultMessage("init", "/downloads"); am.send(dm, null, VirusScanActor.getCategoryName()); } if (doMapReduce) { BigInteger[] values = new BigInteger[TEST_VALUE_COUNT]; for (int i = 0; i < values.length; i++) { values[i] = new BigInteger(Long.toString((long) rand.nextInt(values.length))); } BigInteger[] targets = new BigInteger[Math.max(1, values.length / 10)]; BigInteger res = new BigInteger("0"); for (int i = 0; i < values.length; i++) { res = res.add(values[i].multiply(values[i])); } String id = MapReduceActor.nextId(); logger.trace("**** MapReduce %s (expected=%d) start: %s", id, res, values); // start at least 5 actors MapReduceActor.createMapReduceActor(am, 10); MapReduceActor.createMapReduceActor(am, 10); MapReduceActor.createMapReduceActor(am, 10); MapReduceActor.createMapReduceActor(am, 10); MapReduceActor.createMapReduceActor(am, 10); // getTestActors().put(mra.getName(), mra); DefaultMessage dm = new DefaultMessage("init", new Object[] { values, targets, SumOfSquaresReducer.class }); am.send(dm, null, MapReduceActor.getCategoryName()); } for (String key : getTestActors().keySet()) { am.startActor(getTestActors().get(key)); } for (int i = sc; i > 0; i--) { if (done) { break; } // see if idle a while long now = new Date().getTime(); if (am.getActiveRunnableCount() == 0) { if (now - am.getLastDispatchTime() > MAX_IDLE_SECONDS * 1000 && now - am.getLastSendTime() > MAX_IDLE_SECONDS * 1000) { break; } } setStepCount(i); fireChangeListeners(new ChangeEvent(this)); if (i < 10 || i % 10 == 0) { logger.trace("main waiting: %d...", i); } sleeper(1); } setStepCount(0); fireChangeListeners(new ChangeEvent(this)); // logger.trace("main terminating"); am.terminateAndWait(); } catch (Exception e) { e.printStackTrace(); } } }