52 modified files
hps-et-java/src/main/java/org/jlab/coda/et
diff -N EtAttachment.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtAttachment.java 13 Feb 2012 22:50:52 -0000 1.3
@@ -0,0 +1,167 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et;
+
+import java.io.*;
+
+import org.jlab.coda.et.exception.*;
+
+/**
+ * This class defines an ET system user's attachment to a station.
+ * Attachments can only be created by an ET system's {@link EtSystem#attach(EtStation)}
+ * method. Attachments are means of designating the
+ * ownership of events and keeping track of events.
+ *
+ * @author Carl Timmer
+ */
+public class EtAttachment {
+
+ // TODO: keep a list or set of events we currently have out?
+
+ /** Unique id number. */
+ private int id;
+
+ /** ET system the attachment is associated with. */
+ private EtSystem sys;
+
+ /** Station the attachment is associated with. */
+ private EtStation station;
+
+ /**
+ * Flag telling whether this attachment object is usable or the attachment it
+ * represents has been detached. Set by the user's ET system object.
+ */
+ private boolean usable;
+
+
+ /**
+ * Constructor for creating an attachment to a specific ET system and station.
+ * Attachments can only be created by an ET system's {@link EtSystem#attach(EtStation)}
+ * method.
+ *
+ * @param station station object
+ * @param id unique attachment id number
+ * @param sys ET system object
+ */
+ EtAttachment(EtStation station, int id, EtSystem sys) {
+ this.id = id;
+ this.sys = sys;
+ this.station = station;
+ }
+
+
+ // Getters/Setters
+
+
+ /**
+ * Gets the object of the station attached to.
+ * @return object of station attached to
+ */
+ public EtStation getStation() {return station;}
+
+ /**
+ * Gets the id number of this attachment.
+ * @return id number of this attachment
+ */
+ public int getId() {return id;}
+
+ /**
+ * Tells if this attachment object is usable.
+ * @return <code>true</code> if attachment object is usable and <code>false
+ * </code> otherwise
+ */
+ public boolean isUsable() {return usable;}
+
+ /**
+ * Sets whether this attachment object is usable or not.
+ * @param usable <code>true</code> if this attachment object is usable and <code>false otherwise
+ */
+ void setUsable(boolean usable) {
+ this.usable = usable;
+ }
+
+ /**
+ * Sets the EtSystemUse object for using the ET system.
+ * @return the EtSystemUse object for using the ET system
+ */
+ public EtSystem getSys() {
+ return sys;
+ }
+
+ /**
+ * Gets the value of an attachment's eventsPut, eventsGet, eventsDump, or
+ * eventsMake by network communication with the ET system.
+ *
+ * @param cmd command number
+ * @return value of requested parameter
+ * @throws IOException if there are network communication problems
+ * @throws EtException if the station no longer exists
+ */
+ private long getLongValue(int cmd) throws IOException, EtException {
+ int err;
+ long val;
+
+ synchronized (sys) {
+ sys.getOutputStream().writeInt(cmd);
+ sys.getOutputStream().writeInt(id);
+ sys.getOutputStream().flush();
+ err = sys.getInputStream().readInt();
+ val = sys.getInputStream().readLong();
+ }
+
+ if (err != EtConstants.ok) {
+ throw new EtException("this station has been revmoved from ET system");
+ }
+
+ return val;
+ }
+
+ /**
+ * Gets the number of events put into the ET system by this attachment.
+ * @return number of events put into the ET system by this attachment
+ */
+ public long getEventsPut() throws IOException, EtException {
+ return getLongValue(EtConstants.netAttPut);
+ }
+
+ /**
+ * Gets the number of events gotten from the ET system by this attachment.
+ * @return number of events gotten from the ET system by this attachment
+ */
+ public long getEventsGet() throws IOException, EtException {
+ return getLongValue(EtConstants.netAttGet);
+ }
+
+ /**
+ * Gets the number of events dumped (recycled by returning to GRAND_CENTRAL
+ * station) through this attachment.
+ *
+ * @return number of events dumped into the ET system by this attachment
+ */
+ public long getEventsDump() throws IOException, EtException {
+ return getLongValue(EtConstants.netAttDump);
+ }
+
+ /**
+ * Gets the number of new events gotten from the ET system by this attachment.
+ * @return number of new events gotten from the ET system by this attachment
+ */
+ public long getEventsMake() throws IOException, EtException {
+ return getLongValue(EtConstants.netAttMake);
+ }
+}
+
+
+
hps-et-java/src/main/java/org/jlab/coda/et
diff -N EtConstants.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtConstants.java 13 Feb 2012 22:50:52 -0000 1.3
@@ -0,0 +1,479 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et;
+
+/**
+ * This class defines some useful constants which are made to be identical to those
+ * used in the C-based ET system code.
+ *
+ * @author Carl Timmer
+ */
+
+public final class EtConstants {
+
+ /** This constructor does nothing. */
+ private EtConstants() {
+ }
+
+ /** Ints representing ascii for "cMsg is cool", used to filter out portscanning software. */
+ public static final int[] magicNumbers = {0x45543269, 0x73324772, 0x72656174};
+
+ // constants from et.h
+
+ /** A convenient multicast address used for finding an ET system.
+ * @see EtSystemOpenConfig#addMulticastAddr(String) */
+ public static final String multicastAddr = "239.200.0.0";
+ /** Specify a local host when opening an ET system.
+ * @see EtSystemOpenConfig#setHost(String) */
+ public static final String hostLocal = ".local";
+ /** Specify a remote host when opening an ET system.
+ * @see EtSystemOpenConfig#setHost(String) */
+ public static final String hostRemote = ".remote";
+ /** Allow any host when opening an ET system.
+ * @see EtSystemOpenConfig#setHost(String) */
+ public static final String hostAnywhere = ".anywhere";
+ /** Discover an ET system by multicasting.
+ * @see EtSystemOpenConfig#setNetworkContactMethod(int) */
+ public static final int multicast = 0;
+ /** Discover an ET system by broadcasting.
+ * @see EtSystemOpenConfig#setNetworkContactMethod(int) */
+ public static final int broadcast = 1;
+ /** Open an ET system by specifying host and port.
+ * @see EtSystemOpenConfig#setNetworkContactMethod(int) */
+ public static final int direct = 2;
+ /** Discover an ET system by broadcasting and multicasting.
+ * @see EtSystemOpenConfig#setNetworkContactMethod(int) */
+ public static final int broadAndMulticast = 3;
+ /** A default port on which to broadcast when finding an ET system. */
+ public static final int broadcastPort = 11111;
+ /** A default port on which to multicast when finding an ET system.
+ * @see EtSystemOpenConfig#addMulticastAddr(String)
+ * @see EtSystemOpenConfig#setMulticastAddrs(java.util.Collection) */
+ public static final int multicastPort = 11112;
+ /** A default port on which ET system TCP server makes connections with users.
+ * @see EtSystemOpenConfig#setTcpPort(int) */
+ public static final int serverPort = 11111;
+ /** A default time-to-live value for multicasting.
+ * @see EtSystemOpenConfig#setTTL(int) */
+ public static final int multicastTTL = 32;
+ /** A default value for the number of integers associated with each event that
+ * atations may use to select or filter that event. If this is changed, a
+ * recompilation of ET is necessary and communication with ET systems in
+ * which this value differs is impossible.
+ */
+ public static final int stationSelectInts = 6;
+ /** A limit on the length of the ET system (or file) name's length. This limit
+ * is due to the C implementation. */
+ public static final int fileNameLengthMax = 101;
+
+
+ /** A policy that chooses the first ET system to respond when broadcasting
+ * and/or multicasting to find a system anywhere or remotely.
+ * @see EtSystemOpenConfig#setResponsePolicy(int) */
+ public static final int policyFirst = 0;
+ /** A policy that chooses the first local ET system to respond when
+ * broadcasting and/or multicasting to find a system anywhere or remotely.
+ * If a local system does not respond, the first response is chosen.
+ * @see EtSystemOpenConfig#setResponsePolicy(int) */
+ public static final int policyLocal = 1;
+ /** A policy that throws an EtTooManyException when multiple ET systems
+ * respond when broadcasting and/or multicasting to find an ET system
+ * anywhere or remotely.
+ * @see EtSystemOpenConfig#setResponsePolicy(int) */
+ public static final int policyError = 2;
+
+
+ // system defaults
+
+ /** An ET system's default number of events. */
+ public static final int defaultNumEvents = 300;
+ /** An ET system's default event size in bytes. */
+ public static final int defaultEventSize = 1000;
+ /** An ET system's default maximum number of stations. */
+ public static final int defaultStationsMax = 20;
+ /** An ET system's default maximum number of attachments. */
+ public static final int defaultAttsMax = 50;
+
+ // station stuff
+
+ /** A station object's status meaning it has not been fully created yet. */
+ public static final int stationUnused = 0;
+ /** A station's status used in C implementations meaning the station is
+ * currently being created. */
+ public static final int stationCreating = 1;
+ /** A station's status meaning it exists but has no attachments. */
+ public static final int stationIdle = 2;
+ /** A station's status meaning it exists and has at least one attachment. */
+ public static final int stationActive = 3;
+ /** A station may have multiple attachments.
+ * @see EtStationConfig#setUserMode(int) */
+ public static final int stationUserMulti = 0;
+ /** A station may only have one attachment.
+ * @see EtStationConfig#setUserMode(int) */
+ public static final int stationUserSingle = 1;
+ /** A station will not block the flow of events. Once its cue is full, the
+ * station asks for no more events.
+ * @see EtStationConfig#setBlockMode(int) */
+ public static final int stationNonBlocking = 0;
+ /** A station accepts every event into its cue and may block the flow of
+ * events.
+ * @see EtStationConfig#setBlockMode(int) */
+ public static final int stationBlocking = 1;
+ /** All events are placed into a station's cue with no filtering applied
+ * (besides prescaling).
+ * @see EtStationConfig#setSelectMode(int) */
+ public static final int stationSelectAll = 1;
+ /** Events are placed into a station's cue with a predefined filtering applied
+ * (besides prescaling).
+ * @see EtStationConfig#setSelectMode(int) */
+ public static final int stationSelectMatch = 2;
+ /** Events are placed into a station's cue with a user defined filtering
+ * applied (besides prescaling).
+ * @see EtStationConfig#setSelectMode(int) */
+ public static final int stationSelectUser = 3;
+ /** Events are placed into the cues of a single group of parallel stations
+ * with a round robin distribution algorithm.
+ * @see EtStationConfig#setSelectMode(int) */
+ public static final int stationSelectRRobin = 4;
+ /** Events are placed into the cues of a single group of parallel stations
+ * in an algorithm designed to keep the cues equal in value.
+ * @see EtStationConfig#setSelectMode(int) */
+ public static final int stationSelectEqualCue = 5;
+ /** Events owned by a crashed user process are restored to the ET system in
+ * the output list of the attachment's station.
+ * @see EtStationConfig#setRestoreMode(int) */
+ public static final int stationRestoreOut = 0;
+ /** Events owned by a crashed user process are restored to the ET system in
+ * the input list of the attachment's station.
+ * @see EtStationConfig#setRestoreMode(int) */
+ public static final int stationRestoreIn = 1;
+ /** Events owned by a crashed user process are restored to the ET system by
+ * putting them in GRAND_CENTRAL station (recycling them).
+ * @see EtStationConfig#setRestoreMode(int) */
+ public static final int stationRestoreGC = 2;
+ /** Events owned by a crashed user process attached to a parallel station
+ * are restored to the ET system by redistributing them among that group
+ * of parallel stations (recycling them). Also, if the station has no more
+ * attachments, the events in its input list are also redistributed (unlike
+ * in stationRestoreGC mode where these events are put in the station's output
+ * list).
+ * @see EtStationConfig#setRestoreMode(int) */
+ public static final int stationRestoreRedist = 3;
+ /** Events flow "normally" - that is serially - through a station.
+ * @see EtStationConfig#setFlowMode(int) */
+ public static final int stationSerial = 0;
+ /** Events flow in parallel through stations in a single group.
+ * @see EtStationConfig#setFlowMode(int) */
+ public static final int stationParallel = 1;
+ /** Events flow in parallel through stations in a single group with this station
+ * as the head of that group.
+ * @see EtStationConfig#setFlowMode(int) */
+ public static final int stationParallelHead = 2;
+
+ // station defaults
+
+ /** A default input list cue size for a nonblocking station.
+ * @see EtStationConfig#setCue(int) */
+ public static final int defaultStationCue = 10;
+ /** A default prescale value for a station.
+ * @see EtStationConfig#setPrescale(int) */
+ public static final int defaultStationPrescale = 1;
+
+ // talk to C language ET systems with structures
+
+ /** C structure state value for talking to C language ET systems. */
+ public static final int structNew = 0;
+ /** C structure state value for talking to C language ET systems. */
+ public static final int structOk = 1;
+
+ /** Add station to end of linked list. */
+ public static final int end = -1;
+ /** Make added station head of a new group of parallel stations. */
+ public static final int newHead = -2;
+
+ // Events
+
+ /** Low event priority.
+ * @see EtEvent#setPriority(org.jlab.coda.et.enums.Priority) */
+ public static final int low = 0;
+ /** High event priority.
+ * @see EtEvent#setPriority(org.jlab.coda.et.enums.Priority) */
+ public static final int high = 1;
+ /** Parse event priority information. */
+ public static final int priorityMask = 0x1;
+ /** Event has been obtained with getEvents, not newEvents. */
+ public static final int eventUsed = 0;
+ /** Event has been obtained with newEvents, not getEvents. */
+ public static final int eventNew = 1;
+ /** System is event owner */
+ public static final int system = -1;
+
+ /** User sleeps when waiting for events to fill a station's empty input list. */
+ public static final int sleep = 0;
+ /** User waits for a specified time when waiting for events to fill a
+ * station's empty input list. */
+ public static final int timed = 1;
+ /** User does not wait for events to fill station's empty input list, but
+ * returns immediately. */
+ public static final int async = 2;
+ /** User intends to modify the event's data. */
+ public static final int modify = 4;
+ /** User intends to modify only the event's header information. */
+ public static final int modifyHeader = 8;
+ /** User wants events automatically dumped (not put) if data is not modified. */
+ public static final int dump = 16;
+ /** Parse event waiting information. */
+ public static final int waitMask = 0x3;
+
+ //public static final int openNoWait = 0;
+ //public static final int openWait = 1;
+
+ //public static final int remote = 0;
+ //public static final int local = 1;
+ //public static final int localNoShare = 2;
+
+ //public static final String subnetDefault = "default";
+ //public static final String subnetAll = "all";
+
+ /** An event's data is OK. */
+ public static final int dataOk = 0;
+ /** An event's data is corrupted. */
+ public static final int dataCorrupt = 1;
+ /** An event's data may possibly be corrupted. */
+ public static final int dataPossiblyCorrupt = 2;
+ /** Parse data status information. */
+ public static final int dataMask = 0x30;
+ /** Parse data status information. */
+ public static final int dataShift = 4;
+
+ /** An event's data is big endian. */
+ public static final int endianBig = 0;
+ /** An event's data is little endian. */
+ public static final int endianLittle = 1;
+ /** An event's data endian is the same as the local host's. */
+ public static final int endianLocal = 2;
+ /** An event's data endian is opposite of the local host's. */
+ public static final int endianNotLocal = 3;
+ /** An event's data endian is to be switched. */
+ public static final int endianSwitch = 4;
+
+ /** An event's data does not need to be swapped to be the same endian as the
+ * local host's. */
+ public static final int noSwap = 0;
+ /** An event's data needs to be swapped to be the same endian as the local
+ * host's. */
+ public static final int swap = 1;
+
+ /** Print out no status messages. */
+ public static final int debugNone = 0;
+ /** Print out only severe error messages. */
+ public static final int debugSevere = 1;
+ /** Print out severe and normal error messages. */
+ public static final int debugError = 2;
+ /** Print out all error and warning messages. */
+ public static final int debugWarn = 3;
+ /** Print out all error, warning, and informational messages. */
+ public static final int debugInfo = 4;
+
+ // C language ET system error codes
+
+ /** No error. */
+ public static final int ok = 0;
+ /** General error. */
+ public static final int error = -1;
+ /** Error specifying too many of something. */
+ public static final int errorTooMany = -2;
+ /** Error specifying that something already exists. */
+ public static final int errorExists = -3;
+ /** Error when a thread was told to wake up from a blocking read. */
+ public static final int errorWakeUp = -4;
+ /** Error specifying a time out. */
+ public static final int errorTimeout = -5;
+ /** Error specifying that a station has an empty input list. */
+ public static final int errorEmpty = -6;
+ /** Error specifying that a station's input list is being accessed by
+ * another thread or process. */
+ public static final int errorBusy = -7;
+ /** Error specifying that the ET system is dead. */
+ public static final int errorDead = -8;
+ /** Error specifying problems in a network read. */
+ public static final int errorRead = -9;
+ /** Error specifying problems in a network write. */
+ public static final int errorWrite = -10;
+ /** Error not used in java ET. */
+ public static final int errorRemote = -11;
+ /** Error not used in java ET. */
+ public static final int errorNoRemote = -12;
+ /** Error when memory asked for is too big. */
+ public static final int errorTooBig = -13;
+ /** Error when no memory available. */
+ public static final int errorNoMemory = -14;
+ /** Error when argument has bad value. */
+ public static final int errorBadArg = -15;
+ /** Error when socket error. */
+ public static final int errorSocket = -16;
+ /** Error when network error. */
+ public static final int errorNetwork = -17;
+
+
+ // constants from private.h
+
+
+ /**
+ * String length of dotted-decimal, ip address string
+ * Some systems - but not all - define INET_ADDRSTRLEN
+ * ("ddd.ddd.ddd.ddd\0" = 16)
+ */
+ public static final int ipAddrStrLen = 16;
+
+ /**
+ * MAXHOSTNAMELEN is defined to be 256 on Solaris and is the max length
+ * of the host name so we add one for the terminator. On Linux the
+ * situation is less clear but 257 appears to be the max (whether that
+ * includes termination is not clear).
+ * We need it to be uniform across all platforms since we transfer
+ * this info across the network. Define it to be 256 for everyone.
+ */
+ public static final int maxHostNameLen = 256;
+
+ /** Java ET systems are 32 bit since arrays can only be of size Integer.MAX_VALUE. */
+ public static final int bit64 = 0;
+ /** Major ET version number. */
+ public static final int version = 12;
+ /** Minor ET version number. */
+ public static final int minorVersion = 0;
+ /** Maximum number of attachments to an ET system. */
+ public static final int attachmentsMax = 110;
+ //static final int ipAddrStrLen = 16;
+ //static final int maxHostNameLen = 256;
+
+ /** ET system was implemented in the C language. */
+ public static final int langC = 0;
+ /** ET system was implemented in the C++ language. */
+ public static final int langCpp = 1;
+ /** ET system was implemented in the Java language. */
+ public static final int langJava = 2;
+
+ /** Shared memory layout from C language ET system. */
+ public static final int systemTypeC = 1;
+ /** Shared memory layout from Java language ET system. */
+ public static final int systemTypeJava = 2;
+
+ /** Shared memory layout from Java language ET system. */
+ public static final int initialSharedMemBytes = 64;
+
+ /** A mutex is not locked. Relevant only to C language ET systems. */
+ public static final int mutexUnlocked = 0;
+ /** A mutex is locked. Relevant only to C language ET systems. */
+ public static final int mutexLocked = 1;
+ /** The local UNIX operating system allows multiple processes to share POSIX
+ * mutexes. Relevant only to C language ET systems. */
+ public static final int mutexShare = 0;
+ /** The local UNIX operating system does not allow multiple processes to share
+ * POSIX mutexes. Relevant only to C language ET systems. */
+ public static final int mutexNoShare = 1;
+
+ //static final int attUnused = 0;
+ //static final int attActive = 1;
+ /** An attachment is not being told to wake up. */
+ public static final int attContinue = 0;
+ /** An attachment is being told to wake up. */
+ public static final int attQuit = 1;
+ /** An attachment is not blocked on a read statement. */
+ public static final int attUnblocked = 0;
+ /** An attachment is blocked on a read statement. */
+ public static final int attBlocked = 1;
+
+ // codes sent over the network to identify ET system routines to call
+ public static final int netEvGetL = 0;
+ public static final int netEvsGetL = 1;
+ public static final int netEvPutL = 2;
+ public static final int netEvsPutL = 3;
+ public static final int netEvNewL = 4;
+ public static final int netEvsNewL = 5;
+ public static final int netEvDumpL = 6;
+ public static final int netEvsDumpL = 7;
+ public static final int netEvsNewGrpL = 8;
+
+ public static final int netEvGet = 20;
+ public static final int netEvsGet = 21;
+ public static final int netEvPut = 22;
+ public static final int netEvsPut = 23;
+ public static final int netEvNew = 24;
+ public static final int netEvsNew = 25;
+ public static final int netEvDump = 26;
+ public static final int netEvsDump = 27;
+ public static final int netEvsNewGrp = 28;
+
+ public static final int netAlive = 40;
+ public static final int netWait = 41;
+ public static final int netClose = 42;
+ public static final int netFClose = 43;
+ public static final int netWakeAtt = 44;
+ public static final int netWakeAll = 45;
+
+ public static final int netStatAtt = 60;
+ public static final int netStatDet = 61;
+ public static final int netStatCrAt = 62;
+ public static final int netStatRm = 63;
+ public static final int netStatSPos = 64;
+ public static final int netStatGPos = 65;
+
+ public static final int netStatIsAt = 80;
+ public static final int netStatEx = 81;
+ public static final int netStatSSw = 82;
+ public static final int netStatGSw = 83;
+ public static final int netStatLib = 84;
+ public static final int netStatFunc = 85;
+ public static final int netStatClass = 86;
+
+ public static final int netStatGAtts = 100;
+ public static final int netStatStatus = 101;
+ public static final int netStatInCnt = 102;
+ public static final int netStatOutCnt = 103;
+ public static final int netStatGBlock = 104;
+ public static final int netStatGUser = 105;
+ public static final int netStatGRestore = 106;
+ public static final int netStatGPre = 107;
+ public static final int netStatGCue = 108;
+ public static final int netStatGSelect = 109;
+
+ public static final int netStatSBlock = 115;
+ public static final int netStatSUser = 116;
+ public static final int netStatSRestore = 117;
+ public static final int netStatSPre = 118;
+ public static final int netStatSCue = 119;
+
+ public static final int netAttPut = 130;
+ public static final int netAttGet = 131;
+ public static final int netAttDump = 132;
+ public static final int netAttMake = 133;
+
+ public static final int netSysTmp = 150;
+ public static final int netSysTmpMax = 151;
+ public static final int netSysStat = 152;
+ public static final int netSysStatMax = 153;
+ public static final int netSysProc = 154;
+ public static final int netSysProcMax = 155;
+ public static final int netSysAtt = 156;
+ public static final int netSysAttMax = 157;
+ public static final int netSysHBeat = 158;
+ public static final int netSysPid = 159;
+ public static final int netSysGrp = 160;
+
+ public static final int netSysData = 170;
+ public static final int netSysHist = 171;
+ public static final int netSysGrps = 172;
+}
hps-et-java/src/main/java/org/jlab/coda/et
diff -N EtEvent.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtEvent.java 13 Feb 2012 22:50:52 -0000 1.3
@@ -0,0 +1,216 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2010 Jefferson Science Associates, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et;
+
+import org.jlab.coda.et.exception.EtException;
+import org.jlab.coda.et.enums.Modify;
+import org.jlab.coda.et.enums.Priority;
+import org.jlab.coda.et.enums.DataStatus;
+import org.jlab.coda.et.enums.Age;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * Interface used to define methods necessary to be an Event.
+ */
+public interface EtEvent {
+
+ /**
+ * Initialize an event's fields. Called for an event each time it passes
+ * through GRAND_CENTRAL station.
+ */
+ public void init();
+
+
+ // getters
+
+
+ /**
+ * Gets the event's id number.
+ * @return event's id number.
+ */
+ public int getId();
+
+ /**
+ * Gets the age of the event, either {@link Age#NEW} if a new event obtained through
+ * calling {@link EtSystem#newEvents(EtAttachment, org.jlab.coda.et.enums.Mode, int, int, int)}
+ * or {@link Age#USED} if obtained through calling
+ * {@link EtSystem#getEvents(EtAttachment, org.jlab.coda.et.enums.Mode, org.jlab.coda.et.enums.Modify, int, int)}.
+ *
+ * @return age of the event.
+ */
+ public Age getAge();
+
+ /**
+ * Gets the group the event belongs to (1, 2, ...) if ET system events are divided into groups.
+ * If not, group = 1. Used so some producers don't hog events from others.
+ *
+ * @return the group the event belongs to.
+ */
+ public int getGroup();
+
+ /**
+ * Gets the event's priority, either high {@link Priority#HIGH} or low {@link Priority#LOW}.
+ * Low priority is normal while high priority events get placed at the front of stations'
+ * input and output event lists.
+ *
+ * @return event's priority.
+ */
+ public Priority getPriority();
+
+ /**
+ * Gets the length of the data in bytes.
+ * @return length of the data in bytes.
+ */
+ public int getLength();
+
+ /**
+ * Gets the status of the data (set by the system), which can be OK {@link DataStatus#OK},
+ * corrupted {@link DataStatus#CORRUPT}, or possibly corrupted
+ * {@link DataStatus#POSSIBLYCORRUPT}. Data is OK by default, it is never labeled
+ * as corrupt but can be labeled as possible corrupt if the process owning an
+ * event crashes and the system recovers it.
+ *
+ * @return status of the data.
+ */
+ public DataStatus getDataStatus();
+
+ /**
+ * Gets the event's modify value when receiving it over the network.
+ * This specifies whether the user wants to read the event only, will modify only
+ * the event header (everything except the data), or will modify the data and/or header.
+ * Modifying the data and/or header is {@link Modify#ANYTHING}, modifying only the header
+ * is {@link Modify#HEADER}, else the default assumed, {@link Modify#NOTHING},
+ * is that nothing is modified resulting in this event being put back into
+ * the ET system (by remote server) immediately upon being copied and that copy
+ * sent to the user.
+ *
+ * @return event's modify value.
+ */
+ public Modify getModify();
+
+ /**
+ * Gets the event's control array.
+ * This is an array of integers which can be used for any purpose by the user.
+ *
+ * @return event's control array.
+ */
+ public int[] getControl();
+
+ /**
+ * Gets the data array which is backing the event's data buffer if there is one.
+ * Any changes to the array will be reflected in the buffer.
+ * If there is no backing data array, as is the case when a user connects
+ * to a local, C-based ET system (memory mapped buffer) then an exception
+ * is thrown.
+ *
+ * @return data array which is backing the event's data buffer
+ * @throws UnsupportedOperationException if there is no backing array
+ */
+ public byte[] getData() throws UnsupportedOperationException;
+
+ /**
+ * Gets the event's data buffer.
+ * @return event's data buffer.
+ */
+ public ByteBuffer getDataBuffer();
+
+ /**
+ * Gets the attachment id of the attachment which owns or got the event.
+ * If it's owned by the system its value is {@link EtConstants#system}.
+ *
+ * @return id of owning attachment or {@link EtConstants#system} if system owns it
+ */
+ public int getOwner();
+
+ /**
+ * Gets the event data's byte order.
+ * @return event data's byte order
+ */
+ public ByteOrder getByteOrder();
+
+ /**
+ * Gets the raw byte order data (0x04030201 or 0x01020304).
+ * @return raw byte order data (0x04030201 or 0x01020304).
+ */
+ public int getRawByteOrder();
+
+
+ // setters
+
+
+ /**
+ * Sets the event's priority, either high {@link Priority#HIGH} or low {@link Priority#LOW}.
+ * Low priority is normal while high priority events get placed at the front of stations'
+ * input and output event lists.
+ *
+ * @param pri event priority
+ */
+ public void setPriority(Priority pri);
+
+ /**
+ * Sets the event's data length in bytes.
+ *
+ * @param len data length
+ * @throws EtException if length is less than zero
+ */
+ public void setLength(int len) throws EtException;
+
+ /**
+ * Sets the event's control array by copying it into the event.
+ *
+ * @param con control array
+ * @throws EtException if control array has the wrong number of elements
+ */
+ public void setControl(int[] con) throws EtException;
+
+ /**
+ * Set the event data's byte order.
+ * @param order data's byte order
+ */
+ void setByteOrder(ByteOrder order);
+
+ /**
+ * Set the event data's byte order by using values consistent with C-based ET systems,
+ * {@link EtConstants#endianBig}, {@link EtConstants#endianLittle}, {@link EtConstants#endianLocal},
+ * {@link EtConstants#endianNotLocal}, or {@link EtConstants#endianSwitch}.
+ *
+ * @param endian endian value
+ * @throws EtException if argument is a bad value
+ */
+ void setByteOrder(int endian) throws EtException;
+
+ /**
+ * Set the event data's byte order as big with 0x04030201 or
+ * as little with 0x01020304.
+ *
+ * @param byteOrder data's byte order as big with 0x04030201 or
+ * as little with 0x01020304.
+ */
+ void setRawByteOrder(int byteOrder) throws EtException;
+
+
+ // miscellaneous
+
+
+ /**
+ * Tells caller if the event data needs to be swapped in order to be the
+ * same byte order as the local JVM.
+ *
+ * @return <code>true</code> if swapping is needed, otherwise <code>false</code>
+ */
+ public boolean needToSwap();
+}
hps-et-java/src/main/java/org/jlab/coda/et
diff -N EtEventImpl.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtEventImpl.java 13 Feb 2012 22:50:52 -0000 1.3
@@ -0,0 +1,648 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et;
+
+import java.lang.*;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.jlab.coda.et.exception.*;
+import org.jlab.coda.et.enums.Age;
+import org.jlab.coda.et.enums.Priority;
+import org.jlab.coda.et.enums.DataStatus;
+import org.jlab.coda.et.enums.Modify;
+
+/**
+ * This class defines an ET event.
+ *
+ * @author Carl Timmer
+ */
+
+public class EtEventImpl implements EtEvent {
+
+ // convenience variables
+ private static final int numSelectInts = EtConstants.stationSelectInts;
+ private static final int[] controlInitValues = new int[numSelectInts];
+
+ /** Unique id number (place of event in C-based ET system). */
+ private int id;
+
+ /**
+ * Specifies whether the event was obtained as a new event (through
+ * {@link EtSystem#newEvents(EtAttachment, org.jlab.coda.et.enums.Mode, int, int, int)}),
+ * or as a "used" event (through
+ * {@link EtSystem#getEvents(EtAttachment, org.jlab.coda.et.enums.Mode, org.jlab.coda.et.enums.Modify, int, int)}).
+ * If the event is new, its value is {@link Age#NEW} otherwise {@link Age#USED}.
+ */
+ private Age age;
+
+ /** Group to which this event belongs (1, 2, ...) if ET system events are divided into groups.
+ * If not, group = 1. Used so some producers don't hog events from others. */
+ private int group;
+
+ /** Event priority which is either {@link Priority#HIGH} or {@link Priority#LOW}. */
+ private Priority priority;
+
+ /**
+ * The attachment id which owns or got the event. If it's owned by the
+ * system its value is {@link EtConstants#system}.
+ */
+ private int owner;
+
+ /** Length of the valid data in bytes. */
+ private int length;
+
+ /** Size of the data buffer in bytes. */
+ private int memSize;
+
+ /**
+ * Size limit of events' data buffers in bytes. This is important to
+ * know when Java users connect to C-based ET systems. The C-based ET
+ * systems cannot allow users to increase an event's data size beyond
+ * what was originally allocated. In Java systems there is no size
+ * limit besides computer and JVM limits.
+ */
+ private int sizeLimit;
+
+ /**
+ * Status of the data. It can be ok {@link DataStatus#OK}, corrupted
+ * {@link DataStatus#CORRUPT}, or possibly corrupted
+ * {@link DataStatus#POSSIBLYCORRUPT}.
+ */
+ private DataStatus dataStatus;
+
+ /**
+ * Specifies whether the user wants to read the event only, will modify only the event header
+ * (everything except the data), or will modify the data and/or header.
+ * Modifying the data and/or header is {@link Modify#ANYTHING}, modifying only the header
+ * is {@link Modify#HEADER}, else the default assumed, {@link Modify#NOTHING},
+ * is that nothing is modified resulting in this event being put back into
+ * the ET system (by remote server) immediately upon being copied and that copy
+ * sent to the user.
+ */
+ private Modify modify;
+
+ /**
+ * An integer used to keep track of the data's byte ordering.
+ * Values can be 0x04030201 (local endian) or 0x01020304 (not local endian).
+ */
+ private int byteOrder;
+
+ /**
+ * An array of integers normally used by stations to filter events out of
+ * their input lists. It is used to control the flow of events through
+ * the ET system.
+ */
+ private int[] control;
+
+ /**
+ * This byte array backs the dataBuffer when receiving events from a Java-based
+ * ET system or from over the network. If connected to a local, C-based ET system,
+ * a MappedByteBuffer is used which has <b>no</b> backing array.
+ */
+ private byte[] data;
+
+ /** This ByteBuffer object is a wrapper for the data byte array for convenience. */
+ private ByteBuffer dataBuffer;
+
+ /** Flag specifying whether the ET system process is Java based or not. */
+ private boolean isJava;
+
+
+
+ /**
+ * Creates an event object for users of Java-based ET systems or by the
+ * system itself. Event objects are only created once in the ET
+ * system process - when the ET system is started up.
+ *
+ * @param size size of the data array in bytes
+ */
+ public EtEventImpl(int size) {
+ memSize = size;
+ isJava = true;
+ data = new byte[size];
+ control = new int[numSelectInts];
+ dataBuffer = ByteBuffer.wrap(data);
+ init();
+ }
+
+ /**
+ * Creates an event object for ET system users when connecting to ET systems
+ * over the network. Called by
+ * {@link EtSystem#getEvents(EtAttachment, org.jlab.coda.et.enums.Mode,Modify,int,int)},
+ * and
+ * {@link EtSystem#newEvents(EtAttachment, org.jlab.coda.et.enums.Mode,boolean,int,int,int,int)}.
+ *
+ * @param size size of the data array in bytes.
+ * @param limit limit on the size of the data array in bytes. Only used
+ * for C-based ET systems.
+ * @param isJava is ET system Java based?
+ * @param noBuffer forget about allocating byte array and ByteBuffer?
+ */
+ EtEventImpl(int size, int limit, boolean isJava, boolean noBuffer) {
+ memSize = size;
+ sizeLimit = limit;
+ this.isJava = isJava;
+ control = new int[numSelectInts];
+ if (!noBuffer) {
+ data = new byte[size];
+ dataBuffer = ByteBuffer.wrap(data);
+ }
+ init();
+ }
+
+ /**
+ * Creates an event object for ET system users when connecting to local, C-based ET systems
+ * and using native methods to call et_events_get.
+ * No data array or buffer are created since we will be using shared
+ * memory and it will be taken care of later. Tons of args since it's a lot easier in
+ * JNI to call one method with lots of args then to call lots of set methods on one object.
+ *
+ * @param size {@link #memSize}
+ * @param limit {@link #sizeLimit}
+ * @param status {@link #dataStatus}
+ * @param id {@link #id}
+ * @param age {@link #age}
+ * @param owner {@link #owner}
+ * @param modify {@link #modify}
+ * @param length {@link #length}
+ * @param priority {@link #modify}
+ * @param byteOrder {@link #byteOrder}
+ * @param control {@link #control}
+ */
+ EtEventImpl(int size, int limit, int status, int id, int age, int owner,
+ int modify, int length, int priority, int byteOrder, int[] control) {
+
+ isJava = false;
+ memSize = size;
+ sizeLimit = limit;
+ dataStatus = DataStatus.getStatus(status);
+ this.id = id;
+ this.age = Age.getAge(age);
+ this.owner = owner;
+ this.modify = Modify.getModify(modify);
+ this.length = length;
+ this.priority = Priority.getPriority(priority);
+ this.byteOrder = byteOrder;
+ this.control = control.clone();
+ }
+
+ /**
+ * Creates an event object for ET system users when connecting to local, C-based ET systems
+ * and using native methods to call et_events_get. The ByteBuffer object is created in JNI
+ * code and directly "wraps" the et data pointer from the ET event obtained through
+ * et_events_get.
+ * Tons of args since it's a lot easier in
+ * JNI to call one method with lots of args then to call lots of set methods on one object.
+ *
+ * @param size {@link #memSize}
+ * @param limit {@link #sizeLimit}
+ * @param status {@link #dataStatus}
+ * @param id {@link #id}
+ * @param age {@link #age}
+ * @param owner {@link #owner}
+ * @param modify {@link #modify}
+ * @param length {@link #length}
+ * @param priority {@link #modify}
+ * @param byteOrder {@link #byteOrder}
+ * @param control {@link #control}
+ * @param buffer {@link #dataBuffer}
+ */
+ EtEventImpl(int size, int limit, int status, int id, int age, int owner,
+ int modify, int length, int priority, int byteOrder, int[] control,
+ ByteBuffer buffer) {
+
+ isJava = false;
+ memSize = size;
+ sizeLimit = limit;
+ dataStatus = DataStatus.getStatus(status);
+ this.id = id;
+ this.age = Age.getAge(age);
+ this.owner = owner;
+ this.modify = Modify.getModify(modify);
+ this.length = length;
+ this.priority = Priority.getPriority(priority);
+ this.byteOrder = byteOrder;
+ this.control = control;
+ dataBuffer = buffer;
+ }
+
+ /**
+ * Creates an event object for ET system users when connecting to local, C-based ET systems
+ * and using native methods to call et_events_new_group.
+ * No data array or buffer are created since we will be using shared
+ * memory and it will be taken care of later.
+ *
+ * @param limit {@link #sizeLimit}, {@link #memSize}
+ * @param id {@link #id}
+ * @param owner {@link #owner}
+ */
+ EtEventImpl(int limit, int id, int owner) {
+
+ age = Age.NEW;
+ priority = Priority.LOW;
+ isJava = false;
+ byteOrder = 0x04030201;
+ length = 0;
+ modify = Modify.NOTHING;
+ dataStatus = DataStatus.OK;
+ control = new int[numSelectInts];
+
+ memSize = limit;
+ sizeLimit = limit;
+ this.id = id;
+ this.owner = owner;
+ }
+
+ /**
+ * Creates an event object by duplicating another.
+ *
+ * @param ev event to duplicate
+ */
+ public EtEventImpl(EtEventImpl ev) {
+ this.isJava = ev.isJava;
+ this.memSize = ev.memSize;
+ this.sizeLimit = ev.sizeLimit;
+ this.dataStatus = ev.dataStatus;
+ this.id = ev.id;
+ this.age = ev.age;
+ this.owner = ev.owner;
+ this.group = ev.group;
+ this.modify = ev.modify;
+ this.length = ev.length;
+ this.priority = ev.priority;
+ this.byteOrder = ev.byteOrder;
+
+ this.control = ev.control.clone();
+ this.data = ev.data.clone();
+
+ this.dataBuffer = ByteBuffer.wrap(data);
+ this.dataBuffer.limit(ev.dataBuffer.limit());
+ this.dataBuffer.position(ev.dataBuffer.position());
+ // Cannot copy the mark, oh well.
+ }
+
+ /** Initialize an event's fields. Called for an event each time it passes
+ * through GRAND_CENTRAL station. */
+ public void init() {
+ age = Age.NEW;
+ priority = Priority.LOW;
+ owner = EtConstants.system;
+ length = 0;
+ modify = Modify.NOTHING;
+ byteOrder = 0x04030201;
+ dataStatus = DataStatus.OK;
+ System.arraycopy(controlInitValues, 0, control, 0, numSelectInts);
+ }
+
+
+ // getters
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Age getAge() {
+ return age;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getGroup() {
+ return group;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Priority getPriority() {
+ return priority;
+ }
+
+ /**
+ * Get int value associated with Priority enum.
+ * @return int value associated with Priority enum
+ */
+ public int getPriorityValue() {
+ return priority.getValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getOwner() {
+ return owner;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getLength() {
+ return length;
+ }
+
+ /**
+ * Gets the size of the data buffer in bytes.
+ * @return size of the data buffer in bytes
+ */
+ public int getMemSize() {
+ return memSize;
+ }
+
+ /**
+ * Gets the size limit of the data buffer in bytes when using a C-based ET system.
+ * @return size size limit of the data buffer in bytes
+ */
+ public int getSizeLimit() {
+ return sizeLimit;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DataStatus getDataStatus() {
+ return dataStatus;
+ }
+
+ /**
+ * Get int value associated with DataStatus enum.
+ * @return int value associated with DataStatus enum
+ */
+ public int getDataStatusValue() {
+ return dataStatus.getValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Modify getModify() {
+ return modify;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ByteOrder getByteOrder() {
+ // java is always big endian
+ return ((byteOrder == 0x04030201) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getRawByteOrder() {
+ return byteOrder;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int[] getControl() {
+ return control.clone();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public byte[] getData() throws UnsupportedOperationException {
+ return dataBuffer.array();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ByteBuffer getDataBuffer() {
+ return dataBuffer;
+ }
+
+
+ // setters
+
+
+ /**
+ * Sets the event's id number.
+ * @param id event's id number
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ /**
+ * Sets the age of the event which is {@link Age#NEW} for new events obtained by calling
+ * {@link EtSystem#newEvents(EtAttachment, org.jlab.coda.et.enums.Mode, int, int, int)}),
+ * or {@link Age#NEW} for "used" event obtained by calling
+ * {@link EtSystem#getEvents(EtAttachment, org.jlab.coda.et.enums.Mode, org.jlab.coda.et.enums.Modify, int, int)}).
+ *
+ * @param age age of the event
+ */
+ public void setAge(Age age) {
+ this.age = age;
+ }
+
+ /**
+ * Sets the group the event belongs to: (1, 2, ...) if ET system events are divided into groups,
+ * or group = 1 if not.
+ *
+ * @param group group the event belongs to
+ */
+ public void setGroup(int group) {
+ this.group = group;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setPriority(Priority pri) {
+ priority = pri;
+ }
+
+ /**
+ * Sets the owner of the event (attachment using event or system).
+ * @param owner owner of event (attachment using event or system)
+ */
+ public void setOwner(int owner) {
+ this.owner = owner;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setLength(int len) throws EtException {
+ if (len < 0 || len > sizeLimit) {
+ throw new EtException("bad value for event data length");
+ }
+ length = len;
+ }
+
+ /**
+ * Set the length of valid data from server where sizeLimit may be 0.
+ * @param len length of valid data
+ * @throws EtException if len is negative
+ */
+ public void setLengthFromServer(int len) throws EtException {
+ if (len < 0) {
+ throw new EtException("bad value for event data length");
+ }
+ length = len;
+ }
+
+ /**
+ * Sets the size of the data buffer in bytes.
+ * @param memSize size of the data buffer in bytes
+ */
+ public void setMemSize(int memSize) {
+ this.memSize = memSize;
+ }
+
+ /**
+ * Sets the event's data status. It can be ok {@link DataStatus#OK} which is the default,
+ * corrupted {@link DataStatus#CORRUPT} which is never used actually, or possibly corrupted
+ * {@link DataStatus#POSSIBLYCORRUPT} which occurs when a process holding the event crashes
+ * and the system recovers it.
+ *
+ * @param status data status
+ */
+ public void setDataStatus(DataStatus status) {
+ dataStatus = status;
+ }
+
+ /**
+ * Sets whether the user wants to read the event only, will modify only the event header
+ * (everything except the data), or will modify the data and/or header.
+ * Modifying the data and/or header is {@link Modify#ANYTHING}, modifying only the header
+ * is {@link Modify#HEADER}, else the default assumed, {@link Modify#NOTHING},
+ * is that nothing is modified resulting in this event being put back into
+ * the ET system (by remote server) immediately upon being copied and that copy
+ * sent to the user.
+ *
+ * @param modify
+ */
+ public void setModify(Modify modify) {
+ this.modify = modify;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setByteOrder(int endian) throws EtException {
+ if (endian == EtConstants.endianBig) {
+ byteOrder = 0x04030201;
+ }
+ else if (endian == EtConstants.endianLittle) {
+ byteOrder = 0x01020304;
+ }
+ else if (endian == EtConstants.endianLocal) {
+ byteOrder = 0x04030201;
+ }
+ else if (endian == EtConstants.endianNotLocal) {
+ byteOrder = 0x01020304;
+ }
+ else if (endian == EtConstants.endianSwitch) {
+ byteOrder = Integer.reverseBytes(byteOrder);
+ }
+ else {
+ throw new EtException("bad value for byte order");
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setByteOrder(ByteOrder order) {
+ if (order == null) return;
+ if (order == ByteOrder.BIG_ENDIAN) {
+ byteOrder = 0x04030201;
+ }
+ else {
+ byteOrder = 0x01020304;
+ }
+ }
+
+ /**
+ * [log in to unmask] This is how byte order is stored internally in
+ * this object and how it is stored in the C code.
+ *
+ * @param {@inheritDoc}
+ */
+ public void setRawByteOrder(int byteOrder) throws EtException {
+ if (byteOrder != 0x04030201 && byteOrder != 0x01020304) {
+ throw new EtException("invalid value for byteOrder arg");
+ }
+
+ this.byteOrder = byteOrder;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setControl(int[] con) throws EtException {
+ if (con == null) return;
+ if (con.length != numSelectInts) {
+ throw new EtException("wrong number of elements in control array");
+ }
+ System.arraycopy(con, 0, control, 0, numSelectInts);
+ }
+
+ /**
+ * Sets the event's data without copying. The length and memSize members of
+ * the event are automatically set to the data array's length.
+ * Used only by local Java ET system in newEvents to increase data array size.
+ *
+ * @param data data array
+ */
+ public void setData(byte[] data) {
+ // In C-based ET systems, user cannot increase data size beyond
+ // what was initially allocated, but this is only used by local Java ET system.
+ if (data == null) return;
+ this.data = data;
+ length = data.length;
+ memSize = data.length;
+ }
+
+ /**
+ * Sets the event's data buffer (must be backed by data array).
+ * This is used when reading data from shared memory and
+ * also if remote user gets new events with the no-allocate flag
+ * set. In the latter case, the user must set the data buffer
+ * explicitly or an exception will result when trying to put the
+ * event back. In any case, using this method should only be done
+ * by the expert user.
+ *
+ * @param dataBuffer event's data buffer (must be backed by data array)
+ */
+ public void setDataBuffer(ByteBuffer dataBuffer) {
+ this.dataBuffer = dataBuffer;
+ }
+
+
+ // miscellaneous
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean needToSwap() {
+ return byteOrder != 0x04030201;
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et
diff -N EtEventSelectable.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtEventSelectable.java 13 Feb 2012 22:50:52 -0000 1.3
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et;
+
+import org.jlab.coda.et.system.StationLocal;
+import org.jlab.coda.et.system.SystemCreate;
+
+/**
+ * This interface defines a method to use for custom event selection in a station.
+ *
+ * @author Carl Timmer
+ */
+
+public interface EtEventSelectable {
+
+ /**
+ * An event selection method must follow this form.
+ * @param sys the ET system object
+ * @param st the station using a user-defned selection method
+ * @param ev event being evaluated for selection
+ */
+ public boolean select(SystemCreate sys, StationLocal st, EtEvent ev);
+
+}
hps-et-java/src/main/java/org/jlab/coda/et
diff -N EtJniAccess.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtJniAccess.java 13 Feb 2012 22:50:52 -0000 1.3
@@ -0,0 +1,250 @@
+package org.jlab.coda.et;
+
+import org.jlab.coda.et.exception.*;
+
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.HashMap;
+
+
+/**
+ * This class handles all calls to native methods which, in turn,
+ * makes calls to the C ET library routines to get, new, put, and dump events.
+ */
+class EtJniAccess {
+
+ // Load in the necessary library when this class is loaded
+ static {
+ try {
+ System.loadLibrary("et_jni");
+ }
+ catch (Error e) {
+ System.out.println("error loading libet_jni.so");
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ }
+
+ /** Serialize access to classMap and creation of these objects. */
+ static ReentrantLock classLock = new ReentrantLock();
+
+ /** Store EtJniAccess objects here since we only want to create 1 object per ET system. */
+ static HashMap<String, EtJniAccess> classMap = new HashMap<String, EtJniAccess>(10);
+
+
+ /**
+ * Get an instance of this object for a particular ET system. Only one EtJniAccess object
+ * is created for a particular ET system.
+ *
+ * @param etName name of ET system to open
+ * @return object of this type to use for interaction with local, C-based ET system
+ * @throws EtException for any failure to open ET system except timeout
+ * @throws EtTimeoutException for failure to open ET system within the specified time limit
+ */
+ static EtJniAccess getInstance(String etName) throws EtException, EtTimeoutException {
+ try {
+ classLock.lock();
+
+ // See if we've already opened the ET system being asked for, if so, return that
+ if (classMap.containsKey(etName)) {
+//System.out.println("USE ALREADY EXISTING ET JNI OBJECT for et -> " + etName);
+ EtJniAccess jni = classMap.get(etName);
+ jni.numberOpens++;
+//System.out.println("numberOpens = " + jni.numberOpens);
+ return jni;
+ }
+
+ EtJniAccess jni = new EtJniAccess();
+ jni.openLocalEtSystem(etName);
+ jni.etSystemName = etName;
+ jni.numberOpens = 1;
+//System.out.println("CREATING ET JNI OBJECT for et -> " + etName);
+//System.out.println("numberOpens = " + jni.numberOpens);
+ classMap.put(etName, jni);
+
+ return jni;
+ }
+ finally {
+ classLock.unlock();
+ }
+ }
+
+ private int numberOpens;
+
+ /** Place to store id (pointer) returned from et_open in C code. */
+ private long localEtId;
+
+ /** Store the name of the ET system. */
+ private String etSystemName;
+
+ /**
+ * Create EtJniAccess objects with the {@link #getInstance(String)} method.
+ */
+ private EtJniAccess() {}
+
+
+ /**
+ * Get the et id.
+ * @return et id
+ */
+ long getLocalEtId() {
+ return localEtId;
+ }
+
+
+ /**
+ * Set the et id. Used inside native method {@link #openLocalEtSystem(String)}.
+ * @param id et id
+ */
+ private void setLocalEtId(long id) {
+ localEtId = id;
+ }
+
+
+ /**
+ * Open a local, C-based ET system and store it's id in {@link #localEtId}.
+ * This only needs to be done once per local system even though many connections
+ * to the ET server may be desired.
+ *
+ * @param etName name of ET system to open
+ *
+ * @throws EtException for any failure to open ET system except timeout
+ * @throws EtTimeoutException for failure to open ET system within the specified time limit
+ */
+ private native void openLocalEtSystem(String etName)
+ throws EtException, EtTimeoutException;
+
+
+ /**
+ * Close the local, C-based ET system that we previously opened.
+ */
+ void close() {
+ try {
+ classLock.lock();
+ numberOpens--;
+//System.out.println("close: numberOpens = " + numberOpens);
+ if (numberOpens < 1) {
+ classMap.remove(etSystemName);
+//System.out.println("close: really close local ET system");
+ closeLocalEtSystem(localEtId);
+ }
+ }
+ finally {
+ classLock.unlock();
+ }
+ }
+
+
+ /**
+ * Close the local, C-based ET system that we previously opened.
+ *
+ * @param etId ET system id
+ */
+ private native void closeLocalEtSystem(long etId);
+
+
+ /**
+ * Put the given array of events back into the local, C-based ET system.
+ *
+ * @param etId ET system id
+ * @param attId attachment id
+ * @param evs array of events
+ * @param length number of events to be put (starting at index of 0)
+ *
+ * @throws EtException for variety of general errors
+ * @throws EtDeadException if ET system is dead
+ */
+ native void putEvents(long etId, int attId, EtEventImpl[] evs, int length)
+ throws EtException, EtDeadException;
+
+
+ /**
+ * Dump (dispose of) the given array of unwanted events back into the local, C-based ET system.
+ *
+ * @param etId ET system id
+ * @param attId attachment id
+ * @param evs array of event objects
+ * @param length number of events to be dumped (starting at index of 0)
+ *
+ * @throws EtException for variety of general errors
+ * @throws EtDeadException if ET system is dead
+ */
+ native void dumpEvents(long etId, int attId, EtEventImpl[] evs, int length)
+ throws EtException, EtDeadException;
+
+
+ /**
+ * Get events from the local, C-based ET system.
+ *
+ * @param etId ET system id
+ * @param attId attachment id
+ * @param mode if there are no events available, this parameter specifies
+ * whether to wait for some by sleeping {@link EtConstants#sleep},
+ * to wait for a set time {@link EtConstants#timed},
+ * or to return immediately {@link EtConstants#async}.
+ * @param sec the number of seconds to wait if a timed wait is specified
+ * @param nsec the number of nanoseconds to wait if a timed wait is specified
+ * @param count number of events desired. Size may be different from that requested.
+ *
+ * @return array of events obtained from ET system. Count may be different from that requested.
+ *
+ * @throws EtException for variety of general errors
+ * @throws EtDeadException if ET system is dead
+ */
+ native EtEventImpl[] getEvents(long etId, int attId, int mode, int sec, int nsec, int count)
+ throws EtException, EtDeadException;
+
+
+ /**
+ * Get array of integers from the local, C-based ET system containing all information
+ * necessary to construct an array of events.
+ *
+ * @param etId ET system id
+ * @param attId attachment id
+ * @param mode if there are no events available, this parameter specifies
+ * whether to wait for some by sleeping {@link EtConstants#sleep},
+ * to wait for a set time {@link EtConstants#timed},
+ * or to return immediately {@link EtConstants#async}.
+ * @param sec the number of seconds to wait if a timed wait is specified
+ * @param nsec the number of nanoseconds to wait if a timed wait is specified
+ * @param count number of events desired. Size may be different from that requested.
+ *
+ * @return array of events obtained from ET system. Count may be different from that requested.
+ *
+ * @throws EtException for variety of general errors
+ * @throws EtDeadException if ET system is dead
+ */
+ native int[] getEventsInfo(long etId, int attId, int mode, int sec, int nsec, int count)
+ throws EtException, EtDeadException;
+
+
+ /**
+ * Get new (unused) events from a specified group of such events from the local, C-based ET system.
+ *
+ * @param etId ET system id
+ * @param attId attachment id
+ * @param mode if there are no new events available, this parameter specifies
+ * whether to wait for some by sleeping {@link EtConstants#sleep},
+ * to wait for a set time {@link EtConstants#timed},
+ * or to return immediately {@link EtConstants#async}.
+ * @param sec the number of seconds to wait if a timed wait is specified
+ * @param nsec the number of nanoseconds to wait if a timed wait is specified
+ * @param count number of events desired
+ * @param size the size in bytes of the events desired
+ * @param group group number from which to draw new events. Some ET systems have
+ * unused events divided into groups whose numbering starts at 1.
+ * For ET system not so divided, all events belong to group 1.
+ *
+ * @return array of unused events obtained from ET system. Count may be different from that requested.
+ *
+ * @throws EtException for variety of general errors
+ * @throws EtDeadException if ET system is dead
+ * @throws EtWakeUpException if told to stop sleeping (before timeout) while trying to get events
+ * @throws EtTimeoutException if timed out on {@link EtConstants#timed} option
+ * @throws EtEmptyException if no events available in {@link EtConstants#async} mode
+ * @throws EtBusyException if cannot get access to events due to activity of other
+ * processes when in {@link EtConstants#async} mode
+ */
+ native EtEventImpl[] newEvents(long etId, int attId, int mode, int sec, int nsec, int count, int size, int group)
+ throws EtException, EtDeadException, EtWakeUpException,
+ EtTimeoutException, EtBusyException, EtEmptyException;
+}
hps-et-java/src/main/java/org/jlab/coda/et
diff -N EtStation.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtStation.java 13 Feb 2012 22:50:52 -0000 1.3
@@ -0,0 +1,587 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et;
+
+import java.lang.*;
+import java.io.*;
+import org.jlab.coda.et.exception.*;
+
+/**
+ * This class defines a station for the ET system user.
+ *
+ * @author Carl Timmer
+ */
+
+public class EtStation {
+
+ /** Unique id number. */
+ private int id;
+
+ /** Name of the station. */
+ private String name;
+
+ /** User's ET system object. */
+ private EtSystem sys;
+
+ /** Flag telling whether this station object is usable or the station it
+ * represents has been removed. Set by the user's ET system object. */
+ private boolean usable;
+
+ // userMode = attachmentLimit; 0 = multiple attachments, 1 = single attachment, 2 = 2 attachments, etc...
+
+
+ /**
+ * Creates a station object. Done by the ET system object only.
+ *
+ * @param name station name
+ * @param id station id number
+ * @param sys user's ET system object
+ */
+ EtStation(String name, int id, EtSystem sys) {
+ this.id = id;
+ this.sys = sys;
+ this.name = name;
+ }
+
+
+ // public sets
+
+
+ /**
+ * Sets whether this station object is usable or the station it represents has been removed.
+ * @param usable <code>true</code> if station object is usable,
+ * <code>false</code> if station it represents has been removed
+ */
+ void setUsable(boolean usable) {
+ this.usable = usable;
+ }
+
+
+ // public gets
+
+
+ /** Gets the station name.
+ * @return station name */
+ public String getName() {return name;}
+
+ /** Gets the station id.
+ * @return station id */
+ public int getId() {return id;}
+
+ /** Gets the ET system object.
+ * @return ET system object */
+ public EtSystem getSys() {return sys;}
+
+ /** Tells if this station object is usable.
+ * @return <code>true</code> if station object is usable and <code>false</code> otherwise */
+ public boolean isUsable() {return usable;}
+
+ /**
+ * Gets the station's select array used for filtering events.
+ *
+ * @return array of select integers
+ * @throws EtException
+ * if the station has been removed or cannot be found
+ * @see EtStationConfig#select
+ */
+ public int[] getSelectWords() throws IOException, EtException {
+ if (!usable) {throw new EtException("station has been removed");}
+
+ int err;
+ int[] select = new int[EtConstants.stationSelectInts];
+
+ synchronized(sys) {
+ sys.getOutputStream().writeInt(EtConstants.netStatGSw);
+ sys.getOutputStream().writeInt(id);
+ sys.getOutputStream().flush();
+
+ err = sys.getInputStream().readInt();
+ for (int i=0; i < select.length; i++) {
+ select[i] = sys.getInputStream().readInt();
+ }
+ }
+
+ if (err != EtConstants.ok) {
+ throw new EtException("cannot find station");
+ }
+
+ return select;
+ }
+
+ /**
+ * Sets the station's select array - used for filtering events.
+ *
+ * @param select array of select integers
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed or cannot be found;
+ * if wrong size array, or if the station is GRAND_CENTRAL
+ * @see EtStationConfig#select
+ */
+ public void setSelectWords(int[] select) throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+
+ if (id == 0) {
+ throw new EtException("cannot modify GRAND_CENTRAL station");
+ }
+
+ if (select.length != EtConstants.stationSelectInts) {
+ throw new EtException("wrong number of elements in select array");
+ }
+
+ int err;
+
+ synchronized (sys) {
+ sys.getOutputStream().writeInt(EtConstants.netStatSSw);
+ sys.getOutputStream().writeInt(id);
+ for (int i = 0; i < select.length; i++) {
+ sys.getOutputStream().writeInt(select[i]);
+ }
+ sys.getOutputStream().flush();
+ err = sys.getInputStream().readInt();
+ }
+
+ if (err != EtConstants.ok) {
+ throw new EtException("this station has been removed from ET system");
+ }
+
+ return;
+ }
+
+ /**
+ * This gets "String" station parameter data over the network.
+ *
+ * @param command coded command to send to the TCP server thread.
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station cannot be found
+ */
+ private String getStringValue(int command) throws IOException, EtException {
+ byte[] buf = null;
+ String val = null;
+ int err, length = 0;
+
+ synchronized (sys) {
+ sys.getOutputStream().writeInt(command);
+ sys.getOutputStream().writeInt(id);
+ sys.getOutputStream().flush();
+ err = sys.getInputStream().readInt();
+ length = sys.getInputStream().readInt();
+
+ if (err == EtConstants.ok) {
+ buf = new byte[length];
+ sys.getInputStream().readFully(buf, 0, length);
+ }
+ }
+
+ if (err == EtConstants.ok) {
+ try {
+ val = new String(buf, 0, length - 1, "ASCII");
+ }
+ catch (UnsupportedEncodingException ex) {
+ }
+ }
+ else {
+ if (length == 0) {
+ return null;
+ }
+ throw new EtException("cannot find station");
+ }
+
+ return val;
+ }
+
+ /**
+ * Gets the name of the library containing the station's user-defined select
+ * function. This is only relevant for station's on C language ET systems.
+ *
+ * @return station's user-defined select function library
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed
+ * @see EtStationConfig#selectLibrary
+ */
+ public String getSelectLibrary() throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+ return getStringValue(EtConstants.netStatLib);
+ }
+
+ /**
+ * Gets the name of the station's user-defined select function.
+ * This is only relevant for station's on C language ET systems.
+ *
+ * @return station's user-defined select function
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed
+ * @see EtStationConfig#selectFunction
+ */
+ public String getSelectFunction() throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+ return getStringValue(EtConstants.netStatFunc);
+ }
+
+ /**
+ * Gets the name of the class containing the station's user-defined select
+ * method. This is only relevant for station's on Java language ET systems.
+ *
+ * @return station's user-defined select method class
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed
+ * @see EtStationConfig#selectClass
+ */
+ public String getSelectClass() throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+ return getStringValue(EtConstants.netStatClass);
+ }
+
+
+ /**
+ * This gets "integer" station parameter data over the network.
+ *
+ * @param cmd coded command to send to the TCP server thread.
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station cannot be found
+ */
+ private int getIntValue(int cmd) throws IOException, EtException {
+ int err, val = 0;
+
+ synchronized (sys) {
+ sys.getOutputStream().writeInt(cmd);
+ sys.getOutputStream().writeInt(id);
+ sys.getOutputStream().flush();
+ err = sys.getInputStream().readInt();
+ val = sys.getInputStream().readInt();
+ }
+
+ if (err != EtConstants.ok) {
+ throw new EtException("this station has been removed from ET system");
+ }
+
+ return val;
+ }
+
+ /**
+ * This sets "integer" station parameter data over the network.
+ *
+ * @param cmd coded command to send to the TCP server thread.
+ * @param val value to set.
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station cannot be found
+ */
+ private void setIntValue(int cmd, int val) throws IOException, EtException {
+ int err;
+
+ synchronized (sys) {
+ sys.getOutputStream().writeInt(cmd);
+ sys.getOutputStream().writeInt(id);
+ sys.getOutputStream().writeInt(val);
+ sys.getOutputStream().flush();
+ err = sys.getInputStream().readInt();
+ }
+
+ if (err != EtConstants.ok) {
+ throw new EtException("this station has been removed from ET system");
+ }
+
+ return;
+ }
+
+ /**
+ * Gets the station's number of attachments.
+ *
+ * @return station's number of attachments
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed
+ */
+ public int getNumAttachments() throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+ return getIntValue(EtConstants.netStatGAtts);
+ }
+
+ /**
+ * Gets the station's status. It may have the values
+ * {@link EtConstants#stationUnused}, {@link EtConstants#stationCreating},
+ * {@link EtConstants#stationIdle}, and {@link EtConstants#stationActive}.
+ *
+ * @return station's status
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed
+ */
+ public int getStatus() throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+ return getIntValue(EtConstants.netStatStatus);
+ }
+
+ /**
+ * Gets the number of events in the station's input list.
+ *
+ * @return number of events in the station's input list
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed
+ */
+ public int getInputCount() throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+ return getIntValue(EtConstants.netStatInCnt);
+ }
+
+ /**
+ * Gets the number of events in the station's output list.
+ *
+ * @return number of events in the station's output list
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed
+ */
+ public int getOutputCount() throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+ return getIntValue(EtConstants.netStatOutCnt);
+ }
+
+ /**
+ * Gets the station configuration's block mode.
+ *
+ * @return station's block mode
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed
+ * @see EtStationConfig#blockMode
+ */
+ public int getBlockMode() throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+ return getIntValue(EtConstants.netStatGBlock);
+ }
+
+ /**
+ * Sets the station's block mode dynamically.
+ *
+ * @param mode block mode value
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed, bad mode value, or
+ * the station is GRAND_CENTRAL
+ * @see EtStationConfig#blockMode
+ */
+ public void setBlockMode(int mode) throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+
+ if (id == 0) {
+ throw new EtException("cannot modify GRAND_CENTRAL station");
+ }
+
+ if ((mode != EtConstants.stationBlocking) &&
+ (mode != EtConstants.stationNonBlocking)) {
+ throw new EtException("bad block mode value");
+ }
+ setIntValue(EtConstants.netStatSBlock, mode);
+ return;
+ }
+
+ /**
+ * Gets the station configuration's user mode.
+ *
+ * @return station's user mode
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed
+ * @see EtStationConfig#userMode
+ */
+ public int getUserMode() throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+ return getIntValue(EtConstants.netStatGUser);
+ }
+
+ /**
+ * Sets the station's user mode dynamically.
+ *
+ * @param mode user mode value
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed, bad mode value, or
+ * the station is GRAND_CENTRAL
+ * @see EtStationConfig#userMode
+ */
+ public void setUserMode(int mode) throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+
+ if (id == 0) {
+ throw new EtException("cannot modify GRAND_CENTRAL station");
+ }
+
+ if (mode < 0) {
+ throw new EtException("bad user mode value");
+ }
+
+ setIntValue(EtConstants.netStatSUser, mode);
+ return;
+ }
+
+ /**
+ * Gets the station configuration's restore mode.
+ *
+ * @return station's restore mode
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed
+ * @see EtStationConfig#restoreMode
+ */
+ public int getRestoreMode() throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+ return getIntValue(EtConstants.netStatGRestore);
+ }
+
+ /**
+ * Sets the station's restore mode dynamically.
+ *
+ * @param mode restore mode value
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed, bad mode value, or
+ * the station is GRAND_CENTRAL
+ * @see EtStationConfig#restoreMode
+ */
+ public void setRestoreMode(int mode) throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+
+ if (id == 0) {
+ throw new EtException("cannot modify GRAND_CENTRAL station");
+ }
+
+ if ((mode != EtConstants.stationRestoreOut) &&
+ (mode != EtConstants.stationRestoreIn) &&
+ (mode != EtConstants.stationRestoreGC)) {
+ throw new EtException("bad restore mode value");
+ }
+
+ setIntValue(EtConstants.netStatSRestore, mode);
+ return;
+ }
+
+ /**
+ * Gets the station configuration's select mode.
+ *
+ * @return station's select mode
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed
+ * @see EtStationConfig#selectMode
+ */
+ public int getSelectMode() throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+ return getIntValue(EtConstants.netStatGSelect);
+ }
+
+ /**
+ * Gets the station configuration's cue.
+ *
+ * @return station's cue
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed
+ * @see EtStationConfig#cue
+ */
+ public int getCue() throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+ return getIntValue(EtConstants.netStatGCue);
+ }
+
+ /**
+ * Sets the station's cue size dynamically.
+ *
+ * @param cue cue value
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed, bad cue value, or
+ * the station is GRAND_CENTRAL
+ * @see EtStationConfig#cue
+ */
+ public void setCue(int cue) throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+
+ if (id == 0) {
+ throw new EtException("cannot modify GRAND_CENTRAL station");
+ }
+
+ if (cue < 1) {
+ throw new EtException("bad cue value");
+ }
+
+ setIntValue(EtConstants.netStatSCue, cue);
+ return;
+ }
+
+ /**
+ * Gets the station configuration's prescale.
+ *
+ * @return station's prescale
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed
+ * @see EtStationConfig#prescale
+ */
+ public int getPrescale() throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+ return getIntValue(EtConstants.netStatGPre);
+ }
+
+ /**
+ * Sets the station's prescale dynamically.
+ *
+ * @param prescale prescale value
+ * @throws IOException if there are problems with network communication
+ * @throws EtException if the station has been removed, bad prescale value, or
+ * the station is GRAND_CENTRAL
+ * @see EtStationConfig#prescale
+ */
+ public void setPrescale(int prescale) throws IOException, EtException {
+ if (!usable) {
+ throw new EtException("station has been removed");
+ }
+
+ if (id == 0) {
+ throw new EtException("cannot modify GRAND_CENTRAL station");
+ }
+
+ if (prescale < 1) {
+ throw new EtException("bad prescale value");
+ }
+
+ setIntValue(EtConstants.netStatSPre, prescale);
+ return;
+ }
+
+
+}
hps-et-java/src/main/java/org/jlab/coda/et
diff -N EtStationConfig.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtStationConfig.java 13 Feb 2012 22:50:52 -0000 1.3
@@ -0,0 +1,399 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et;
+
+import java.lang.*;
+import java.util.*;
+import java.io.Serializable;
+import org.jlab.coda.et.exception.*;
+
+/**
+ * This class specifies a configuration used to create a new station.
+ *
+ * @author Carl Timmer
+ */
+
+public class EtStationConfig implements Serializable {
+
+ /**
+ * Maximum number of events to store in this station's input list when the
+ * station is nonblocking. When the input list has reached this limit,
+ * additional events flowing through the ET system are passed to the next
+ * station in line.
+ */
+ private int cue;
+
+ /**
+ * A value of N means selecting 1 out of every Nth event that meets this
+ * station's selection criteria.
+ */
+ private int prescale;
+
+ /**
+ * Determine whether the station is part of a single group of stations
+ * through which events flow in parallel or is not. A value of
+ * {@link EtConstants#stationParallel} means it is a parallel station,
+ * while a value of {@link EtConstants#stationSerial} means it is not.
+ */
+ private int flowMode;
+
+ /**
+ * The maximum number of users permitted to attach to this station. A value
+ * of 0 means any number of users may attach. It may be set to
+ * {@link EtConstants#stationUserMulti} or {@link EtConstants#stationUserSingle}
+ * meaning unlimited users and a single user respectively.
+ */
+ private int userMode;
+
+ /**
+ * Determine the method of dealing with events obtained by a user through an
+ * attachment, but whose process has ended before putting the events back
+ * into the system. It may have the value {@link EtConstants#stationRestoreIn}
+ * which places the events in the station's input list,
+ * {@link EtConstants#stationRestoreOut} which places them in the output list,
+ * or {@link EtConstants#stationRestoreGC} which places them in GRAND_CENTRAL
+ * station.
+ */
+ private int restoreMode;
+
+ /**
+ * Determine whether all events will pass through the station (blocking) or
+ * whether events should fill a cue with additional events bypassing the
+ * station and going to the next (nonblocking). The permitted values are
+ * {@link EtConstants#stationBlocking} and {@link EtConstants#stationNonBlocking}.
+ */
+ private int blockMode;
+
+ /**
+ * Determine the method of filtering events for selection into the station's
+ * input list. A value of {@link EtConstants#stationSelectAll} applies no
+ * filtering, {@link EtConstants#stationSelectMatch} applies a builtin
+ * method for selection ({@link org.jlab.coda.et.system.StationLocal#select}), and
+ * {@link EtConstants#stationSelectUser} allows the user to define a selection
+ * method. If the station is part of a single group of parallel stations, a
+ * value of {@link EtConstants#stationSelectRRobin} distributes events among the
+ * parallel stations using a round robin algorithm. Similarly, if the station
+ * is part of a single group of parallel stations, a value of
+ * {@link EtConstants#stationSelectEqualCue} distributes events among the
+ * parallel stations using an algorithm to keep the cues equal to eachother.
+ */
+ private int selectMode;
+
+ /**
+ * An array of integers used in the builtin selection method and available
+ * for any tasks the user desires. Its size is set by
+ * {@link EtConstants#stationSelectInts}.
+ */
+ private int[] select;
+
+ /**
+ * Name of user-defined select function in a C library. It may be null. This
+ * is only relevant to C language ET systems.
+ */
+ private String selectFunction;
+
+ /**
+ * Name of the C library containing the user-defined select function. It may
+ * be null. This is only relevant to C language ET systems.
+ */
+ private String selectLibrary;
+
+ /**
+ * Name of the Java class containing the user-defined select method. It may
+ * be null. This is only relevant to Java language ET systems.
+ */
+ private String selectClass;
+
+
+ /**
+ * Creates a new StationConfig object with default values for everything.
+ * The default values are:
+ * cue = {@link EtConstants#defaultStationCue},
+ * prescale = {@link EtConstants#defaultStationPrescale},
+ * flowMode = {@link EtConstants#stationSerial},
+ * userMode = {@link EtConstants#stationUserMulti},
+ * restoreMode = {@link EtConstants#stationRestoreOut},
+ * blockMode = {@link EtConstants#stationBlocking},
+ * selectMode = {@link EtConstants#stationSelectAll}, and
+ * select = filled with -1's
+ */
+ public EtStationConfig() {
+ cue = EtConstants.defaultStationCue;
+ prescale = EtConstants.defaultStationPrescale;
+ flowMode = EtConstants.stationSerial;
+ userMode = EtConstants.stationUserMulti;
+ restoreMode = EtConstants.stationRestoreOut;
+ blockMode = EtConstants.stationBlocking;
+ selectMode = EtConstants.stationSelectAll;
+ select = new int[EtConstants.stationSelectInts];
+ Arrays.fill(select, -1);
+ }
+
+
+ /**
+ * Creates a new StationConfig object from an existing one.
+ * @param config config to copy
+ */
+ public EtStationConfig(EtStationConfig config) {
+ cue = config.cue;
+ prescale = config.prescale;
+ flowMode = config.flowMode;
+ userMode = config.userMode;
+ restoreMode = config.restoreMode;
+ blockMode = config.blockMode;
+ selectMode = config.selectMode;
+ select = (int[]) config.select.clone();
+ selectFunction = config.selectFunction;
+ selectLibrary = config.selectLibrary;
+ selectClass = config.selectClass;
+ }
+
+
+ /**
+ * Checks to see if station configurations are compatible when adding
+ * a parallel station to an existing group of parallel stations.
+ *
+ * @param group station configuration of head of existing group of parallel stations
+ * @param config configuration of station seeking to be added to the group
+ */
+ public static boolean compatibleParallelConfigs(EtStationConfig group, EtStationConfig config) {
+
+ // both must be parallel stations
+ if ((group.flowMode != EtConstants.stationParallel) ||
+ (config.flowMode != EtConstants.stationParallel)) {
+ return false;
+ }
+
+ // if group is roundrobin or equal-cue, then config must be same
+ if (((group.selectMode == EtConstants.stationSelectRRobin) &&
+ (config.selectMode != EtConstants.stationSelectRRobin)) ||
+ ((group.selectMode == EtConstants.stationSelectEqualCue) &&
+ (config.selectMode != EtConstants.stationSelectEqualCue))) {
+ return false;
+ }
+
+ // If group is roundrobin or equal-cue, then config's blocking & prescale must be same.
+ // BlockMode is forced to be blocking and prescale is forced to be 1
+ // in the method EtSystem.configCheck.
+ if (((group.selectMode == EtConstants.stationSelectRRobin) ||
+ (group.selectMode == EtConstants.stationSelectEqualCue)) &&
+ ((group.blockMode != config.blockMode) ||
+ (group.prescale != config.prescale))) {
+ return false;
+ }
+
+ // if group is NOT roundrobin or equal-cue, then config's cannot be either
+ if (((group.selectMode != EtConstants.stationSelectRRobin) &&
+ (group.selectMode != EtConstants.stationSelectEqualCue)) &&
+ ((config.selectMode == EtConstants.stationSelectRRobin) ||
+ (config.selectMode == EtConstants.stationSelectEqualCue))) {
+ return false;
+ }
+
+ return true;
+ }
+
+
+ // public gets
+
+
+ /** Gets the cue size.
+ * @return cue size */
+ public int getCue() {return cue;}
+
+ /** Gets the prescale value.
+ * @return prescale value */
+ public int getPrescale() {return prescale;}
+
+ /** Gets the flow mode.
+ * @return flow mode */
+ public int getFlowMode() {return flowMode;}
+
+ /** Gets the user mode.
+ * @return user mode */
+ public int getUserMode() {return userMode;}
+
+ /** Gets the restore mode.
+ * @return restore mode */
+ public int getRestoreMode() {return restoreMode;}
+
+ /** Gets the block mode.
+ * @return block mode */
+ public int getBlockMode() {return blockMode;}
+
+ /** Gets the select mode.
+ * @return select mode */
+ public int getSelectMode() {return selectMode;}
+
+ /** Gets a copy of the select integer array.
+ * @return copy of select integer array */
+ public int[] getSelect() {return select.clone();}
+
+ /** Gets the user-defined select function name.
+ * @return selection function name */
+ public String getSelectFunction() {return selectFunction;}
+
+ /** Gets the name of the library containing the user-defined select function.
+ * @return library name */
+ public String getSelectLibrary() {return selectLibrary;}
+
+ /** Gets the name of the class containing the user-defined select method.
+ * @return class name */
+ public String getSelectClass() {return selectClass;}
+
+
+ // public sets
+
+
+ /**
+ * Sets the station's cue size.
+ *
+ * @param q cue size
+ * @throws EtException if there is a bad cue size value
+ */
+ public void setCue(int q) throws EtException {
+ if (q < 1) {
+ throw new EtException("bad cue value");
+ }
+ cue = q;
+ }
+
+ /**
+ * Sets the station's prescale value.
+ *
+ * @param pre prescale value
+ * @throws EtException if there is a bad prescale value
+ */
+ public void setPrescale(int pre) throws EtException {
+ if (pre < 1) {
+ throw new EtException("bad prescale value");
+ }
+ prescale = pre;
+ }
+
+ /**
+ * Sets the station's flow mode value.
+ *
+ * @param mode flow mode
+ * @throws EtException if there is a bad flow mode value
+ */
+ public void setFlowMode(int mode) throws EtException {
+ if ((mode != EtConstants.stationSerial) &&
+ (mode != EtConstants.stationParallel)) {
+ throw new EtException("bad flow mode value");
+ }
+ flowMode = mode;
+ }
+
+ /**
+ * Sets the station's user mode value.
+ *
+ * @param mode user mode
+ * @throws EtException if there is a bad user mode value
+ */
+ public void setUserMode(int mode) throws EtException {
+ if (mode < 0) {
+ throw new EtException("bad user mode value");
+ }
+ userMode = mode;
+ }
+
+ /**
+ * Sets the station's restore mode value.
+ *
+ * @param mode restore mode
+ * @throws EtException if there is a bad restore mode value
+ */
+ public void setRestoreMode(int mode) throws EtException {
+ if ((mode != EtConstants.stationRestoreOut) &&
+ (mode != EtConstants.stationRestoreIn) &&
+ (mode != EtConstants.stationRestoreGC) &&
+ (mode != EtConstants.stationRestoreRedist)) {
+ throw new EtException("bad restore mode value");
+ }
+ restoreMode = mode;
+ }
+
+ /**
+ * Sets the station's block mode value.
+ *
+ * @param mode block mode
+ * @throws EtException if there is a bad block mode value
+ */
+ public void setBlockMode(int mode) throws EtException {
+ if ((mode != EtConstants.stationBlocking) &&
+ (mode != EtConstants.stationNonBlocking)) {
+ throw new EtException("bad block mode value");
+ }
+ blockMode = mode;
+ }
+
+ /**
+ * Sets the station's select mode value.
+ *
+ * @param mode select mode
+ * @throws EtException if there is a bad select mode value
+ */
+ public void setSelectMode(int mode) throws EtException {
+ if ((mode != EtConstants.stationSelectAll) &&
+ (mode != EtConstants.stationSelectMatch) &&
+ (mode != EtConstants.stationSelectUser) &&
+ (mode != EtConstants.stationSelectRRobin) &&
+ (mode != EtConstants.stationSelectEqualCue)) {
+ throw new EtException("bad select mode value");
+ }
+ selectMode = mode;
+ }
+
+ /**
+ * Sets the station's select integer array.
+ *
+ * @param sel select integer array
+ * @throws EtException if there are the wrong number of elements in the array
+ */
+ public void setSelect(int[] sel) throws EtException {
+ if (sel.length != EtConstants.stationSelectInts) {
+ throw new EtException("wrong number of elements in select array");
+ }
+ select = (int[]) sel.clone();
+ }
+
+ /**
+ * Sets the station's user-defined select function.
+ *
+ * @param func name of the user-defined select function
+ */
+ public void setSelectFunction(String func) {
+ selectFunction = func;
+ }
+
+ /**
+ * Sets the library containing the user-defined select function.
+ *
+ * @param lib name of the library containg the user-defined select function
+ */
+ public void setSelectLibrary(String lib) {
+ selectLibrary = lib;
+ }
+
+ /**
+ * Sets the class containing the user-defined select method.
+ *
+ * @param sClass name of the class containg the user-defined select method
+ */
+ public void setSelectClass(String sClass) {
+ selectClass = sClass;
+ }
+}
hps-et-java/src/main/java/org/jlab/coda/et
diff -N EtStationSelection.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtStationSelection.java 13 Feb 2012 22:50:52 -0000 1.3
@@ -0,0 +1,41 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et;
+
+import org.jlab.coda.et.system.StationLocal;
+import org.jlab.coda.et.system.SystemCreate;
+
+
+/**
+ * This class contains an example of a user-defined method used to
+ * select events for a station.
+ *
+ * @author Carl Timmer
+ */
+
+public class EtStationSelection implements EtEventSelectable {
+
+ public EtStationSelection() {
+ }
+
+ public boolean select(SystemCreate sys, StationLocal st, EtEvent ev) {
+ if (ev.getId()%2 == 0) {
+ //System.out.println(" Select Func: accept ev.id = " + ev.id);
+ return true;
+ }
+ //System.out.println(" Select Func: reject ev.id = " + ev.id);
+ return false;
+ }
+}
hps-et-java/src/main/java/org/jlab/coda/et
diff -N EtSystem.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtSystem.java 13 Feb 2012 22:50:52 -0000 1.3
@@ -0,0 +1,2700 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et;
+
+import java.lang.*;
+import java.nio.ByteOrder;
+import java.util.*;
+import java.io.*;
+import java.net.*;
+import java.nio.MappedByteBuffer;
+import java.nio.ByteBuffer;
+
+import org.jlab.coda.et.data.*;
+import org.jlab.coda.et.exception.*;
+import org.jlab.coda.et.enums.Modify;
+import org.jlab.coda.et.enums.Mode;
+import org.jlab.coda.et.enums.Priority;
+import org.jlab.coda.et.enums.DataStatus;
+
+// TODO: if IO exception occurs, open is not set to false, must catch it and call close()
+// TODO: so open is set to false. Then try open again.
+/**
+ * This class implements an object which allows a user to interact with an ET
+ * system. It is not the ET system itself, but rather a proxy which communicates
+ * over the network or through JNI with the real ET system.
+ *
+ * @author Carl Timmer
+ */
+
+public class EtSystem {
+
+ /** Object to specify how to open the ET system of interest. */
+ private EtSystemOpenConfig openConfig;
+
+ /** Object used to connect to a real ET system. */
+ private EtSystemOpen sys;
+
+ /** Flag telling whether the real ET system is currently opened or not. */
+ private boolean open;
+
+ /** Debug level. */
+ private int debug;
+
+ /** Tcp socket connected to ET system's server. */
+ private Socket sock;
+
+ /** Flag specifying whether the ET system process is Java based or not. */
+ private boolean isJava;
+
+ /** Data input stream built on top of the socket's input stream (with an
+ * intervening buffered input stream). */
+ private DataInputStream in;
+
+ /** Data output stream built on top of the socket's output stream (with an
+ * intervening buffered output stream). */
+ private DataOutputStream out;
+
+
+
+ /**
+ * Construct a new EtSystem object.
+ *
+ * @param config EtSystemOpenConfig object to specify how to open the ET
+ * system of interest (copy is stored & used)
+ * @param debug debug level (e.g. {@link EtConstants#debugInfo})
+ * @throws EtException if config is null or not self-consistent
+ */
+ public EtSystem(EtSystemOpenConfig config, int debug) throws EtException {
+
+ if (config == null) {
+ throw new EtException("Invalid arg");
+ }
+
+ openConfig = new EtSystemOpenConfig(config);
+
+ if (!openConfig.selfConsistent()) {
+ throw new EtException("system open configuration is not self-consistent");
+ }
+
+ sys = new EtSystemOpen(openConfig);
+
+ if ((debug != EtConstants.debugNone) &&
+ (debug != EtConstants.debugSevere) &&
+ (debug != EtConstants.debugError) &&
+ (debug != EtConstants.debugWarn) &&
+ (debug != EtConstants.debugInfo)) {
+
+ this.debug = EtConstants.debugError;
+ }
+ else {
+ this.debug = debug;
+ }
+
+ try {
+ sys.setDebug(debug);
+ }
+ catch (EtException e) { /* never happen */ }
+
+ //open();
+ }
+
+ /**
+ * Construct a new EtSystem object. Debug level set to print only errors.
+ *
+ * @param config EtSystemOpenConfig object to specify how to open the ET
+ * system of interest (copy is stored & used)
+ * @throws EtException if config is not self-consistent
+ */
+ public EtSystem(EtSystemOpenConfig config) throws EtException {
+
+ this(config, EtConstants.debugError);
+ }
+
+ /**
+ * Construct a new EtSystem object. Not meant for general use.
+ * Use one of the other constructors.
+ *
+ * @param sys EtSystemOpen object to specify a connection to the ET
+ * system of interest
+ * @param debug debug level (e.g. {@link EtConstants#debugInfo})
+ *
+ * @throws IOException
+ * if problems with network communications
+ * @throws UnknownHostException
+ * if the host address(es) is(are) unknown
+ * @throws EtException
+ * if arg is null;
+ * if the responding ET system has the wrong name, runs a different
+ * version of ET, or has a different value for
+ * {@link EtConstants#stationSelectInts}
+ * @throws EtTooManyException
+ * if there were more than one valid response when policy is set to
+ * {@link EtConstants#policyError} and we are looking either
+ * remotely or anywhere for the ET system.
+ */
+ public EtSystem(EtSystemOpen sys, int debug) throws
+ IOException, EtException, EtTooManyException {
+
+ if (sys == null) {
+ throw new EtException("Invalid arg");
+ }
+
+ this.sys = sys;
+ openConfig = sys.getConfig();
+
+ if ((debug != EtConstants.debugNone) &&
+ (debug != EtConstants.debugSevere) &&
+ (debug != EtConstants.debugError) &&
+ (debug != EtConstants.debugWarn) &&
+ (debug != EtConstants.debugInfo)) {
+
+ this.debug = EtConstants.debugError;
+ }
+ else {
+ this.debug = debug;
+ }
+
+ if (sys.isConnected()) {
+ if (sys.getLanguage() == EtConstants.langJava) {isJava = true;}
+
+ // buffer communication streams for efficiency
+ sock = sys.getSocket();
+
+ if (openConfig.getTcpRecvBufSize() > 0) {
+ in = new DataInputStream(new BufferedInputStream(sock.getInputStream(), openConfig.getTcpRecvBufSize()));
+ }
+ else {
+ in = new DataInputStream( new BufferedInputStream( sock.getInputStream(), sock.getReceiveBufferSize()));
+ }
+
+ if (openConfig.getTcpSendBufSize() > 0) {
+ out = new DataOutputStream(new BufferedOutputStream(sock.getOutputStream(), openConfig.getTcpSendBufSize()));
+ }
+ else {
+ out = new DataOutputStream(new BufferedOutputStream(sock.getOutputStream(), sock.getSendBufferSize()));
+ }
+
+ open = true;
+ }
+ else {
+ open();
+ }
+
+ }
+
+
+ // Local getters & setters
+
+
+ /**
+ * Get the data input stream to talk to ET system server.
+ * @return data input stream to talk to ET system server
+ */
+ public DataInputStream getInputStream() {
+ return in;
+ }
+
+ /**
+ * Get the data output stream to receive from the ET system server.
+ * @return data output stream to receive from the ET system server
+ */
+ public DataOutputStream getOutputStream() {
+ return out;
+ }
+
+ /**
+ * Gets the debug output level.
+ * @return debug output level
+ */
+ public int getDebug() {
+ return debug;
+ }
+
+ /**
+ * Sets the debug output level. Must be either {@link EtConstants#debugNone},
+ * {@link EtConstants#debugSevere}, {@link EtConstants#debugError},
+ * {@link EtConstants#debugWarn}, or {@link EtConstants#debugInfo}.
+ *
+ * @param val debug level
+ * @throws EtException if bad argument value
+ */
+ public void setDebug(int val) throws EtException {
+ if ((val != EtConstants.debugNone) &&
+ (val != EtConstants.debugSevere) &&
+ (val != EtConstants.debugError) &&
+ (val != EtConstants.debugWarn) &&
+ (val != EtConstants.debugInfo)) {
+ throw new EtException("bad debug argument");
+ }
+ debug = val;
+ }
+
+ /**
+ * Gets a copy of the configuration object used to specify how to open the ET system.
+ * @return copy of the configuration object used to specify how to open the ET system.
+ */
+ public EtSystemOpenConfig getConfig() {
+ return new EtSystemOpenConfig(openConfig);
+ }
+
+
+ /**
+ * Open the ET system and set up buffered communication.
+ *
+ * @throws IOException
+ * if problems with network communications
+ * @throws UnknownHostException
+ * if the host address(es) is(are) unknown
+ * @throws EtException
+ * if the responding ET system has the wrong name, runs a different
+ * version of ET, or has a different value for
+ * {@link EtConstants#stationSelectInts}
+ * @throws EtTooManyException
+ * if there were more than one valid response when policy is set to
+ * {@link EtConstants#policyError} and we are looking either
+ * remotely or anywhere for the ET system.
+ */
+ synchronized public void open() throws IOException, EtException, EtTooManyException {
+
+ if (open) {
+ return;
+ }
+
+ try {
+ sys.connect();
+ }
+ catch (EtTooManyException ex) {
+ if (debug >= EtConstants.debugError) {
+ int count = 1;
+ System.out.println("The following hosts responded:");
+ for (Map.Entry<ArrayList<String>,Integer> entry : sys.getResponders().entrySet()) {
+ System.out.println(" host #" + (count++) + " at port " + entry.getValue());
+ ArrayList<String> addrList = entry.getKey();
+ for (String s : addrList) {
+ System.out.println(" " + s);
+ }
+ System.out.println();
+ }
+ }
+ throw ex;
+ }
+
+ if (sys.getLanguage() == EtConstants.langJava) {isJava = true;}
+
+ sock = sys.getSocket();
+
+ // buffer communication streams for efficiency
+ if (openConfig.getTcpRecvBufSize() > 0) {
+ in = new DataInputStream(new BufferedInputStream(sock.getInputStream(), openConfig.getTcpRecvBufSize()));
+ }
+ else {
+ in = new DataInputStream( new BufferedInputStream( sock.getInputStream(), sock.getReceiveBufferSize()));
+ }
+
+ if (openConfig.getTcpSendBufSize() > 0) {
+ out = new DataOutputStream(new BufferedOutputStream(sock.getOutputStream(), openConfig.getTcpSendBufSize()));
+ }
+ else {
+ out = new DataOutputStream(new BufferedOutputStream(sock.getOutputStream(), sock.getSendBufferSize()));
+ }
+
+ open = true;
+ }
+
+
+ /** Close the ET system. */
+ synchronized public void close() {
+
+ if (!open) {
+ return;
+ }
+
+ // if communication with ET system fails, we've already been "closed"
+ try {
+ // Are we using JNI? If so, close the ET system it opened.
+ if (sys.isMapLocalSharedMemory()) {
+//System.out.println(" Close et sys JNI object");
+ sys.getJni().close();
+ }
+// else {
+//System.out.println(" Do NOT close et sys JNI object since NO local shared memory");
+// }
+
+ out.writeInt(EtConstants.netClose); // close and forcedclose do the same thing in java
+ out.flush();
+ in.readInt();
+ }
+ catch (IOException ex) {
+ if (debug >= EtConstants.debugError) {
+ System.out.println("network communication error");
+ }
+ }
+ finally {
+ try {
+ in.close();
+ out.close();
+ sys.disconnect(); // does sock.close()
+ }
+ catch (IOException ex) { /* ignore exception */ }
+ }
+
+ open = false;
+ }
+
+
+ /**
+ * Is the ET system alive and are we connected to it?
+ *
+ * @return <code>true</code> if the ET system is alive and we're connected to it,
+ * otherwise <code>false</code>
+ */
+ synchronized public boolean alive() {
+ if (!open) {
+ return false;
+ }
+
+ int alive;
+ // If ET system is NOT alive, or if ET system was killed and restarted
+ // (breaking tcp connection), we'll get a read or write error.
+ try {
+ out.writeInt(EtConstants.netAlive);
+ out.flush();
+ alive = in.readInt();
+ }
+ catch (IOException ex) {
+ if (debug >= EtConstants.debugError) {
+ System.out.println("network communication error");
+ }
+ return false;
+ }
+
+ return (alive == 1);
+ }
+
+
+ /**
+ * Wake up an attachment that is waiting to read events from a station's empty input list.
+ *
+ * @param att attachment to wake up
+ *
+ * @throws IOException
+ * if problems with network communications
+ * @throws EtException
+ * if arg is null;
+ * if not connected to ET system;
+ * if the attachment object is invalid
+ */
+ synchronized public void wakeUpAttachment(EtAttachment att) throws IOException, EtException {
+ if (!open) {
+ throw new EtException("Not connected to ET system");
+ }
+
+ if (att == null || !att.isUsable() || att.getSys() != this) {
+ throw new EtException("Invalid attachment");
+ }
+
+ out.writeInt(EtConstants.netWakeAtt);
+ out.writeInt(att.getId());
+ out.flush();
+ }
+
+
+ /**
+ * Wake up all attachments waiting to read events from a station's
+ * empty input list.
+ *
+ * @param station station whose attachments are to wake up
+ *
+ * @throws IOException
+ * if problems with network communications
+ * @throws EtException
+ * if arg is null;
+ * if not connected to ET system;
+ * if the station object is invalid
+ */
+ synchronized public void wakeUpAll(EtStation station) throws IOException, EtException {
+ if (!open) {
+ throw new EtException("Not connected to ET system");
+ }
+
+ if (station == null || !station.isUsable() || station.getSys() != this) {
+ throw new EtException("Invalid station");
+ }
+
+ out.writeInt(EtConstants.netWakeAll);
+ out.writeInt(station.getId());
+ out.flush();
+ }
+
+
+ //****************************************************
+ // STATIONS *
+ //****************************************************
+
+
+ /**
+ * Checks a station configuration for self-consistency.
+ *
+ * @param config station configuration
+ *
+ * @throws EtException
+ * if arg is null;
+ * if the station configuration is not self-consistent
+ */
+ private void configCheck(EtStationConfig config) throws EtException {
+
+ if (config == null) {
+ throw new EtException("Invalid arg");
+ }
+
+ // USER mode means specifing a class
+ if ((config.getSelectMode() == EtConstants.stationSelectUser) &&
+ (config.getSelectClass() == null)) {
+
+ throw new EtException("station config needs a select class name");
+ }
+
+ // Must be parallel, block, not prescale, and not restore to input list if rrobin or equal cue
+ if (((config.getSelectMode() == EtConstants.stationSelectRRobin) ||
+ (config.getSelectMode() == EtConstants.stationSelectEqualCue)) &&
+ ((config.getFlowMode() == EtConstants.stationSerial) ||
+ (config.getBlockMode() == EtConstants.stationNonBlocking) ||
+ (config.getRestoreMode() == EtConstants.stationRestoreIn) ||
+ (config.getPrescale() != 1))) {
+
+ throw new EtException("if flowMode = rrobin/equalcue, station must be parallel, nonBlocking, prescale=1, & not restoreIn");
+ }
+
+ // If redistributing restored events, must be a parallel station
+ if ((config.getRestoreMode() == EtConstants.stationRestoreRedist) &&
+ (config.getFlowMode() != EtConstants.stationParallel)) {
+
+ throw new EtException("if restoreMode = restoreRedist, station must be parallel");
+ }
+
+ if (config.getCue() > sys.getNumEvents()) {
+ config.setCue(sys.getNumEvents());
+ }
+ }
+
+
+ /**
+ * Creates a new station placed at the end of the ordered list of stations.
+ * If the station is added to a group of parallel stations,
+ * it is placed at the end of the list of parallel stations.
+ *
+ * @param config station configuration
+ * @param name station name
+ *
+ * @return new station object
+ *
+ * @throws IOException
+ * if problems with network communications
+ * @throws EtException
+ * if not connected to ET system;
+ * if the select method's class cannot be loaded;
+ * if the position is less than 1 (GRAND_CENTRAL's spot);
+ * if the name is GRAND_CENTRAL (already taken);
+ * if the configuration's cue size is too big;
+ * if the configuration needs a select class name
+ * @throws EtExistsException
+ * if the station already exists but with a different configuration
+ * @throws EtTooManyException
+ * if the maximum number of stations has been created already
+ */
+ public EtStation createStation(EtStationConfig config, String name)
+ throws IOException, EtException,
+ EtExistsException, EtTooManyException {
+
+ return createStation(config, name, EtConstants.end, EtConstants.end);
+ }
+
+
+ /**
+ * Creates a new station at a specified position in the ordered list of
+ * stations. If the station is added to a group of parallel stations,
+ * it is placed at the end of the list of parallel stations.
+ *
+ * @param config station configuration
+ * @param name station name
+ * @param position position in the linked list to put the station.
+ *
+ * @return new station object
+ *
+ * @throws IOException
+ * if problems with network communications
+ * @throws EtException
+ * if not connected to ET system;
+ * if the select method's class cannot be loaded;
+ * if the position is less than 1 (GRAND_CENTRAL's spot);
+ * if the name is GRAND_CENTRAL (already taken);
+ * if the configuration's cue size is too big;
+ * if the configuration needs a select class name
+ * @throws EtExistsException
+ * if the station already exists but with a different configuration
+ * @throws EtTooManyException
+ * if the maximum number of stations has been created already
+ */
+ public EtStation createStation(EtStationConfig config, String name, int position)
+ throws IOException, EtException,
+ EtExistsException, EtTooManyException {
+ return createStation(config, name, position, EtConstants.end);
+ }
+
+
+ /**
+ * Creates a new station at a specified position in the ordered list of
+ * stations and in a specified position in an ordered list of parallel
+ * stations if it is a parallel station.
+ *
+ * @param config station configuration
+ * @param name station name
+ * @param position position in the main list to put the station.
+ * @param parallelPosition position in the list of parallel
+ * stations to put the station.
+ *
+ * @return new station object
+ *
+ * @throws IOException
+ * if problems with network communications
+ * @throws EtException
+ * if arg is null;
+ * if not connected to ET system;
+ * if the select method's class cannot be loaded;
+ * if the position is less than 1 (GRAND_CENTRAL's spot);
+ * if the name is GRAND_CENTRAL (already taken);
+ * if the configuration's cue size is too big;
+ * if the configuration needs a select class name
+ * @throws EtExistsException
+ * if the station already exists but with a different configuration
+ * @throws EtTooManyException
+ * if the maximum number of stations has been created already
+ */
+ synchronized public EtStation createStation(EtStationConfig config, String name,
+ int position, int parallelPosition)
+ throws IOException, EtException,
+ EtExistsException, EtTooManyException {
+
+ if (!open) {
+ throw new EtException("Not connected to ET system");
+ }
+
+ if (name == null || config == null) {
+ throw new EtException("Invalid arg");
+ }
+
+ // cannot create GrandCentral
+ if (name.equals("GRAND_CENTRAL")) {
+ throw new EtException("Cannot create GRAND_CENTRAL station");
+ }
+
+ // check value of position
+ if (position != EtConstants.end && position < 1) {
+ throw new EtException("Bad value for position");
+ }
+
+ // check value of parallel position
+ if ((parallelPosition != EtConstants.end) &&
+ (parallelPosition != EtConstants.newHead) &&
+ (parallelPosition < 0)) {
+ throw new EtException("Bad value for parallel position");
+ }
+
+ // check station configuration for self consistency
+ configCheck(config);
+
+ // command
+ out.writeInt(EtConstants.netStatCrAt);
+
+ // station configuration
+ out.writeInt(EtConstants.structOk); // not used in Java
+ out.writeInt(config.getFlowMode());
+ out.writeInt(config.getUserMode());
+ out.writeInt(config.getRestoreMode());
+ out.writeInt(config.getBlockMode());
+ out.writeInt(config.getPrescale());
+ out.writeInt(config.getCue());
+ out.writeInt(config.getSelectMode());
+ int[] select = config.getSelect();
+ for (int i=0; i < EtConstants.stationSelectInts; i++) {
+ out.writeInt(select[i]);
+ }
+
+ int functionLength = 0; // no function
+ if (config.getSelectFunction() != null) {
+ functionLength = config.getSelectFunction().length() + 1;
+ }
+ out.writeInt(functionLength);
+
+ int libraryLength = 0; // no lib
+ if (config.getSelectLibrary() != null) {
+ libraryLength = config.getSelectLibrary().length() + 1;
+ }
+ out.writeInt(libraryLength);
+
+ int classLength = 0; // no class
+ if (config.getSelectClass() != null) {
+ classLength = config.getSelectClass().length() + 1;
+ }
+ out.writeInt(classLength);
+
+ // station name and position
+ int nameLength = name.length() + 1;
+ out.writeInt(nameLength);
+ out.writeInt(position);
+ out.writeInt(parallelPosition);
+
+ // write string(s)
+ try {
+ if (functionLength > 0) {
+ out.write(config.getSelectFunction().getBytes("ASCII"));
+ out.writeByte(0);
+ }
+ if (libraryLength > 0) {
+ out.write(config.getSelectLibrary().getBytes("ASCII"));
+ out.writeByte(0);
+ }
+ if (classLength > 0) {
+ out.write(config.getSelectClass().getBytes("ASCII"));
+ out.writeByte(0);
+ }
+ out.write(name.getBytes("ASCII"));
+ out.writeByte(0);
+ }
+ catch (UnsupportedEncodingException ex) { /* never happen */ }
+
+ out.flush();
+
+ int err = in.readInt();
+ int statId = in.readInt();
+
+ if (err == EtConstants.errorTooMany) {
+ throw new EtTooManyException("Maximum number of stations already created");
+ }
+ else if (err == EtConstants.errorExists) {
+ throw new EtExistsException("Station already exists with different definition");
+ }
+ else if (err == EtConstants.error) {
+ throw new EtException("Trying to add incompatible parallel station, or\n" +
+ "trying to add parallel station to head of existing parallel group, or\n" +
+ "cannot load select class");
+ }
+
+ // create station
+ EtStation station = new EtStation(name, statId, this);
+ station.setUsable(true);
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("Creating station " + name + " is done");
+ }
+
+ return station;
+ }
+
+
+ /**
+ * Removes an existing station.
+ *
+ * @param station station object
+ *
+ * @throws IOException
+ * if problems with network communications
+ * @throws EtException
+ * if arg is null;
+ * if not connected to ET system;
+ * if attachments to the station still exist;
+ * if the station is GRAND_CENTRAL (which must always exist);
+ * if the station does not exist;
+ * if the station object is invalid
+ */
+ synchronized public void removeStation(EtStation station) throws IOException, EtException {
+
+ if (!open) {
+ throw new EtException("Not connected to ET system");
+ }
+
+ if (station == null) {
+ throw new EtException("Invalid station");
+ }
+
+ // cannot remove GrandCentral
+ if (station.getId() == 0) {
+ throw new EtException("Cannot remove GRAND_CENTRAL station");
+ }
+
+ // station object invalid
+ if (!station.isUsable() || station.getSys() != this) {
+ throw new EtException("Invalid station");
+ }
+
+ out.writeInt(EtConstants.netStatRm);
+ out.writeInt(station.getId());
+ out.flush();
+
+ int err = in.readInt();
+ if (err == EtConstants.error) {
+ throw new EtException("Either no such station exists " +
+ "or remove all attachments before removing station");
+ }
+
+ station.setUsable(false);
+ }
+
+
+ /**
+ * Changes the position of a station in the ordered list of stations.
+ *
+ * @param station station object
+ * @param position position in the main station list (starting at 0)
+ * @param parallelPosition position in list of parallel stations (starting at 0)
+ *
+ * @throws IOException
+ * if problems with network communications
+ * @throws EtException
+ * if arg is null;
+ * if not connected to ET system;
+ * if the station does not exist;
+ * if trying to move GRAND_CENTRAL;
+ * if position is < 1 (GRAND_CENTRAL is always first);
+ * if parallelPosition < 0;
+ * if station object is invalid;
+ * if trying to move an incompatible parallel station to an existing group
+ * of parallel stations or to the head of an existing group of parallel
+ * stations.
+ */
+ synchronized public void setStationPosition(EtStation station, int position,
+ int parallelPosition)
+ throws IOException, EtException {
+
+ if (!open) {
+ throw new EtException("Not connected to ET system");
+ }
+
+ if (station == null) {
+ throw new EtException("Invalid station");
+ }
+
+ // cannot move GrandCentral
+ if (station.getId() == 0) {
+ throw new EtException("Cannot move GRAND_CENTRAL station");
+ }
+
+ if ((position != EtConstants.end) && (position < 0)) {
+ throw new EtException("bad value for position");
+ }
+ else if (position == 0) {
+ throw new EtException("GRAND_CENTRAL station is always first");
+ }
+
+ if ((parallelPosition != EtConstants.end) &&
+ (parallelPosition != EtConstants.newHead) &&
+ (parallelPosition < 0)) {
+ throw new EtException("bad value for parallelPosition");
+ }
+
+ if (!station.isUsable() || station.getSys() != this) {
+ throw new EtException("Invalid station");
+ }
+
+ out.writeInt(EtConstants.netStatSPos);
+ out.writeInt(station.getId());
+ out.writeInt(position);
+ out.writeInt(parallelPosition);
+ out.flush();
+
+ int err = in.readInt();
+ if (err == EtConstants.error) {
+ station.setUsable(false);
+ throw new EtException("station does not exist");
+ }
+ }
+
+
+ /**
+ * Gets the position of a station in the ordered list of stations.
+ *
+ * @param station station object
+ * @return position of a station in the main linked list of stations
+ *
+ * @throws IOException
+ * if problems with network communications
+ * @throws EtException
+ * if arg is null;
+ * if not connected to ET system;
+ * if the station does not exist;
+ * if station object is invalid
+ */
+ synchronized public int getStationPosition(EtStation station)
+ throws IOException, EtException {
+
+ if (!open) {
+ throw new EtException("Not connected to ET system");
+ }
+
+ if (station == null || !station.isUsable() || station.getSys() != this) {
+ throw new EtException("Invalid station");
+ }
+
+ // GrandCentral is always first
+ if (station.getId() == 0) {
+ return 0;
+ }
+
+ out.writeInt(EtConstants.netStatGPos);
+ out.writeInt(station.getId());
+ out.flush();
+
+ int err = in.readInt();
+ int position = in.readInt();
+ // skip parallel position info
+ in.skipBytes(4);
+ if (err == EtConstants.error) {
+ station.setUsable(false);
+ throw new EtException("station does not exist");
+ }
+
+ return position;
+ }
+
+
+ /**
+ * Gets the position of a parallel station in its ordered list of
+ * parallel stations.
+ *
+ * @param station station object
+ * @return position of a station in the linked list of stations
+ *
+ * @throws IOException
+ * if problems with network communications
+ * @throws EtException
+ * if arg is null;
+ * if not connected to ET system;
+ * if the station does not exist;
+ * if station object is invalid
+ */
+ synchronized public int getStationParallelPosition(EtStation station)
+ throws IOException, EtException {
+
+ if (!open) {
+ throw new EtException("Not connected to ET system");
+ }
+
+ if (station == null || !station.isUsable() || station.getSys() != this) {
+ throw new EtException("Invalid station");
+ }
+
+ // parallel position is 0 for serial stations (like GrandCentral)
+ if (station.getId() == 0) {
+ return 0;
+ }
+
+ out.writeInt(EtConstants.netStatGPos);
+ out.writeInt(station.getId());
+ out.flush();
+
+ int err = in.readInt();
+ // skip main position info
+ in.skipBytes(4);
+ int pPosition = in.readInt();
+ if (err == EtConstants.error) {
+ station.setUsable(false);
+ throw new EtException("station does not exist");
+ }
+
+ return pPosition;
+ }
+
+
+ /**
+ * Create an attachment to a station.
+ *
+ * @param station station object
+ * @return an attachment object
+ *
+ * @throws IOException
+ * if problems with network communications
+ * @throws EtException
+ * if arg is null;
+ * if not connected to ET system;
+ * if the station does not exist;
+ * if station object is invalid
+ * @throws EtTooManyException
+ * if no more attachments are allowed to the station;
+ * if no more attachments are allowed to ET system
+ */
+ synchronized public EtAttachment attach(EtStation station)
+ throws IOException, EtException, EtTooManyException {
+
+ if (!open) {
+ throw new EtException("Not connected to ET system");
+ }
+
+ if (station == null || !station.isUsable() || station.getSys() != this) {
+ throw new EtException("Invalid station");
+ }
+
+ // find name of our host
+ String host = "unknown";
+ try {host = InetAddress.getLocalHost().getHostName();}
+ catch (UnknownHostException ex) { /* host = "unknown" */ }
+
+ // find interface (ip address) socket is using
+ String ipAddr = sock.getLocalAddress().getHostAddress();
+
+ out.writeInt(EtConstants.netStatAtt);
+ out.writeInt(station.getId());
+ out.writeInt(-1); // no pid in Java
+ out.writeInt(host.length() + 1);
+ out.writeInt(ipAddr.length() + 1);
+
+ // write strings
+ try {
+ out.write(host.getBytes("ASCII"));
+ out.writeByte(0);
+ out.write(ipAddr.getBytes("ASCII"));
+ out.writeByte(0);
+ }
+ catch (UnsupportedEncodingException ex) { /* never happen */ }
+ out.flush();
+
+ int err = in.readInt();
+ int attId = in.readInt();
+ if (err == EtConstants.error) {
+ station.setUsable(false);
+ throw new EtException("station does not exist");
+ }
+ else if (err == EtConstants.errorTooMany) {
+ throw new EtTooManyException("no more attachments allowed to either station or system");
+ }
+
+ EtAttachment att = new EtAttachment(station, attId, this);
+ att.setUsable(true);
+ return att;
+ }
+
+
+
+ /**
+ * Remove an attachment from a station.
+ *
+ * @param att attachment object
+ *
+ * @throws IOException
+ * if problems with network communications
+ * @throws EtException
[truncated at 1000 lines; 1704 more skipped]
hps-et-java/src/main/java/org/jlab/coda/et
diff -N EtSystemOpen.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtSystemOpen.java 13 Feb 2012 22:50:52 -0000 1.3
@@ -0,0 +1,1471 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et;
+
+import java.lang.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.nio.channels.FileChannel;
+import java.nio.MappedByteBuffer;
+import java.nio.ByteOrder;
+
+import org.jlab.coda.et.exception.*;
+
+/**
+ * This class opens (finds and connects to) an ET system. The use of this class
+ * is hidden from the user. There is no reason to use it explicitly.
+ *
+ * @author Carl Timmer
+ */
+
+public class EtSystemOpen {
+
+ /** Object specifying how to open an ET system. */
+ private EtSystemOpenConfig config;
+
+ /** TCP socket connection established with an ET system's server. */
+ private Socket sock;
+
+ /** IP address (dot decimal) of the host the ET system resides on. */
+ private String hostAddress;
+
+ /** List of all IP addresses (dot decimal) of the host the ET system resides on. */
+ private ArrayList<String> hostAddresses;
+
+ /** Port number of the ET system's tcp server. */
+ private int tcpPort;
+
+ /** In case of multiple responding ET systems, a map of their addresses & ports. */
+ private LinkedHashMap<ArrayList<String>, Integer> responders;
+
+ /** Is this object connected to a real, live ET system? */
+ private boolean connected;
+
+ /** Is the ET system on the local host? */
+ private boolean etOnLocalHost;
+
+ /** Debug level. Set by {@link EtSystemOpen#setDebug(int)}. */
+ private int debug;
+
+ // using shared memory
+
+ /** If opening a local, C-based ET system, try mapping the memory containing
+ * the event data instead of sending it over sockets. */
+ private boolean mapLocalSharedMemory;
+
+ /** Buffer containing mapped memory if {@link #mapLocalSharedMemory} flag is true. */
+ private MappedByteBuffer buffer;
+
+ /** Object for accessing native methods which use C library to get and put events. */
+ private EtJniAccess jni;
+
+ // properties of opened ET system
+
+ /** Endian value of the opened ET system. */
+ private int endian;
+
+ /** Total number of events of the opened ET system. */
+ private int numEvents;
+
+ /** Event size in bytes of the opened ET system. */
+ private long eventSize;
+
+ /** Major version number of the opened ET system. */
+ private int version;
+
+ /** Number of select integers in the opened ET system. */
+ private int stationSelectInts;
+
+ /** Language used to implement the opened ET system. The possible values are
+ * {@link EtConstants#langJava} for Java, {@link EtConstants#langCpp} for C++,
+ * and {@link EtConstants#langC} for C. */
+ private int language;
+
+ /** True if ET system is 64 bit, else false. */
+ private boolean bit64;
+
+ private ArrayList<String> localHostIpAddrs;
+
+
+ // convenience variables
+ private final boolean foundServer=true, cannotFindServer=false;
+ private final boolean gotMatch=true, noMatch=false;
+
+
+ /**
+ * Constructor which stores copy of argument.
+ * @param config EtSystemOpenConfig object
+ */
+ public EtSystemOpen(EtSystemOpenConfig config) {
+ this.config = new EtSystemOpenConfig(config);
+ debug = EtConstants.debugError;
+ responders = new LinkedHashMap<ArrayList<String>, Integer>(20);
+ hostAddresses = new ArrayList<String>();
+
+ // get set of all host's IP addresses (dot-decimal)
+ localHostIpAddrs = new ArrayList<String>();
+ try {
+ InetAddress[] haddrs = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName());
+ for (InetAddress ia : haddrs) {
+ localHostIpAddrs.add(ia.getHostAddress());
+ }
+ }
+ catch (UnknownHostException e) {
+ if (debug >= EtConstants.debugWarn) {
+ System.out.println("EtSystemOpen constructor: cannot find local IP addresses");
+ }
+ }
+ }
+
+
+ // public sets
+
+
+ /**
+ * Sets the debug output level. Must be either {@link EtConstants#debugNone},
+ * {@link EtConstants#debugSevere}, {@link EtConstants#debugError},
+ * {@link EtConstants#debugWarn}, or {@link EtConstants#debugInfo}.
+ *
+ * @param debug debug level
+ * @throws EtException
+ * if bad argument value
+ */
+ public void setDebug(int debug) throws EtException {
+ if ((debug != EtConstants.debugNone) &&
+ (debug != EtConstants.debugSevere) &&
+ (debug != EtConstants.debugError) &&
+ (debug != EtConstants.debugWarn) &&
+ (debug != EtConstants.debugInfo)) {
+ throw new EtException("bad debug argument");
+ }
+ this.debug = debug;
+ }
+
+
+ // public gets
+
+
+ /** Gets the total number of events of the opened ET system.
+ * @return total number of events */
+ public int getNumEvents() {return numEvents;}
+
+ /** Gets the size of the normal events in bytes of the opened ET system.
+ * @return size of normal events in bytes */
+ public long getEventSize() {return eventSize;}
+
+ /** Gets the tcp server port number of the opened ET system.
+ * @return tcp server port number */
+ public int getTcpPort() {return tcpPort;}
+
+ /** Gets the address (dot decimal) of the host the opened ET system is running on.
+ * @return the address (dot decimal) of the host the opened ET system is running on */
+ public String getHostAddress() {return hostAddress;}
+
+ /** Gets list of all the IP addresses (dot decimal) of the host the opened ET system is running on.
+ * @return list of all the IP addresses (dot decimal) of the host the opened ET system is running on */
+ public ArrayList<String> getHostAddresses() {return hostAddresses;}
+
+ /** Gets the name of the ET system (file).
+ * @return ET system name */
+ public String getName() {return config.getEtName();}
+
+ /** Gets the endian value of the opened ET system.
+ * @return endian value */
+ public int getEndian() {return endian;}
+
+ /** Gets the major version number of the opened ET system.
+ * @return major ET version number */
+ public int getVersion() {return version;}
+
+ /** Gets the language used to implement the opened ET system.
+ * @return language */
+ public int getLanguage() {return language;}
+
+ /** Gets the number of station select integers of the opened ET system.
+ * @return number of select integers */
+ public int getSelectInts() {return stationSelectInts;}
+
+ /** Gets the socket connecting this object to the ET system.
+ * @return socket */
+ public Socket getSocket() {return sock;}
+
+ /** Gets the debug output level.
+ * @return debug output level */
+ public int getDebug() {return debug;}
+
+ /** Gets a copy of the EtSystemOpenConfig configuration object.
+ * @return copy of configuration object */
+ public EtSystemOpenConfig getConfig() {return new EtSystemOpenConfig(config);}
+
+ /** Gets whether the ET system is connected (opened) or not.
+ * @return status of connection to ET system */
+ synchronized public boolean isConnected() {return connected;}
+
+ /** Gets whether the operating system is 64 bit or not.
+ * @return <code>true</code> if the operating system is 64 bit, else <code>false</code> */
+ public boolean isBit64() {return bit64;}
+
+ /** Gets a map of the hosts and ports of responding ET systems to broad/multicasts.
+ * @return a map of the hosts and ports of responding ET systems to broad/multicasts */
+ public LinkedHashMap<ArrayList<String>, Integer> getResponders() {return responders;}
+
+ /** Gets whether opening a local, C-based ET system and trying to map the memory containing
+ * the event data instead of sending it over sockets.
+ * @return <code>true</code> if opening a local, C-based ET system and trying to map the memory containing
+ * the event data instead of sending it over sockets */
+ public boolean isMapLocalSharedMemory() {return mapLocalSharedMemory;}
+
+ /** Gets buffer containing the memory mapped file if {@link #isMapLocalSharedMemory} returns true.
+ * @return buffer contained the memory mapped file */
+ public MappedByteBuffer getBuffer() {return buffer;}
+
+ /** Gets the object used to access native methods when using local, C-based ET system. */
+ public EtJniAccess getJni() {return jni;}
+
+
+ // The next two methods are really only useful when the
+ // EtTooManyException is thrown from "connect" or findServerPort.
+
+
+ /** Gets all host names when multiple ET systems respond.
+ * @return all host names from responding ET systems */
+ public String[] getAllHosts() {
+ if (responders.size() == 0) {
+ if (hostAddress == null) {
+ return null;
+ }
+ return new String[] {hostAddress};
+ }
+ return (String []) responders.keySet().toArray();
+ }
+
+ /** Gets all port numbers when multiple ET systems respond.
+ * @return all port numbers from responding ET systems */
+ public int[] getAllPorts() {
+ if (responders.size() == 0) {
+ if (tcpPort == 0) {
+ return null;
+ }
+ return new int[] {tcpPort};
+ }
+
+ Integer[] p = (Integer []) responders.values().toArray();
+ int[] ports = new int[p.length];
+ for (int i=0; i < p.length; i++) {
+ ports[i] = p[i];
+ }
+ return ports;
+ }
+
+
+ /**
+ * Finds the ET system's tcp server port number and host.
+ *
+ * @return <code>true</code> if server found, else <code>false</code>
+ *
+ * @throws java.io.IOException
+ * if problems with network communications
+ * @throws java.net.UnknownHostException
+ * if the host address(es) is(are) unknown
+ * @throws EtTooManyException
+ * if there were more than one valid response when policy is set to
+ * {@link EtConstants#policyError} and we are looking either
+ * remotely or anywhere for the ET system.
+ */
+ private boolean findServerPort() throws IOException, UnknownHostException, EtTooManyException {
+
+ boolean match = noMatch;
+ int status, totalPacketsSent = 0, sendPacketLimit = 4;
+ int timeOuts[] = {100, 2000, 4000, 7000};
+ int waitTime, socketTimeOut = 20000; // socketTimeOut > sum of timeOuts
+ String specifiedHost = null;
+ HashSet<String> knownHostIpAddrs = new HashSet<String>();
+
+ // clear out any previously stored objects
+ responders.clear();
+ hostAddresses.clear();
+
+ // Put outgoing packet info into a byte array to send to ET systems
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(122);
+ DataOutputStream dos = new DataOutputStream(baos);
+
+ // write magic #s
+ dos.writeInt(EtConstants.magicNumbers[0]);
+ dos.writeInt(EtConstants.magicNumbers[1]);
+ dos.writeInt(EtConstants.magicNumbers[2]);
+ // write ET version
+ dos.writeInt(EtConstants.version);
+ // write string length of ET name
+ dos.writeInt(config.getEtName().length() + 1);
+ // write ET name
+ try {
+ dos.write(config.getEtName().getBytes("ASCII"));
+ dos.writeByte(0);
+ }
+ catch (UnsupportedEncodingException ex) {/* will never happen */}
+ dos.flush();
+
+ // construct byte array to send over a socket
+ final byte sbuffer[] = baos.toByteArray();
+ dos.close();
+ baos.close();
+
+ // We may need to send packets over many different sockets
+ // as there may be broadcasting on multiple subnets as well
+ // as multicasts on several addresses. Keep track of these
+ // sockets, addresses, & packets with this class:
+ class send {
+ int port;
+ String address;
+ InetAddress addr;
+ MulticastSocket socket;
+ DatagramPacket packet;
+
+ send (String address, MulticastSocket socket, int port) throws UnknownHostException {
+ this.port = port;
+ this.address = address;
+ this.socket = socket;
+ addr = InetAddress.getByName(address); //UnknownHostEx
+ packet = new DatagramPacket(sbuffer, sbuffer.length, addr, port);
+ }
+ }
+
+ // store all places to send packets to in a list
+ LinkedList<send> sendList = new LinkedList<send>();
+
+ // find local host
+ String localHost = null;
+ InetAddress localAddr = null;
+ try {
+ localAddr = InetAddress.getLocalHost();
+ localHost = localAddr.getHostName();
+ }
+ catch (UnknownHostException ex) {}
+
+ // If the host is not remote or anywhere out there. If it's
+ // local or we know its name, send a UDP packet to it alone.
+ if ((!config.getHost().equals(EtConstants.hostRemote)) &&
+ (!config.getHost().equals(EtConstants.hostAnywhere))) {
+
+ // We can use multicast socket for regular UDP - it works
+ MulticastSocket socket = new MulticastSocket(); //IOEx
+ // Socket will unblock after timeout,
+ // letting reply collecting thread quit
+ try {socket.setSoTimeout(socketTimeOut);}
+ catch (SocketException ex) {}
+
+ // If it's local, find name and send packet directly there.
+ // This will work in Java where the server listens on all addresses.
+ // But it won't work for C where only broad and multicast address
+ // are listened to.
+ if ((config.getHost().equals(EtConstants.hostLocal)) ||
+ (config.getHost().equals("localhost"))) {
+ specifiedHost = localHost;
+ // else if we know host's name ...
+ } else {
+ specifiedHost = config.getHost();
+ }
+
+ // get set of all host's IP addresses (dot-decimal)
+ InetAddress[] haddrs = InetAddress.getAllByName(specifiedHost); // UnknownHostException
+ for (InetAddress ia : haddrs) {
+ knownHostIpAddrs.add(ia.getHostAddress());
+ }
+
+ sendList.add(new send(specifiedHost, socket, config.getUdpPort()));
+
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("findServerPort: send to local or specified host " + specifiedHost +
+ " on port " + config.getUdpPort());
+ }
+ }
+ // else if the host name is not specified, and it's either
+ // remote or anywhere out there, broad/multicast to find it
+ else { }
+
+
+ // setup broadcast sockets & packets first
+ if ((config.getNetworkContactMethod() == EtConstants.broadcast) ||
+ (config.getNetworkContactMethod() == EtConstants.broadAndMulticast)) {
+
+ // if no broadcast addresses have been specifically set, use 255.255.255.255
+ if (config.getBroadcastAddrs().size() < 1) {
+ // We can use multicast socket for broadcasting - it works
+ MulticastSocket socket = new MulticastSocket(); //IOEx
+ // Socket will unblock after timeout,
+ // letting reply collecting thread quit
+ try {
+ socket.setSoTimeout(socketTimeOut);
+ socket.setBroadcast(true);
+ }
+ catch (SocketException ex) {
+ }
+
+ sendList.add(new send(config.broadcastIP, socket, config.getUdpPort()));
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("findServerPort: broadcasting to " + config.broadcastIP +
+ " on port " + config.getUdpPort());
+ }
+ }
+ // otherwise only broadcast on addresses specifically set
+ else {
+ for (String addr : config.getBroadcastAddrs()) {
+ MulticastSocket socket = new MulticastSocket(); //IOEx
+ try {
+ socket.setSoTimeout(socketTimeOut);
+ socket.setBroadcast(true);
+ }
+ catch (SocketException ex) {
+ }
+
+ sendList.add(new send(addr, socket, config.getUdpPort()));
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("findServerPort: broadcasting to " + addr +
+ " on port " + config.getUdpPort());
+ }
+ }
+ }
+ }
+
+ // setup multicast sockets & packets next
+ if ((config.getNetworkContactMethod() == EtConstants.multicast) ||
+ (config.getNetworkContactMethod() == EtConstants.broadAndMulticast)) {
+
+ for (String addr : config.getMulticastAddrs()) {
+ MulticastSocket socket = new MulticastSocket(); //IOEx
+ try {
+ socket.setSoTimeout(socketTimeOut);
+ }
+ catch (SocketException ex) {
+ }
+
+ if (config.getTTL() != 1) {
+ socket.setTimeToLive(config.getTTL()); //IOEx
+ }
+
+ sendList.add(new send(addr, socket, config.getMulticastPort()));
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("findServerPort: multicasting to " + addr + " on port " + config.getMulticastPort());
+ }
+ }
+ }
+
+
+ /** Class to help receive a packet on a socket. */
+ class get {
+ // min data size = 8*4 + 3 + Constants.ipAddrStrLen +
+ // 2*Constants.maxHostNameLen(); = 558 bytes
+ // but give us a bit of extra room for lots of names with 4k bytes
+ byte[] buffer = new byte[4096];
+ DatagramReceive thread;
+ DatagramPacket packet;
+ MulticastSocket socket;
+
+ get(MulticastSocket sock) {
+ packet = new DatagramPacket(buffer, buffer.length);
+ socket = sock;
+ }
+
+ // start up thread to receive single udp packet on single socket
+ void start() {
+ thread = new DatagramReceive(packet, socket);
+ thread.start();
+ }
+ }
+
+ // store things here
+ LinkedList<get> receiveList = new LinkedList<get>();
+
+ // start reply collecting threads
+ for (send sender : sendList) {
+ get receiver = new get(sender.socket);
+ receiveList.add(receiver);
+ // start single thread
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("findServerPort: starting thread to socket " + sender.socket);
+ }
+ receiver.start();
+ }
+
+ Thread.yield();
+
+ sendPoint:
+ // set a limit on the total # of packet groups sent out to find a server
+ while (totalPacketsSent < sendPacketLimit) {
+ // send packets out on all sockets
+ for (send sender : sendList) {
+ sender.socket.send(sender.packet); //IOException
+ }
+ // set time to wait for reply (gets longer with each round)
+ waitTime = timeOuts[totalPacketsSent++];
+
+ get:
+ while (true) {
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("findServerPort: wait for " + waitTime + " milliseconds");
+ }
+ // wait for replies
+ try {
+ Thread.sleep(waitTime);
+ }
+ catch (InterruptedException ix) {
+ }
+
+ // check for replies on all sockets
+ for (get receiver : receiveList) {
+ status = receiver.thread.waitForReply(10);
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("findServerPort: receive on socket " + receiver.socket +
+ ", status = " + status);
+ }
+
+ // if error or timeout ...
+ if ((status == DatagramReceive.error) || (status == DatagramReceive.timedOut)) {
+ // continue;
+ }
+
+ // else if got packet ...
+ else if (status == DatagramReceive.receivedPacket) {
+ // Analyze packet to see if it matches the ET system we were
+ // looking for; if not, try to get another packet. If it
+ // is a match, store it in a HashMap (responders).
+ if (replyMatch(receiver.packet, knownHostIpAddrs)) { // IOEx, UnknownHostEx
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("findServerPort: found match");
+ }
+ match = gotMatch;
+ }
+ else {
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("findServerPort: no match");
+ }
+ }
+ // See if there are other packets cued up,
+ // but don't wait too long. The thread we
+ // started is ended so start another up again.
+ waitTime = 50;
+ receiver.start();
+ Thread.yield();
+
+ continue get;
+ }
+
+ }
+
+
+ // if we don't have a match, try again
+ if (!match) {
+ // If max # of packets not yet sent, send another
+ // batch and try again with a longer wait
+ if (totalPacketsSent < sendPacketLimit) {
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("findServerPort: timedout, try again with longer wait");
+ }
+ continue sendPoint;
+ }
+ }
+
+ break sendPoint;
+
+ } // while (true)
+ } // while (totalPacketsSent < sendPacketLimit)
+
+
+ if (match) {
+ // If the host is not remote or anywhere (i.e. we know its name) ...
+ if ((!config.getHost().equals(EtConstants.hostRemote)) &&
+ (!config.getHost().equals(EtConstants.hostAnywhere))) {
+
+ // In this case we only keep a single response even
+ // though there may be more since each of these must
+ // have come from the same ET system.
+ }
+ // if we're looking remotely or anywhere
+ else {
+ // if we have more than one responding ET system
+ if (responders.size() > 1) {
+ // if picking first responding ET system ...
+ if (config.getResponsePolicy() == EtConstants.policyFirst) {
+ Iterator<Map.Entry<ArrayList<String>,Integer>> i = responders.entrySet().iterator();
+ Map.Entry<ArrayList<String>,Integer> entry = i.next();
+ hostAddresses = entry.getKey();
+ hostAddress = hostAddresses.get(0);
+ tcpPort = entry.getValue();
+ etOnLocalHost = isHostLocal(hostAddresses);
+ }
+ // else if picking local system first ...
+ else if (config.getResponsePolicy() == EtConstants.policyLocal) {
+ // compare local host to responding hosts
+ etOnLocalHost = false;
+
+ for (Map.Entry<ArrayList<String>, Integer> entry : responders.entrySet()) {
+ ArrayList<String> addrList = entry.getKey();
+ // see if this responder is local
+ if (isHostLocal(addrList)) {
+ hostAddresses = entry.getKey();
+ hostAddress = hostAddresses.get(0);
+ tcpPort = entry.getValue();
+ etOnLocalHost = true;
+ break;
+ }
+ }
+
+ // if no local host found, pick first responder
+ if (!etOnLocalHost) {
+ Iterator<Map.Entry<ArrayList<String>,Integer>> i = responders.entrySet().iterator();
+ Map.Entry<ArrayList<String>,Integer> entry = i.next();
+ hostAddresses = entry.getKey();
+ hostAddress = hostAddresses.get(0);
+ tcpPort = entry.getValue();
+ }
+ }
+ // else if policy.Error
+ else {
+ throw new EtTooManyException("too many responding ET systems");
+ }
+ }
+ }
+ return foundServer;
+ }
+
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("findServerPort: cannot find server, quitting");
+ }
+
+ hostAddresses.clear();
+ hostAddress = null;
+ tcpPort = 0;
+
+ return cannotFindServer;
+ }
+
+
+ /**
+ * Analyze a received UDP packet & see if it matches the ET system we're looking for.
+ *
+ * @param packet responding UDP packet
+ * @throws java.io.IOException
+ * if problems with network comunications
+ * @throws java.net.UnknownHostException
+ * if the replied host address(es) is(are) unknown
+ */
+ private boolean replyMatch(DatagramPacket packet, HashSet<String> knownHostIpAddrs)
+ throws IOException, UnknownHostException {
+
+ byte buf[];
+ ByteArrayInputStream bais = new ByteArrayInputStream(packet.getData());
+ DataInputStream dis = new DataInputStream(bais);
+ // In case of multiple addresses from a responding ET system, a list of addresses. */
+ ArrayList<String> addresses = new ArrayList<String>(20);
+
+ // decode packet from ET system: (NEW!!!)
+ //
+ // (0) ET magic numbers (3 ints)
+ // (1) ET version #
+ // (2) port of tcp server thread (not udp config->port)
+ // (3) Constants.broadcast .multicast or broadAndMulticast (int)
+ // (4) length of next string
+ // (5) broadcast address (dotted-dec) if broadcast received or
+ // multicast address (dotted-dec) if multicast received
+ // (see int #3)
+ // (6) length of next string
+ // (7) hostname given by "uname" (used as a general
+ // identifier of this host no matter which interface is used)
+ // (8) length of next string
+ // (9) canonical name of host
+ // (10) number of IP addresses
+ // (11) 32bit, net-byte ordered IPv4 address assoc with following address
+ // (12) length of next string
+ // (13) first dotted-decimal IPv4 address
+ // (14) 32bit, net-byte ordered IPv4 address assoc with following address
+ // (15) length of next string
+ // (16) second dotted-decimal IPv4 address ...
+ //
+ // All known IP addresses are sent here both in numerical & dotted-decimal forms.
+ //
+
+
+ // (0) ET magic numbers (3 ints)
+ int magic1 = dis.readInt();
+ int magic2 = dis.readInt();
+ int magic3 = dis.readInt();
+ if (magic1 != EtConstants.magicNumbers[0] ||
+ magic2 != EtConstants.magicNumbers[1] ||
+ magic3 != EtConstants.magicNumbers[2]) {
+//System.out.println("replyMatch: Magic numbers did NOT match");
+ return noMatch;
+ }
+
+ // (1) ET version #
+ int version = dis.readInt(); //IOEx
+ if (version != EtConstants.version) {
+//System.out.println("replyMatch: version did NOT match");
+ return noMatch;
+ }
+//System.out.println("replyMatch: version = " + version);
+
+ // (2) server port #
+ int port = dis.readInt();
+ if ((port < 1) || (port > 65536)) {
+ return noMatch;
+ }
+//System.out.println("replyMatch: server port = " + port);
+
+ // (3) response to what type of cast?
+ int cast = dis.readInt();
+ if ((cast != EtConstants.broadcast) &&
+ (cast != EtConstants.multicast) &&
+ (cast != EtConstants.broadAndMulticast)) {
+ return noMatch;
+ }
+
+// if (cast == EtConstants.broadcast) {
+// System.out.println("replyMatch: broadcasting");
+// }
+// else if (cast != EtConstants.multicast) {
+// System.out.println("replyMatch: multicasting");
+// }
+// else if (cast != EtConstants.broadAndMulticast) {
+// System.out.println("replyMatch: broad & multi casting");
+// }
+// else {
+// System.out.println("replyMatch: don't know if broad or multi casting");
+// }
+
+ // (4) read length of IP address (dotted-decimal) of responding address
+ // or 0.0.0.0 if java
+ int length = dis.readInt();
+ if ((length < 1) || (length > EtConstants.ipAddrStrLen)) {
+ return noMatch;
+ }
+
+ // (5) read IP address
+ buf = new byte[length];
+ dis.readFully(buf, 0, length);
+ String repliedIpAddress = null;
+ try {repliedIpAddress = new String(buf, 0, length - 1, "ASCII");}
+ catch (UnsupportedEncodingException e) {/*never happens*/}
+//System.out.println("replyMatch: IP address = " + repliedIpAddress);
+
+ // (6) Read length of "uname" or InetAddress.getLocalHost().getHostName() if java,
+ // used as identifier of this host no matter which interface used.
+ length = dis.readInt();
+ if ((length < 1) || (length > EtConstants.maxHostNameLen)) {
+ return noMatch;
+ }
+
+ // (7) read uname
+ buf = new byte[length];
+ dis.readFully(buf, 0, length);
+ String repliedUname = null;
+ try {repliedUname = new String(buf, 0, length - 1, "ASCII");}
+ catch (UnsupportedEncodingException e) {}
+//System.out.println("replyMatch: uname len = " + length);
+//System.out.println("replyMatch: uname = " + repliedUname);
+
+ // (8) Read length of canonical name
+ length = dis.readInt();
+ if ((length < 1) || (length > EtConstants.maxHostNameLen)) {
+ return noMatch;
+ }
+
+ // (9) read canonical name
+ buf = new byte[length];
+ dis.readFully(buf, 0, length);
+ String canonicalName = null;
+ try {canonicalName = new String(buf, 0, length - 1, "ASCII");}
+ catch (UnsupportedEncodingException e) {}
+//System.out.println("replyMatch: canonical name len = " + length);
+//System.out.println("replyMatch: canonical name = " + canonicalName);
+
+ // (10) # of following addresses
+ int numAddrs = dis.readInt();
+ if (numAddrs < 0) {
+ return noMatch;
+ }
+//System.out.println("replyMatch: # of addresses to come = " + numAddrs);
+
+ int addr;
+ String repliedHostAddress = null;
+
+ for (int i=0; i<numAddrs; i++) {
+ // (11) 32 bit network byte ordered address - not currently used
+ addr = dis.readInt();
+//System.out.println("replyMatch: addr #" + i + ": numeric addr = " + addr);
+
+ // (12) read length of string address of responding host
+ length = dis.readInt();
+//System.out.println("replyMatch: addr #" + i + ": string len = " + length);
+
+ // (13) read host address (minus ending null)
+ buf = new byte[length];
+ dis.readFully(buf, 0, length);
+ try {repliedHostAddress = new String(buf, 0, length - 1, "ASCII");}
+ catch (UnsupportedEncodingException e) {}
+//System.out.println("replyMatch: addr #" + i + ": string addr = " + repliedHostAddress);
+
+ // store things
+ addresses.add(repliedHostAddress);
+ }
+
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("replyMatch: port = " + port +
+ ", replied IP addr = " + repliedIpAddress +
+ ", uname = " + repliedUname);
+ for (int i=0; i<numAddrs; i++) {
+ System.out.println(" : addr " + (i + 1) + " = " + addresses.get(i));
+ }
+ System.out.println();
+ }
+
+ dis.close();
+ bais.close();
+
+ //InetAddress localHost = InetAddress.getLocalHost(); //UnknownHostEx
+
+ // if we're looking for a host anywhere
+ if (config.getHost().equals(EtConstants.hostAnywhere)) {
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("replyMatch: ET is anywhere, addresses = ");
+ for (String address : addresses) {
+ System.out.println(" " + address);
+ }
+ }
+
+ // Store host & port in ordered map in case there are several systems
+ // that respond and user must chose which one he wants.
+
+ // Potential difficulty here is that the host may be responding with
+ // several address, but we're only using one. What if our
+ // host does not know about this particular IP address? It may not
+ // be able to connect, but might be able to with one of the others.
+ // How do we fix this problem?
+ responders.put(addresses, port);
+
+ // store info here in case only 1 response
+ hostAddresses = addresses;
+ hostAddress = addresses.get(0);
+ tcpPort = port;
+ return gotMatch;
+ }
+
+ // else if we're looking for a remote host
+ else if (config.getHost().equals(EtConstants.hostRemote)) {
+ for (String address : addresses) {
+ for (String localIP : localHostIpAddrs) {
+ // if ET system's address matches a local one, it's not remote
+ if (localIP.equals(address)) {
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("replyMatch: ET is local but looking for remote, " + address);
+ }
+
+ return noMatch;
+ }
+ }
+ }
+
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("replyMatch: ET is remote, addresses = ");
+ for (String address : addresses) {
+ System.out.println(" " + address);
+ }
+ }
+
+ // If we're here, then we have a remote responder.
+ // Store address(es) & port in lists in case there are several systems
+ // that respond and user must chose which one he wants
+ responders.put(addresses, port);
+
+ // store info here in case only 1 response
+ etOnLocalHost = false;
+ hostAddresses = addresses;
+ hostAddress = addresses.get(0);
+ tcpPort = port;
+ return gotMatch;
+ }
+
+ // else if we're looking for a local host
+ else if ((config.getHost().equals(EtConstants.hostLocal)) ||
+ (config.getHost().equals("localhost"))) {
+
+ for (String address : addresses) {
+ for (String localIP : localHostIpAddrs) {
+ if (localIP.equals(address)) {
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("replyMatch: ET is local, " + address);
+ }
+
+ // Store values. In this case no other match will be examined.
+ etOnLocalHost = true;
+ hostAddresses = addresses;
+ hostAddress = address;
+ tcpPort = port;
+ return gotMatch;
+ }
+ }
+ }
+
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("replyMatch: no local match");
+ }
+ }
+
+ // else a specific host name has been specified
+ else {
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("replyMatch: <name>, addresses = ");
+ for (String address : addresses) {
+ System.out.println(" " + address);
+ }
+ }
+
+ for (String address : addresses) {
+ for (String hostIP : knownHostIpAddrs) {
+//System.out.println("replyMatch: compare " + address + " to " + hostIP);
+ if (hostIP.equals(address)) {
+ if (debug >= EtConstants.debugInfo) {
+ System.out.println("replyMatch: <name> matched, " + address);
+ }
+
+ // Store values. In this case no other match will be examined.
+ etOnLocalHost = isHostLocal(addresses);
+ hostAddresses = addresses;
+ hostAddress = address;
+ tcpPort = port;
+ return gotMatch;
+ }
+ }
+ }
+ }
+
+ return noMatch;
+ }
+
+
+ /**
+ * Connect to ET system's server.
+ *
+ * @throws IOException
+ * if problems with network communications
+ * @throws EtException
+ * if the responing ET system has the wrong name, runs a different version
+ * of ET, or has a different value for {@link EtConstants#stationSelectInts}
+ */
+ private void connectToEtServer() throws IOException, EtException {
+
+ DataInputStream dis = new DataInputStream(sock.getInputStream());
+ DataOutputStream dos = new DataOutputStream(sock.getOutputStream());
+
+ // write magic #s
+ dos.writeInt(EtConstants.magicNumbers[0]);
+ dos.writeInt(EtConstants.magicNumbers[1]);
+ dos.writeInt(EtConstants.magicNumbers[2]);
+
+ // write our endian, length of ET filename, and ET filename
+ dos.writeInt(EtConstants.endianBig);
+ dos.writeInt(config.getEtName().length() + 1);
+ dos.writeInt(0); // 1 means 64 bit, 0 means 32 bit (all java is 32 bit)
+ dos.writeLong(0L); // write one 64 bit long instead of 2, 32 bit ints since = 0 anyway
+ try {
+ dos.write(config.getEtName().getBytes("ASCII"));
+ dos.writeByte(0);
+ }
+ catch (UnsupportedEncodingException ex) {/* will never happen */}
+ dos.flush();
+
+ // read what ET's tcp server sends back
+ if (dis.readInt() != EtConstants.ok) {
+ throw new EtException("found the wrong ET system");
+ }
+ endian = dis.readInt();
+ numEvents = dis.readInt();
+ eventSize = dis.readLong();
+ version = dis.readInt();
[truncated at 1000 lines; 475 more skipped]
hps-et-java/src/main/java/org/jlab/coda/et
diff -N EtSystemOpenConfig.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtSystemOpenConfig.java 13 Feb 2012 22:50:52 -0000 1.3
@@ -0,0 +1,804 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et;
+
+import java.lang.*;
+import java.util.*;
+import java.net.*;
+import org.jlab.coda.et.exception.*;
+
+/**
+ * This class defines a set of configuration parameters used to open an ET system.
+ *
+ * @author Carl Timmer
+ */
+public class EtSystemOpenConfig {
+
+ /** Broadcast address. */
+ static public final String broadcastIP = "255.255.255.255";
+
+
+ /** ET system name. */
+ private String name;
+
+ /** Either ET system host name or destination of broadcasts and multicasts. */
+ private String host;
+
+ /** Network interface used for actually connecting to ET system. */
+ private String networkInterface;
+
+ /** Are we broadcasting on all local subnets to find ET system? */
+ private boolean broadcasting;
+
+ /** Broadcast addresses. */
+ private HashSet<String> broadcastAddrs;
+
+ /** Multicast addresses. */
+ private HashSet<String> multicastAddrs;
+
+ /**
+ * If true, only connect to ET systems with sockets (remotely). If false, try
+ * opening any local C-based ET systems using mapped memory and JNI interface.
+ */
+ private boolean connectRemotely;
+
+ /**
+ * Means used to contact an ET system over network. The possible values are
+ * @link Constants#broadcast} for broadcasting, {@link EtConstants#multicast}
+ * for multicasting, {@link EtConstants#direct} for connecting directly to the
+ * ET tcp server, and {@link EtConstants#broadAndMulticast} for using both
+ * broadcasting and multicasting.
+ */
+ private int networkContactMethod;
+
+ /** UDP port number for broadcasting or sending udp packets to known hosts. */
+ private int udpPort;
+
+ /** TCP server port number of the ET system. */
+ private int tcpPort;
+
+ /** Port number to multicast to. In Java, a multicast socket cannot have same
+ * port number as another datagram socket. */
+ private int multicastPort;
+
+ /** Time-to-live value for multicasting. */
+ private int ttl;
+
+ /**
+ * Policy on what to do about multiple responding ET systems to a broadcast
+ * or multicast. The possible values are {@link EtConstants#policyFirst} which
+ * chooses the first ET system to respond, {@link EtConstants#policyLocal}
+ * which chooses the first local ET system to respond and if none then the
+ * first response, or {@link EtConstants#policyError} which throws an
+ * EtTooManyException exception.
+ */
+ private int responsePolicy;
+
+ /** If no ET system is available, how many milliseconds do we wait while trying to open it? */
+ private long waitTime;
+
+ /** TCP send buffer size in bytes. */
+ private int tcpSendBufSize;
+
+ /** TCP receive buffer size in bytes. */
+ private int tcpRecvBufSize;
+
+ /**
+ * TCP socket's no-delay setting.
+ * <code>True</code> if no delay, else <code>false</code>.
+ */
+ private boolean noDelay;
+
+
+ /**
+ * No arg constructor.
+ * Only ET name and host need to be set.
+ */
+ public EtSystemOpenConfig() {
+ // some default values
+ broadcasting = true;
+ connectRemotely = false;
+ networkContactMethod = EtConstants.broadcast;
+ multicastPort = EtConstants.multicastPort;
+ udpPort = EtConstants.broadcastPort;
+ tcpPort = EtConstants.serverPort;
+ ttl = 32;
+ responsePolicy = EtConstants.policyError;
+ broadcastAddrs = new HashSet<String>(10);
+ multicastAddrs = new HashSet<String>(10);
+ }
+
+
+ /**
+ * Most general constructor for creating a new EtSystemOpenConfig object.
+ *
+ * @param etName ET system name
+ * @param hostName may open an ET system on the given host which could be the:
+ * 1) actual ET system's host name,
+ * 2) dotted decimal address of ET system's host, or
+ * 3) general location of ET system such as {@link EtConstants#hostAnywhere},
+ * {@link EtConstants#hostLocal}, or {@link EtConstants#hostRemote}
+ * @param bAddrs collection of broadcast addresses (as Strings) to broadcast on in order to
+ * find ET system
+ * @param mAddrs collection of multicast addresses (as Strings) to multicast to in order to
+ * find ET system
+ * @param remoteOnly <code>true</code> if talking to ET system only through sockets
+ * (as if remote), or <code>false</code> if also using JNI/shared memory
+ * for talking to local C-based ET systems
+ * @param method means used to contact an ET system over the network:
+ * {@link EtConstants#broadcast}, {@link EtConstants#multicast},
+ * {@link EtConstants#direct}, or {@link EtConstants#broadAndMulticast}
+ * @param tPort TCP server port number of the ET system
+ * @param uPort UDP port number for broadcasting or sending udp packets to known hosts
+ * @param mPort Port number to multicast to
+ * @param ttlNum Time-to_live value for multicasting
+ * @param policy policy on what to do about multiple responding ET systems to
+ * a broadcast or multicast: {@link EtConstants#policyFirst},
+ * {@link EtConstants#policyLocal}, or {@link EtConstants#policyError}
+ *
+ * @throws EtException
+ * if method value is not valid;
+ * if method is not direct and no broad/multicast addresses were specified;
+ * if method is direct and no actual host name was specified;
+ * if port numbers are < 1024 or > 65535;
+ * if ttl is < 0 or > 254;
+ * if string args are null or blank;
+ * if policy value is not valid
+ */
+ public EtSystemOpenConfig(String etName, String hostName,
+ Collection<String> bAddrs, Collection<String> mAddrs,
+ boolean remoteOnly,
+ int method, int tPort, int uPort,
+ int mPort, int ttlNum, int policy)
+ throws EtException {
+
+ name = etName;
+ if (etName == null || etName.equals("")) {
+ throw new EtException("Bad ET system name");
+ }
+
+ host = hostName;
+ if (host == null || host.equals("")) {
+ if (method != EtConstants.broadcast) {
+ throw new EtException("Bad host or location name");
+ }
+ }
+
+ if ((bAddrs == null) || (bAddrs.size() < 1)) {
+ broadcastAddrs = new HashSet<String>(10);
+ }
+ else {
+ broadcastAddrs = new HashSet<String>(bAddrs);
+ }
+
+ boolean noMulticastAddrs = true;
+ if ((mAddrs == null) || (mAddrs.size() < 1)) {
+ multicastAddrs = new HashSet<String>(10);
+ }
+ else {
+ multicastAddrs = new HashSet<String>(mAddrs);
+ noMulticastAddrs = false;
+ }
+
+ connectRemotely = remoteOnly;
+
+ if ((method != EtConstants.multicast) &&
+ (method != EtConstants.broadcast) &&
+ (method != EtConstants.broadAndMulticast) &&
+ (method != EtConstants.direct)) {
+ throw new EtException("Bad contact method value");
+ }
+ else {
+ networkContactMethod = method;
+ }
+
+ // do we broadcast?
+ broadcasting = networkContactMethod == EtConstants.broadcast ||
+ networkContactMethod == EtConstants.broadAndMulticast;
+
+ // inconsistencies?
+ if (networkContactMethod == EtConstants.direct) {
+ if (host.equals(EtConstants.hostRemote) ||
+ host.equals(EtConstants.hostAnywhere)) {
+ throw new EtException("Need to specify an actual host name");
+ }
+ }
+ else if ( ((networkContactMethod == EtConstants.multicast) ||
+ (networkContactMethod == EtConstants.broadAndMulticast)) &&
+ noMulticastAddrs) {
+ throw new EtException("Need to specify a multicast address");
+ }
+
+
+ if ((uPort < 1024) || (uPort > 65535)) {
+ throw new EtException("Bad UDP port value");
+ }
+ udpPort = uPort;
+
+ if ((tPort < 1024) || (tPort > 65535)) {
+ throw new EtException("Bad TCP port value");
+ }
+ tcpPort = tPort;
+
+ if ((mPort < 1024) || (mPort > 65535)) {
+ throw new EtException("Bad multicast port value");
+ }
+ multicastPort = mPort;
+
+
+ if ((ttlNum < 0) || (ttlNum > 254)) {
+ throw new EtException("Bad TTL value");
+ }
+ ttl = ttlNum;
+
+
+ if ((policy != EtConstants.policyFirst) &&
+ (policy != EtConstants.policyLocal) &&
+ (policy != EtConstants.policyError)) {
+ throw new EtException("Bad policy value");
+ }
+
+ if ((host.equals(EtConstants.hostRemote)) &&
+ (policy == EtConstants.policyLocal)) {
+ // stupid combination of settings
+ throw new EtException("Policy value cannot be local if host is remote");
+ }
+ responsePolicy = policy;
+ }
+
+
+ /**
+ * Constructor for broadcasting on all subnets. First responder is chosen.
+ *
+ * @param etName ET system name
+ * @param hostName may open an ET system on the given host which could be the:
+ * 1) actual ET system's host name,
+ * 2) dotted decimal address of ET system's host, or
+ * 3) general location of ET system such as {@link EtConstants#hostAnywhere},
+ * {@link EtConstants#hostLocal}, or {@link EtConstants#hostRemote}
+ *
+ * @throws EtException
+ * if no broadcast addresses were specified;
+ * if port number is < 1024 or > 65535
+ */
+ public EtSystemOpenConfig(String etName, String hostName)
+ throws EtException {
+ this (etName, hostName, null, null, false, EtConstants.broadcast,
+ EtConstants.serverPort, EtConstants.broadcastPort, EtConstants.multicastPort,
+ EtConstants.multicastTTL, EtConstants.policyFirst);
+ }
+
+
+ /**
+ * Constructor for broadcasting on all subnets. First responder is chosen.
+ *
+ * @param etName ET system name
+ * @param uPort UDP port number to broadcast to
+ * @param hostName may open an ET system on the given host which could be the:
+ * 1) actual ET system's host name,
+ * 2) dotted decimal address of ET system's host, or
+ * 3) general location of ET system such as {@link EtConstants#hostAnywhere},
+ * {@link EtConstants#hostLocal}, or {@link EtConstants#hostRemote}
+ *
+ * @throws EtException
+ * if no broadcast addresses were specified;
+ * if port number is < 1024 or > 65535
+ */
+ public EtSystemOpenConfig(String etName, int uPort, String hostName)
+ throws EtException {
+ this (etName, hostName, null, null, false, EtConstants.broadcast,
+ EtConstants.serverPort, uPort, EtConstants.multicastPort,
+ EtConstants.multicastTTL, EtConstants.policyFirst);
+ }
+
+
+ /**
+ * Constructor for multicasting. First responder is chosen.
+ *
+ * @param etName ET system name
+ * @param hostName may open an ET system on the given host which could be the:
+ * 1) actual ET system's host name,
+ * 2) dotted decimal address of ET system's host, or
+ * 3) general location of ET system such as {@link EtConstants#hostAnywhere},
+ * {@link EtConstants#hostLocal}, or {@link EtConstants#hostRemote}
+ * @param mAddrs collection of multicast addresses (as Strings)
+ * @param mPort multicasting port number
+ * @param ttlNum multicasting time-to_live value
+ *
+ * @throws EtException
+ * if no multicast addresses were specified;
+ * if port number is < 1024 or > 65535, or ttl is < 0 or > 254
+ */
+ public EtSystemOpenConfig(String etName, String hostName,
+ Collection<String> mAddrs, int mPort, int ttlNum)
+ throws EtException {
+ this (etName, hostName, null, mAddrs, false, EtConstants.multicast,
+ EtConstants.serverPort, EtConstants.broadcastPort, mPort,
+ ttlNum, EtConstants.policyFirst);
+ }
+
+
+ /**
+ * Constructor for multicasting. First responder is chosen.
+ *
+ * @param etName ET system name
+ * @param hostName may open an ET system on the given host which could be the:
+ * 1) actual ET system's host name,
+ * 2) dotted decimal address of ET system's host, or
+ * 3) general location of ET system such as {@link EtConstants#hostAnywhere},
+ * {@link EtConstants#hostLocal}, or {@link EtConstants#hostRemote}
+ * @param mAddrs collection of multicast addresses (as Strings)
+ * @param uPort port number to send direct udp packet to
+ * @param mPort multicasting port number
+ * @param ttlNum multicasting time-to_live value
+ *
+ * @throws EtException
+ * if no multicast addresses were specified;
+ * if port numbers are < 1024 or > 65535, or ttl is < 0 or > 254
+ */
+ public EtSystemOpenConfig(String etName, String hostName,
+ Collection<String> mAddrs, int uPort, int mPort, int ttlNum)
+ throws EtException {
+ this (etName, hostName, null, mAddrs, false, EtConstants.multicast,
+ EtConstants.serverPort, uPort, mPort,
+ ttlNum, EtConstants.policyFirst);
+ }
+
+
+ /**
+ * Constructor for connecting directly to tcp server. First responder is
+ * chosen.
+ *
+ * @param etName ET system name
+ * @param hostName ET system host name
+ * @param tPort TCP server port number of the ET system
+ *
+ * @throws EtException
+ * if no actual host name was specified;
+ * if port number is < 1024 or > 65535
+ */
+ public EtSystemOpenConfig(String etName, String hostName, int tPort)
+ throws EtException {
+ this (etName, hostName, null, null, false, EtConstants.direct,
+ tPort, EtConstants.broadcastPort, EtConstants.multicastPort,
+ EtConstants.multicastTTL, EtConstants.policyFirst);
+ }
+
+
+ /**
+ * Constructor to create a new EtSystemOpenConfig object from another.
+ * @param config EtSystemOpenConfig object from which to create a new configuration
+ */
+ public EtSystemOpenConfig(EtSystemOpenConfig config) {
+ name = config.name;
+ host = config.host;
+ broadcastAddrs = config.getBroadcastAddrs();
+ multicastAddrs = config.getMulticastAddrs();
+ networkContactMethod = config.networkContactMethod;
+ connectRemotely = config.connectRemotely;
+ udpPort = config.udpPort;
+ tcpPort = config.tcpPort;
+ multicastPort = config.multicastPort;
+ ttl = config.ttl;
+ responsePolicy = config.responsePolicy;
+ waitTime = config.waitTime;
+ networkInterface = config.networkInterface;
+ tcpRecvBufSize = config.tcpRecvBufSize;
+ tcpSendBufSize = config.tcpSendBufSize;
+ noDelay = config.noDelay;
+ }
+
+
+ /**
+ * Determine if vital parameters are set and all settings are self consistent.
+ * @return <code>true</code> if setting are self consistent, else <code>false</code>
+ */
+ public boolean selfConsistent() {
+ if (name == null || name.equals("") ||
+ host == null || host.equals("")) {
+ return false;
+ }
+
+ boolean noMulticastAddrs = multicastAddrs.size() < 1;
+
+ if (networkContactMethod == EtConstants.direct) {
+ if (host.equals(EtConstants.hostRemote) ||
+ host.equals(EtConstants.hostAnywhere)) {
+ return false;
+ }
+ }
+ else if ( ((networkContactMethod == EtConstants.multicast) ||
+ (networkContactMethod == EtConstants.broadAndMulticast)) &&
+ noMulticastAddrs) {
+ return false;
+ }
+
+ // stupid combination of settings
+ if ((host.equals(EtConstants.hostRemote)) &&
+ (responsePolicy == EtConstants.policyLocal)) {
+ return false;
+ }
+
+ return true;
+ }
+
+
+ // Getters
+
+
+ /** Gets the ET system name.
+ * @return ET system name */
+ public String getEtName() {return name;}
+
+ /** Gets the ET system host name or general location of ET system.
+ * @return ET system host name or general location of ET system */
+ public String getHost() {return host;}
+
+ /** Gets multicast addresses.
+ * @return multicast addresses */
+ public HashSet<String> getBroadcastAddrs() {return (HashSet<String>) broadcastAddrs.clone();}
+
+ /** Gets multicast addresses.
+ * @return multicast addresses */
+ public HashSet<String> getMulticastAddrs() {return (HashSet<String>) multicastAddrs.clone();}
+
+ /** Gets the means used to contact an ET system.
+ * @return means used to contact an ET system */
+ public int getNetworkContactMethod() {return networkContactMethod;}
+
+ /** Gets policy on what to do about multiple responding ET systems to a
+ * broadcast or multicast.
+ * @return policy on what to do about multiple responding ET systems to a broadcast or multicast */
+ public int getResponsePolicy() {return responsePolicy;}
+
+ /** Gets UDP port number for broadcasting or sending udp packets to known hosts.
+ * @return UDP port number for broadcast or sending udp packets to known hosts */
+ public int getUdpPort() {return udpPort;}
+
+ /** Gets TCP server port number of the ET system.
+ * @return TCP server port number of the ET system */
+ public int getTcpPort() {return tcpPort;}
+
+ /** Gets port number to multicast to.
+ * @return port number to multicast to */
+ public int getMulticastPort() {return multicastPort;}
+
+ /** Gets time-to-live value for multicasting.
+ * @return time-to-live value for multicasting */
+ public int getTTL() {return ttl;}
+
+ /** Gets the number of multicast addresses.
+ * @return the number of multicast addresses */
+ public int getNumMulticastAddrs() {return multicastAddrs.size();}
+
+ /** Are we broadcasting to find ET system?
+ * @return boolean indicating wether we are broadcasting to find ET system */
+ public boolean isBroadcasting() {return broadcasting;}
+
+ /** Set true if we're broadcasting to find ET system. */
+ public void broadcasting(boolean on) {broadcasting = on;}
+
+ /** Are we going to connect to an ET system remotely only (=true), or will
+ * we also try to use memory mapping and JNI with local C-based ET systems?
+ * @return <code>true</code> if connecting to ET system remotely only, else <code>false</code> */
+ public boolean isConnectRemotely() {return connectRemotely;}
+
+ /** If no ET system is available, the number of milliseconds we wait while trying to open it.
+ * @return the number of milliseconds we wait while trying to open ET system */
+ public long getWaitTime() {return waitTime;}
+
+ /** Get the network interface used for connecting to the ET system.
+ * @return the network interface used for connecting to the ET system or null if none specified. */
+ public String getNetworkInterface() {
+ return networkInterface;
+ }
+
+ /** Get the TCP receive buffer size in bytes.
+ * @return TCP receive buffer size in bytes */
+ public int getTcpSendBufSize() {
+ return tcpSendBufSize;
+ }
+
+ /** Get the TCP send buffer size in bytes.
+ * @return TCP send buffer size in bytes */
+ public int getTcpRecvBufSize() {
+ return tcpRecvBufSize;
+ }
+
+ /** Get the TCP no-delay setting.
+ * @return TCP no-delay setting */
+ public boolean isNoDelay() {
+ return noDelay;
+ }
+
+
+ // Setters
+
+
+ /** Sets the ET system name.
+ * @param etName ET system name */
+ public void setEtName(String etName) {name = etName;}
+
+ /** Sets the ET system host name or broad/multicast destination.
+ * @param hostName system host name or broad/multicast destination */
+ public void setHost(String hostName) {host = hostName;}
+
+ /** Removes a multicast address from the set.
+ * @param addr multicast address to be removed */
+ public void removeMulticastAddr(String addr) {multicastAddrs.remove(addr);}
+
+ /** Sets whether we going to connect to an ET system remotely only (=true), or whether
+ * we will try to use memory mapping and JNI with local C-based ET systems.
+ * @param connectRemotely <code>true</code> if connecting to ET system remotely only, else <code>false</code> */
+ public void setConnectRemotely(boolean connectRemotely) {this.connectRemotely = connectRemotely;}
+
+ /** If no ET system is available, set the number of milliseconds we wait while trying to open it.
+ * @param waitTime the number of milliseconds we wait while trying to open ET system */
+ public void setWaitTime(long waitTime) {
+ if (waitTime < 0) {
+ waitTime = 0;
+ }
+ this.waitTime = waitTime;
+ }
+
+
+
+ /**
+ * Adds a broadcast address to the set.
+ *
+ * @param addr broadcast address to be added
+ * @throws EtException if the address is not a broadcast address
+ */
+ public void addBroadcastAddr(String addr) throws EtException {
+ try {InetAddress.getByName(addr);}
+ catch (UnknownHostException ex) {
+ throw new EtException("not a broadcast address");
+ }
+
+ broadcastAddrs.add(addr);
+ }
+
+
+ /**
+ * Sets the collection of broadcast addresses.
+ *
+ * @param addrs collection of broadcast addresses (as Strings) or null
+ * @throws EtException if one of the addresses is not a broadcast address
+ */
+ public void setBroadcastAddrs(Collection<String> addrs) throws EtException {
+ if (addrs == null) {
+ broadcastAddrs = new HashSet<String>(10);
+ return;
+ }
+
+ for (String addr : addrs) {
+ try {InetAddress.getByName(addr);}
+ catch (UnknownHostException ex) {
+ throw new EtException("not a broadcast address");
+ }
+ }
+ broadcastAddrs = new HashSet<String>(addrs);
+ }
+
+
+ /**
+ * Adds a multicast address to the set.
+ *
+ * @param addr multicast address to be added
+ * @throws EtException if the address is not a multicast address
+ */
+ public void addMulticastAddr(String addr) throws EtException {
+ InetAddress inetAddr;
+ try {inetAddr = InetAddress.getByName(addr);}
+ catch (UnknownHostException ex) {
+ throw new EtException("not a multicast address");
+ }
+
+ if (!inetAddr.isMulticastAddress()) {
+ throw new EtException("not a multicast address");
+ }
+ multicastAddrs.add(addr);
+ }
+
+
+ /**
+ * Sets the collection of multicast addresses.
+ *
+ * @param addrs collection of multicast addresses (as Strings) or null
+ * @throws EtException if one of the addresses is not a multicast address
+ */
+ public void setMulticastAddrs(Collection<String> addrs) throws EtException {
+ if (addrs == null) {
+ multicastAddrs = new HashSet<String>(10);
+ return;
+ }
+
+ InetAddress inetAddr;
+ for (String addr : addrs) {
+ try {inetAddr = InetAddress.getByName(addr);}
+ catch (UnknownHostException ex) {
+ throw new EtException("not a broadcast address");
+ }
+ if (!inetAddr.isMulticastAddress()) {
+ throw new EtException(addr + " is not a multicast address");
+ }
+ }
+ multicastAddrs = new HashSet<String>(addrs);
+ }
+
+
+ /**
+ * Sets the means or method of contacting an ET system. Its values may be
+ * {@link EtConstants#broadcast} for broadcasting, {@link EtConstants#multicast}
+ * for multicasting, {@link EtConstants#direct} for connecting directly to the
+ * ET tcp server, and {@link EtConstants#broadAndMulticast} for using both
+ * broadcasting and multicasting.
+ *
+ * @param method means or method of contacting an ET system
+ * @throws EtException if the argument has a bad value
+ */
+ public void setNetworkContactMethod(int method) throws EtException {
+ if ((method != EtConstants.multicast) &&
+ (method != EtConstants.broadcast) &&
+ (method != EtConstants.broadAndMulticast) &&
+ (method != EtConstants.direct)) {
+ throw new EtException("bad contact method value");
+ }
+ networkContactMethod = method;
+ }
+
+
+ /**
+ * Sets the policy on what to do about multiple responding ET systems to a
+ * broadcast or multicast. The possible values are
+ * {@link EtConstants#policyFirst} which chooses the first ET system to
+ * respond, {@link EtConstants#policyLocal} which chooses the first local ET
+ * system to respond and if none then the first response, or
+ * {@link EtConstants#policyError} which throws an EtTooManyException
+ * exception.
+ *
+ * @param policy policy on what to do about multiple responding ET systems
+ * @throws EtException
+ * if the argument has a bad value or if the policy says to choose a local
+ * ET system but the host is set to chose a remote system.
+ */
+ public void setResponsePolicy(int policy) throws EtException {
+ if ((policy != EtConstants.policyFirst) &&
+ (policy != EtConstants.policyLocal) &&
+ (policy != EtConstants.policyError)) {
+ throw new EtException("bad policy value");
+ }
+
+ if ((host.equals(EtConstants.hostRemote)) &&
+ (policy == EtConstants.policyLocal)) {
+ // stupid combination of settings
+ throw new EtException("policy value cannot be local if host is remote");
+ }
+ responsePolicy = policy;
+ }
+
+
+ /**
+ * Sets the UDP port number for broadcasting and sending udp packets to known hosts.
+ *
+ * @param port UDP port number for broadcasting and sending udp packets to known hosts
+ * @throws EtException if the port number is < 1024 or > 65535
+ */
+ public void setUdpPort(int port) throws EtException {
+ if ((port < 1024) || (port > 65535)) {
+ throw new EtException("bad UDP port value");
+ }
+ udpPort = port;
+ }
+
+
+ /**
+ * Sets the TCP server port number of the ET system.
+ *
+ * @param port TCP server port number of the ET system
+ * @throws EtException if the port number is < 1024 or > 65535
+ */
+ public void setTcpPort(int port) throws EtException {
+ if ((port < 1024) || (port > 65535)) {
+ throw new EtException("bad TCP port value");
+ }
+ tcpPort = port;
+ }
+
+
+ /**
+ * Sets the port number to multicast to.
+ *
+ * @param port port number to multicast to
+ * @throws EtException if the port number is < 1024 or > 65535
+ */
+ public void setMulticastPort(int port) throws EtException {
+ if ((port < 1024) || (port > 65535)) {
+ throw new EtException("bad multicast port value");
+ }
+ multicastPort = port;
+ }
+
+
+ /**
+ * Sets the time-to-live value for multicasting.
+ *
+ * @param ttlNum time-to-live value for multicasting
+ * @throws EtException if the port number is < 0 or > 254
+ */
+ public void setTTL(int ttlNum) throws EtException {
+ if ((ttlNum < 0) || (ttlNum > 254)) {
+ throw new EtException("bad TTL value");
+ }
+ ttl = ttlNum;
+ }
+
+ /**
+ * Set the network interface (in dotted-decimal format) used for connecting to the ET system.
+ * @param networkInterface the network interface used for connecting to the ET system,
+ * or null if none specified.
+ * @throws EtException
+ * if the interface is not in dotted-decimal format or is an invalid IP address.
+ */
+ public void setNetworkInterface(String networkInterface) throws EtException {
+ if (networkInterface != null) {
+ try {InetAddress.getByName(networkInterface);}
+ catch (UnknownHostException ex) {
+ throw new EtException("not a valid network interface");
+ }
+ }
+ this.networkInterface = networkInterface;
+ }
+
+ /**
+ * Set the TCP send buffer size in bytes. A value of 0
+ * means use the operating system default.
+ *
+ * @param tcpSendBufSize TCP send buffer size in bytes
+ * @throws EtException
+ * if the argument is less than 0
+ */
+ public void setTcpSendBufSize(int tcpSendBufSize) throws EtException {
+ if (tcpSendBufSize < 0) {
+ throw new EtException("buffer size must be >= than 0");
+ }
+ this.tcpSendBufSize = tcpSendBufSize;
+ }
+
+ /**
+ * Set the TCP receive buffer size in bytes. A value of 0
+ * means use the operating system default.
+ *
+ * @param tcpRecvBufSize TCP receive buffer size in bytes
+ * @throws EtException
+ * if the argument is less than 0
+ */
+ public void setTcpRecvBufSize(int tcpRecvBufSize) throws EtException {
+ if (tcpRecvBufSize < 0) {
+ throw new EtException("buffer size must be >= than 0");
+ }
+ this.tcpRecvBufSize = tcpRecvBufSize;
+ }
+
+ /**
+ * Set the TCP no-delay setting. It is off by default.
+ * @param noDelay TCP no-delay setting
+ */
+ public void setNoDelay(boolean noDelay) {
+ this.noDelay = noDelay;
+ }
+
+
+}
hps-et-java/src/main/java/org/jlab/coda/et
diff -N EtUtils.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtUtils.java 13 Feb 2012 22:50:52 -0000 1.3
@@ -0,0 +1,291 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2010 Jefferson Science Associates, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et;
+
+import java.nio.ByteOrder;
+
+/**
+ * Collection of methods to help manipulate bytes in arrays.
+ * @author timmer
+ */
+public class EtUtils {
+
+ /**
+ * Turn short into byte array.
+ * Avoids creation of new byte array with each call.
+ *
+ * @param data short to convert
+ * @param byteOrder byte order of returned bytes (big endian if null)
+ * @param dest array in which to store returned bytes
+ * @param off offset into dest array where returned bytes are placed
+ * @throws org.jlab.coda.jevio.EvioException if dest is null or too small or offset negative
+ */
+ public static void shortToBytes(short data, ByteOrder byteOrder, byte[] dest, int off) {
+
+ if (byteOrder == null || byteOrder == ByteOrder.BIG_ENDIAN) {
+ dest[off ] = (byte)(data >>> 8);
+ dest[off+1] = (byte)(data );
+ }
+ else {
+ dest[off ] = (byte)(data );
+ dest[off+1] = (byte)(data >>> 8);
+ }
+ }
+
+
+ /**
+ * Turn int into byte array.
+ * Avoids creation of new byte array with each call.
+ *
+ * @param data int to convert
+ * @param byteOrder byte order of returned bytes (big endian if null)
+ * @param dest array in which to store returned bytes
+ * @param off offset into dest array where returned bytes are placed
+ */
+ public static void intToBytes(int data, ByteOrder byteOrder, byte[] dest, int off) {
+
+ if (byteOrder == null || byteOrder == ByteOrder.BIG_ENDIAN) {
+ dest[off ] = (byte)(data >> 24);
+ dest[off+1] = (byte)(data >> 16);
+ dest[off+2] = (byte)(data >> 8);
+ dest[off+3] = (byte)(data );
+ }
+ else {
+ dest[off ] = (byte)(data );
+ dest[off+1] = (byte)(data >> 8);
+ dest[off+2] = (byte)(data >> 16);
+ dest[off+3] = (byte)(data >> 24);
+ }
+ }
+
+ /**
+ * Turn long into byte array.
+ * Avoids creation of new byte array with each call.
+ *
+ * @param data long to convert
+ * @param byteOrder byte order of returned bytes (big endian if null)
+ * @param dest array in which to store returned bytes
+ * @param off offset into dest array where returned bytes are placed
+ */
+ public static void longToBytes(long data, ByteOrder byteOrder, byte[] dest, int off) {
+
+ if (byteOrder == null || byteOrder == ByteOrder.BIG_ENDIAN) {
+ dest[off ] = (byte)(data >> 56);
+ dest[off+1] = (byte)(data >> 48);
+ dest[off+2] = (byte)(data >> 40);
+ dest[off+3] = (byte)(data >> 32);
+ dest[off+4] = (byte)(data >> 24);
+ dest[off+5] = (byte)(data >> 16);
+ dest[off+6] = (byte)(data >> 8);
+ dest[off+7] = (byte)(data );
+ }
+ else {
+ dest[off ] = (byte)(data );
+ dest[off+1] = (byte)(data >> 8);
+ dest[off+2] = (byte)(data >> 16);
+ dest[off+3] = (byte)(data >> 24);
+ dest[off+4] = (byte)(data >> 32);
+ dest[off+5] = (byte)(data >> 40);
+ dest[off+6] = (byte)(data >> 48);
+ dest[off+7] = (byte)(data >> 56);
+ }
+ }
+
+ /**
+ * Copies a short value into 2 bytes of a byte array.
+ * @param shortVal short value
+ * @param b byte array
+ * @param off offset into the byte array
+ */
+ public static void shortToBytes(short shortVal, byte[] b, int off) {
+ shortToBytes(shortVal, null, b, off);
+ }
+
+ /**
+ * Copies an integer value into 4 bytes of a byte array.
+ * @param intVal integer value
+ * @param b byte array
+ * @param off offset into the byte array
+ */
+ public static void intToBytes(int intVal, byte[] b, int off) {
+ intToBytes(intVal, null, b, off);
+ }
+
+ /**
+ * Copies an long (64 bit) value into 8 bytes of a byte array.
+ * @param longVal long value
+ * @param b byte array
+ * @param off offset into the byte array
+ */
+ public static void longToBytes(long longVal, byte[] b, int off) {
+ longToBytes(longVal, null, b, off);
+ }
+
+
+ /**
+ * Turn section of byte array into a short.
+ *
+ * @param data byte array to convert
+ * @param byteOrder byte order of supplied bytes (big endian if null)
+ * @param off offset into data array
+ * @return short converted from byte array
+ */
+ public static short bytesToShort(byte[] data, ByteOrder byteOrder, int off) {
+
+ if (byteOrder == null || byteOrder == ByteOrder.BIG_ENDIAN) {
+ return (short)(
+ (0xff & data[ off]) << 8 |
+ (0xff & data[1+off])
+ );
+ }
+ else {
+ return (short)(
+ (0xff & data[ off]) |
+ (0xff & data[1+off] << 8)
+ );
+ }
+ }
+
+ /**
+ * Turn section of byte array into an int.
+ *
+ * @param data byte array to convert
+ * @param byteOrder byte order of supplied bytes (big endian if null)
+ * @param off offset into data array
+ * @return int converted from byte array
+ */
+ public static int bytesToInt(byte[] data, ByteOrder byteOrder, int off) {
+
+ if (byteOrder == null || byteOrder == ByteOrder.BIG_ENDIAN) {
+ return (
+ (0xff & data[ off]) << 24 |
+ (0xff & data[1+off]) << 16 |
+ (0xff & data[2+off]) << 8 |
+ (0xff & data[3+off])
+ );
+ }
+ else {
+ return (
+ (0xff & data[ off]) |
+ (0xff & data[1+off]) << 8 |
+ (0xff & data[2+off]) << 16 |
+ (0xff & data[3+off]) << 24
+ );
+ }
+ }
+
+ /**
+ * Turn section of byte array into a long.
+ *
+ * @param data byte array to convert
+ * @param byteOrder byte order of supplied bytes (big endian if null)
+ * @param off offset into data array
+ * @return long converted from byte array
+ */
+ public static long bytesToLong(byte[] data, ByteOrder byteOrder, int off) {
+
+ if (byteOrder == null || byteOrder == ByteOrder.BIG_ENDIAN) {
+ return (
+ // Convert to longs before shift because digits
+ // are lost with ints beyond the 32-bit limit
+ (long)(0xff & data[ off]) << 56 |
+ (long)(0xff & data[1+off]) << 48 |
+ (long)(0xff & data[2+off]) << 40 |
+ (long)(0xff & data[3+off]) << 32 |
+ (long)(0xff & data[4+off]) << 24 |
+ (long)(0xff & data[5+off]) << 16 |
+ (long)(0xff & data[6+off]) << 8 |
+ (long)(0xff & data[7+off])
+ );
+ }
+ else {
+ return (
+ (long)(0xff & data[ off]) |
+ (long)(0xff & data[1+off]) << 8 |
+ (long)(0xff & data[2+off]) << 16 |
+ (long)(0xff & data[3+off]) << 24 |
+ (long)(0xff & data[4+off]) << 32 |
+ (long)(0xff & data[5+off]) << 40 |
+ (long)(0xff & data[6+off]) << 48 |
+ (long)(0xff & data[7+off]) << 56
+ );
+ }
+ }
+
+ /**
+ * Converts 2 bytes of a byte array into a short.
+ * @param b byte array
+ * @param off offset into the byte array (0 = start at first element)
+ * @return short value
+ */
+ public static short bytesToShort(byte[] b, int off) {
+ return bytesToShort(b, null, off);
+ }
+
+ /**
+ * Converts 4 bytes of a byte array into an integer.
+ *
+ * @param b byte array
+ * @param off offset into the byte array (0 = start at first element)
+ * @return integer value
+ */
+ public static int bytesToInt(byte[] b, int off) {
+ return bytesToInt(b, null, off);
+ }
+
+ /**
+ * Converts 8 bytes of a byte array into a long.
+ * @param b byte array
+ * @param off offset into the byte array (0 = start at first element)
+ * @return long value
+ */
+ public static long bytesToLong(byte[] b, int off) {
+ return bytesToLong(b, null, off);
+ }
+
+ /**
+ * Swaps 4 bytes of a byte array in place.
+ * @param b byte array
+ * @param off offset into the byte array
+ */
+ public static void swapArrayInt(byte[] b, int off) {
+ byte b1, b2, b3, b4;
+ b1 = b[off];
+ b2 = b[off+1];
+ b3 = b[off+2];
+ b4 = b[off+3];
+ b[off+3] = b1;
+ b[off+2] = b2;
+ b[off+1] = b3;
+ b[off] = b4;
+ }
+
+ /**
+ * Swaps 2 bytes of a byte array in place.
+ * @param b byte array
+ * @param off offset into the byte array
+ */
+ public static void swapArrayShort(byte[] b, int off) {
+ byte b1, b2;
+ b1 = b[off];
+ b2 = b[off+1];
+ b[off+1] = b1;
+ b[off] = b2;
+ }
+
+
+
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/apps
diff -N Blaster.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Blaster.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,280 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.apps;
+
+
+import org.jlab.coda.et.*;
+import org.jlab.coda.et.enums.Mode;
+
+import java.awt.image.DataBuffer;
+import java.lang.Exception;
+import java.lang.NumberFormatException;
+import java.lang.String;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * This class is an example of an event producer designed to blast data
+ * at the highest possible rate to the ET system.
+ *
+ * @author Carl Timmer
+ */
+public class Blaster {
+
+ public Blaster() {
+ }
+
+
+ private static void usage() {
+ System.out.println("\nUsage: java Blaster -f <ET name> -host <ET host> [-h] [-v] [-c <chunk size>]\n" +
+ " [-s <event size>] [-g <group>] [-p <ET server port>] [-i <interface address>]\n" +
+ " [-rb <buffer size>] [-sb <buffer size>] [-nd]\n\n" +
+ " -host ET system's host\n" +
+ " -f ET system's (memory-mapped file) name\n" +
+ " -h help\n" +
+ " -v verbose output\n" +
+ " -c number of events in one get/put array\n" +
+ " -s event size in bytes\n" +
+ " -g group from which to get new events (1,2,...)\n" +
+ " -p ET server port\n" +
+ " -i outgoing network interface IP address (dot-decimal)\n\n" +
+ " -rb TCP receive buffer size (bytes)\n" +
+ " -sb TCP send buffer size (bytes)\n" +
+ " -nd turn on TCP no-delay\n" +
+ " This consumer works by making a direct connection to the\n" +
+ " ET system's server port.\n");
+ }
+
+
+ public static void main(String[] args) {
+
+ String etName = null, host = null, netInterface = null;
+ int port = EtConstants.serverPort;
+ int group = 1;
+ int size = 32;
+ int chunk = 1;
+ int recvBufSize = 0;
+ int sendBufSize = 0;
+ boolean noDelay = false;
+ boolean verbose = false;
+
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].equalsIgnoreCase("-f")) {
+ etName = args[++i];
+ }
+ else if (args[i].equalsIgnoreCase("-i")) {
+ netInterface = args[++i];
+ }
+ else if (args[i].equalsIgnoreCase("-host")) {
+ host = args[++i];
+ }
+ else if (args[i].equalsIgnoreCase("-p")) {
+ try {
+ port = Integer.parseInt(args[++i]);
+ if ((port < 1024) || (port > 65535)) {
+ System.out.println("Port number must be between 1024 and 65535.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper port number.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-c")) {
+ try {
+ chunk = Integer.parseInt(args[++i]);
+ if ((chunk < 1) || (chunk > 1000)) {
+ System.out.println("Chunk size may be 1 - 1000.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper chunk size.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-s")) {
+ try {
+ size = Integer.parseInt(args[++i]);
+ if (size < 1) {
+ System.out.println("Size needs to be positive int.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper size.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-g")) {
+ try {
+ group = Integer.parseInt(args[++i]);
+ if ((group < 1) || (group > 10)) {
+ System.out.println("Group number must be between 0 and 10.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper group number.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-rb")) {
+ try {
+ recvBufSize = Integer.parseInt(args[++i]);
+ if (recvBufSize < 1) {
+ System.out.println("recv buffer must be > 0.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper recv buffer size.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-sb")) {
+ try {
+ sendBufSize = Integer.parseInt(args[++i]);
+ if (sendBufSize < 1) {
+ System.out.println("send buffer must be > 0.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper send buffer size.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-nd")) {
+ noDelay = true;
+ }
+ else if (args[i].equalsIgnoreCase("-v")) {
+ verbose = true;
+ }
+ else {
+ usage();
+ return;
+ }
+ }
+
+ if (host == null || etName == null) {
+ usage();
+ return;
+ }
+
+ try {
+ // Make a direct connection to ET system's tcp server
+ EtSystemOpenConfig config = new EtSystemOpenConfig(etName, host, port);
+ config.setConnectRemotely(true);
+
+ if (noDelay) config.setNoDelay(noDelay);
+ if (recvBufSize > 0) config.setTcpRecvBufSize(recvBufSize);
+ if (sendBufSize > 0) config.setTcpSendBufSize(sendBufSize);
+ if (netInterface != null) config.setNetworkInterface(netInterface);
+
+ // create ET system object with verbose debugging output
+ EtSystem sys = new EtSystem(config);
+ if (verbose) sys.setDebug(EtConstants.debugInfo);
+ sys.open();
+
+ // get GRAND_CENTRAL station object
+ EtStation gc = sys.stationNameToObject("GRAND_CENTRAL");
+
+ // attach to GRAND_CENTRAL
+ EtAttachment att = sys.attach(gc);
+
+ // array of events
+ EtEvent[] mevs;
+ EtEventImpl realEvent;
+
+ // data to put in new events
+ byte[] data = new byte[size];
+ ByteBuffer byteBuffer = ByteBuffer.wrap(data);
+
+ long eventCount=0L, byteCount=0L;
+ long t1, t2, time, totalT=0L, totalEventCount=0L, totalByteCount=0L;
+ double eventRate, avgEventRate, byteRate, avgByteRate;
+
+
+ // keep track of time for event rate calculations
+ t1 = System.currentTimeMillis();
+
+ while (true) {
+ // get array of new events without allocating memory for data
+ mevs = sys.newEvents(att, Mode.SLEEP, true, 0, chunk, size, group);
+
+ // example of how to manipulate events
+ for (EtEvent mev : mevs) {
+ // A little bit of trickery to set the data buffer
+ // without having to create objects and allocate
+ // memory each time.
+ realEvent = (EtEventImpl) mev;
+ realEvent.setDataBuffer(byteBuffer);
+
+ // set data length
+ mev.setLength(size);
+ }
+
+ // put events back into ET system
+ sys.putEvents(att, mevs);
+ eventCount += mevs.length;
+ byteCount += mevs.length*(size + 52) + 20; // 52 is event overhead, 20 is ET call overhead
+
+ // calculate the event rate
+ t2 = System.currentTimeMillis();
+ time = t2 - t1;
+
+ if (time > 5000) {
+ eventRate = 1000.0 * eventCount / time;
+ byteRate = 1000.0 * byteCount / time;
+
+ totalEventCount += eventCount;
+ totalByteCount += byteCount;
+
+ totalT += time;
+
+ avgEventRate = 1000.0 * totalEventCount / totalT;
+ avgByteRate = 1000.0 * totalByteCount / totalT;
+
+ System.out.printf("evRate: %3.4g Hz, %3.4g avg; byteRate: %3.4g bytes/sec, %3.4g avg\n",
+ eventRate, avgEventRate, byteRate, avgByteRate);
+
+ eventCount = 0;
+ byteCount = 0;
+
+ t1 = System.currentTimeMillis();
+ }
+ }
+ }
+ catch (Exception ex) {
+ System.out.println("Error using ET system as producer");
+ ex.printStackTrace();
+ }
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/apps
diff -N Consumer.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Consumer.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,267 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.apps;
+
+import java.lang.*;
+import java.nio.ByteBuffer;
+
+import org.jlab.coda.et.*;
+import org.jlab.coda.et.enums.Mode;
+
+
+/**
+ * This class is an example of an event consumer for an ET system.
+ *
+ * @author Carl Timmer
+ */
+public class Consumer {
+
+ public Consumer() {
+ }
+
+
+ private static void usage() {
+ System.out.println("\nUsage: java Consumer -f <et name> -host <ET host> -s <station name> [-h] [-v] [-nb]\n" +
+ " [-p <ET server port>] [-c <chunk size>] [-q <queue size>]\n" +
+ " [-pos <station position>] [-ppos <parallel station position>]\n\n" +
+ " -host ET system's host\n" +
+ " -f ET system's (memory-mapped file) name\n" +
+ " -s create station of this name\n" +
+ " -h help\n" +
+ " -v verbose output\n" +
+ " -nb make station non-blocking\n" +
+ " -p ET server port\n" +
+ " -c number of events in one get/put array\n" +
+ " -q queue size if creating nonblocking station\n" +
+ " -pos position of created station in station list (1,2,...)\n" +
+ " -ppos position of created station within a group of parallel stations (-1=end, -2=head)\n\n" +
+ " This consumer works by making a direct connection\n" +
+ " to the ET system's tcp server port.\n");
+ }
+
+
+ public static void main(String[] args) {
+
+ int position = 1, pposition = 0, qSize = 0, chunk = 1;
+ boolean blocking = true, verbose = false;
+ String etName = null, host = null, statName = null;
+ int port = EtConstants.serverPort;
+ int flowMode = EtConstants.stationSerial;
+
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].equalsIgnoreCase("-f")) {
+ etName = args[++i];
+ }
+ else if (args[i].equalsIgnoreCase("-host")) {
+ host = args[++i];
+ }
+ else if (args[i].equalsIgnoreCase("-nb")) {
+ blocking = false;
+ }
+ else if (args[i].equalsIgnoreCase("-v")) {
+ verbose = true;
+ }
+ else if (args[i].equalsIgnoreCase("-s")) {
+ statName = args[++i];
+ }
+ else if (args[i].equalsIgnoreCase("-p")) {
+ try {
+ port = Integer.parseInt(args[++i]);
+ if ((port < 1024) || (port > 65535)) {
+ System.out.println("Port number must be between 1024 and 65535.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper port number.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-c")) {
+ try {
+ chunk = Integer.parseInt(args[++i]);
+ if ((chunk < 1) || (chunk > 1000)) {
+ System.out.println("Chunk size may be 1 - 1000.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper chunk size.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-q")) {
+ try {
+ qSize = Integer.parseInt(args[++i]);
+ if (qSize < 1) {
+ System.out.println("Queue size must be > 0.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper queue size number.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-pos")) {
+ try {
+ position = Integer.parseInt(args[++i]);
+ if (position < 1) {
+ System.out.println("Position must be > 0.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper position number.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-ppos")) {
+ try {
+ pposition = Integer.parseInt(args[++i]);
+ if (pposition < -2 || pposition == 0) {
+ System.out.println("Parallel position must be > -3 and != 0.");
+ usage();
+ return;
+ }
+ System.out.println("FLOW moDE is ||");
+ flowMode = EtConstants.stationParallel;
+ if (pposition == -2) pposition = EtConstants.newHead;
+ else if (pposition == -1) pposition = EtConstants.end;
+
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper parallel position number.");
+ usage();
+ return;
+ }
+ }
+ else {
+ usage();
+ return;
+ }
+ }
+
+ if (host == null || etName == null || statName == null) {
+ usage();
+ return;
+ }
+
+ try {
+ // make a direct connection to ET system's tcp server
+ EtSystemOpenConfig config = new EtSystemOpenConfig(etName, host, port);
+
+ // create ET system object with verbose debugging output
+ EtSystem sys = new EtSystem(config, EtConstants.debugInfo);
+ sys.open();
+
+ // configuration of a new station
+ EtStationConfig statConfig = new EtStationConfig();
+ statConfig.setFlowMode(flowMode);
+ if (!blocking) {
+ statConfig.setBlockMode(EtConstants.stationNonBlocking);
+ if (qSize > 0) {
+ statConfig.setCue(qSize);
+ }
+ }
+
+ // create station
+ EtStation stat = sys.createStation(statConfig, statName, position, pposition);
+
+ // attach to new station
+ EtAttachment att = sys.attach(stat);
+
+ // array of events
+ EtEvent[] mevs;
+
+ int num, count = 0;
+ long t1=0, t2=0, time, totalT=0, totalCount=0;
+ double rate, avgRate;
+
+ // keep track of time
+ t1 = System.currentTimeMillis();
+
+ while (true) {
+
+ // get events from ET system
+ mevs = sys.getEvents(att, Mode.SLEEP, null, 0, chunk);
+
+ // example of reading & printing event data
+ if (verbose) {
+ for (EtEvent mev : mevs) {
+ // Get event's data buffer
+ // buf.limit() = length of the actual data (not buffer capacity)
+ ByteBuffer buf = mev.getDataBuffer();
+
+ num = buf.getInt(0);
+ System.out.println("data byte order = " + mev.getByteOrder());
+ if (mev.needToSwap()) {
+ System.out.println(" data needs swapping, swapped int = " + Integer.reverseBytes(num));
+ }
+ else {
+ System.out.println(" data does NOT need swapping, int = " + num);
+ }
+
+ System.out.print("control array = {");
+ int[] con = mev.getControl();
+ for (int j : con) {
+ System.out.print(j + " ");
+ }
+ System.out.println("}");
+ }
+ }
+
+ // put events back into ET system
+ sys.putEvents(att, mevs);
+ count += mevs.length;
+
+ // calculate the event rate
+ t2 = System.currentTimeMillis();
+ time = t2 - t1;
+
+ if (time > 5000) {
+ // reset things if necessary
+ if ( (totalCount >= (Long.MAX_VALUE - count)) ||
+ (totalT >= (Long.MAX_VALUE - time)) ) {
+ totalT = totalCount = count = 0;
+ t1 = System.currentTimeMillis();
+ continue;
+ }
+ rate = 1000.0 * ((double) count) / time;
+ totalCount += count;
+ totalT += time;
+ avgRate = 1000.0 * ((double) totalCount) / totalT;
+ System.out.println("rate = " + String.format("%.3g", rate) +
+ " Hz, avg = " + String.format("%.3g", avgRate));
+ count = 0;
+ t1 = System.currentTimeMillis();
+ }
+ }
+ }
+ catch (Exception ex) {
+ System.out.println("Error using ET system as consumer");
+ ex.printStackTrace();
+ }
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/apps
diff -N EtMonitor.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtMonitor.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,548 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.apps;
+
+import java.lang.*;
+import java.io.*;
+import java.net.*;
+
+import org.jlab.coda.et.data.*;
+import org.jlab.coda.et.exception.*;
+import org.jlab.coda.et.EtConstants;
+import org.jlab.coda.et.EtSystemOpenConfig;
+import org.jlab.coda.et.EtSystem;
+
+/**
+ * This class implements a monitor of an ET system. It opens the system,
+ * receives all relevant data over a tcp connection, and prints it out.
+ *
+ * @author Carl Timmer
+ */
+
+public class EtMonitor {
+
+ static int period = 3; // seconds
+ static long prevGcOut;
+
+ public EtMonitor() {
+ }
+
+
+ private static void usage() {
+ System.out.println("\nUsage: java EtMonitor -f <et name> [-p <period>] [-port <server port>] [-h <host>]\n\n" +
+ " -f ET system's name\n" +
+ " -p period in seconds between data updates\n" +
+ " -port port number for a direct connection\n" +
+ " -h host the ET system resides on (defaults to local)\n" +
+ " This monitor works by making a direct connection to the\n" +
+ " ET system's tcp server port.\n");
+ }
+
+
+ public static void main(String[] args) {
+ String etName = null, host = null;
+ int port = EtConstants.serverPort;
+
+ try {
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].equalsIgnoreCase("-f")) {
+ etName = args[++i];
+ }
+ else if (args[i].equalsIgnoreCase("-h")) {
+ host = args[++i];
+ }
+ else if (args[i].equalsIgnoreCase("-port")) {
+ try {
+ port = Integer.parseInt(args[++i]);
+ if ((port < 1024) || (port > 65535)) {
+ System.out.println("Port number must be between 1024 and 65535.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper port number.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-p")) {
+ try {
+ period = Integer.parseInt(args[++i]);
+ if (period < 1) {
+ System.out.println("Period must be at least 1 second.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper period value.");
+ usage();
+ return;
+ }
+ }
+ else {
+ usage();
+ return;
+ }
+ }
+
+ if (host == null) {
+ try {
+ host = InetAddress.getLocalHost().getHostName();
+ }
+ catch (UnknownHostException ex) {
+ System.out.println("Host not specified and cannot find local host name.");
+ usage();
+ return;
+ }
+ }
+
+ if (etName == null) {
+ usage();
+ return;
+ }
+
+ // make a direct connection to ET system's tcp server
+ EtSystemOpenConfig config = new EtSystemOpenConfig(etName, host, port);
+
+ // create ET system object with debugging output
+ EtSystem sys = new EtSystem(config, EtConstants.debugError);
+ AllData etData = new AllData();
+
+/*
+ // timing
+ long t1, t2;
+ for (int j=0; j < 10; j++) {
+ t1 = System.currentTimeMillis();
+ for(int i=0; i < 2000; i++) {
+ etData = sys.getData();
+ }
+ t2 = System.currentTimeMillis();
+ double rate = 1000.0*2000.0/((double)(t2-t1));
+ System.out.println("rate = " + rate + " Hz");
+ }
+*/
+
+ while (true) {
+ try {
+ etData = sys.getData();
+ display(sys, etData);
+ }
+ catch (EtException ex) {
+ System.out.print("\n*****************************************\n");
+ System.out.print("* Error getting data from ET system *");
+ System.out.print("\n*****************************************\n");
+ }
+ Thread.sleep(period * 1000);
+ }
+
+
+ }
+ catch (IOException ex) {
+ System.out.println("Communication error with ET system:");
+ ex.printStackTrace();
+ }
+ catch (Exception ex) {
+ System.out.println("ERROR:");
+ ex.printStackTrace();
+ }
+
+ }
+
+
+ private static void display(EtSystem sys, AllData data)
+ {
+ int end = 499, lang;
+ boolean blocking;
+ double rate = 0.0;
+ StringBuffer str = new StringBuffer(end+1);
+
+ str.append(" ET SYSTEM - (");
+ str.append(data.sysData.getEtName());
+ str.append(") (host ");
+ str.append(sys.getHost());
+ str.append(") (bits ");
+ if (data.sysData.isBit64()) {
+ str.append("64)\n");
+ }
+ else {
+ str.append("32)\n");
+ }
+ str.append(" (tcp port ");
+ str.append(data.sysData.getTcpPort());
+ str.append(") (udp port ");
+ str.append(data.sysData.getUdpPort());
+ str.append(") (multicast port ");
+ str.append(data.sysData.getMulticastPort());
+ str.append(")\n (pid ");
+ str.append(data.sysData.getMainPid());
+ str.append(") (lang ");
+ lang = sys.getLanguage();
+ if (lang == EtConstants.langJava) {
+ str.append("Java) (period ");
+ }
+ else if (lang == EtConstants.langC) {
+ str.append("C) (period ");
+ }
+ else if (lang == EtConstants.langCpp) {
+ str.append("C++) (period ");
+ }
+ else {
+ str.append("unknown) (period ");
+ }
+ str.append(period);
+ str.append(" sec)\n");
+ System.out.println(str.toString());
+ str.delete(0, end);
+
+ str.append(" STATIC INFO - maximum of:\n");
+ str.append(" events(");
+ str.append(data.sysData.getEvents());
+ str.append("), event size(");
+ str.append(data.sysData.getEventSize());
+ str.append("), temps(");
+ str.append(data.sysData.getTempsMax());
+ str.append(")\n");
+ str.append(" stations(");
+ str.append(data.sysData.getStationsMax());
+ str.append("), attaches(");
+ str.append(data.sysData.getAttachmentsMax());
+ str.append("), procs(");
+ str.append(data.sysData.getProcessesMax());
+ str.append(")\n");
+
+ if (data.sysData.getInterfaces() > 0) {
+ String[] ifAddrs = data.sysData.getInterfaceAddresses();
+ str.append(" network interfaces(");
+ str.append(ifAddrs.length);
+ str.append(") ");
+ for (int i=0; i < ifAddrs.length; i++) {
+ str.append(ifAddrs[i]);
+ str.append(", ");
+ }
+ str.append("\n");
+ }
+ else {
+ str.append(" network interfaces(0): none\n");
+ }
+
+ if (data.sysData.getMulticasts() > 0) {
+ String[] mAddrs = data.sysData.getMulticastAddresses();
+ str.append(" multicast addresses(");
+ str.append(mAddrs.length);
+ str.append(") ");
+ for (int i=0; i < mAddrs.length; i++) {
+ str.append(mAddrs[i]);
+ str.append(", ");
+ }
+ str.append("\n");
+ }
+
+ str.append("\n DYNAMIC INFO - currently there are:\n");
+ str.append(" processes(");
+ str.append(data.sysData.getProcesses());
+ str.append("), attachments(");
+ str.append(data.sysData.getAttachments());
+ str.append("), temps(");
+ str.append(data.sysData.getTemps());
+ str.append(")\n stations(");
+ str.append(data.sysData.getStations());
+ str.append("), hearbeat(");
+ str.append(data.sysData.getHeartbeat());
+ str.append(")\n");
+ System.out.println(str.toString());
+ str.delete(0, end);
+
+ str.append(" STATIONS:\n");
+
+ for (int i=0; i < data.statData.length; i++) {
+ str.append(" \"");
+ str.append(data.statData[i].getName());
+ str.append("\" (id = ");
+ str.append(data.statData[i].getId());
+ str.append(")\n static info\n");
+
+ if (data.statData[i].getStatus() == EtConstants.stationIdle)
+ str.append(" status(IDLE), ");
+ else
+ str.append(" status(ACTIVE), ");
+
+ if (data.statData[i].getFlowMode() == EtConstants.stationSerial) {
+ str.append("flow(SERIAL), ");
+ }
+ else {
+ str.append("flow(PARALLEL), ");
+ }
+
+ if (data.statData[i].getBlockMode() == EtConstants.stationBlocking) {
+ str.append("blocking(YES), ");
+ blocking = true;
+ }
+ else {
+ str.append("blocking(NO), ");
+ blocking = false;
+ }
+
+ if (data.statData[i].getUserMode() == EtConstants.stationUserMulti) {
+ str.append("user(MULTI), ");
+ }
+ else {
+ str.append("user(");
+ str.append(data.statData[i].getUserMode());
+ str.append("), ");
+ }
+
+ if (data.statData[i].getSelectMode() == EtConstants.stationSelectAll)
+ str.append("select(ALL)\n");
+ else if (data.statData[i].getSelectMode() == EtConstants.stationSelectMatch)
+ str.append("select(MATCH)\n");
+ else if (data.statData[i].getSelectMode() == EtConstants.stationSelectUser)
+ str.append("select(USER)\n");
+ else if (data.statData[i].getSelectMode() == EtConstants.stationSelectRRobin)
+ str.append("select(RROBIN)\n");
+ else
+ str.append("select(EQUALCUE)\n");
+
+ if (data.statData[i].getRestoreMode() == EtConstants.stationRestoreOut)
+ str.append(" restore(OUT), ");
+ else if (data.statData[i].getRestoreMode() == EtConstants.stationRestoreIn)
+ str.append(" restore(IN), ");
+ else
+ str.append(" restore(GC), ");
+
+ str.append("prescale(");
+ str.append(data.statData[i].getPrescale());
+ str.append("), cue(");
+ str.append(data.statData[i].getCue());
+ str.append("), ");
+
+ str.append("select words(");
+ int[] select = data.statData[i].getSelect();
+ for (int j=0; j < select.length; j++) {
+ str.append(select[j]);
+ str.append(", ");
+ }
+ str.append(")");
+
+ if (data.statData[i].getSelectMode() == EtConstants.stationSelectUser) {
+ str.append("\n lib = ");
+ str.append(data.statData[i].getSelectLibrary());
+ str.append(", function = ");
+ str.append(data.statData[i].getSelectFunction());
+ str.append(", class = ");
+ str.append(data.statData[i].getSelectClass());
+ str.append("");
+ }
+
+ System.out.println(str.toString());
+ str.delete(0, end);
+
+ // dynamic station info or info on active stations
+ if (data.statData[i].getStatus() != EtConstants.stationActive) {
+ System.out.println();
+ continue;
+ }
+
+ str.append(" dynamic info\n");
+ str.append(" attachments: total#(");
+ str.append(data.statData[i].getAttachments());
+ str.append("), ids(");
+
+ int[] attIds = data.statData[i].getAttachmentIds();
+ for (int j=0; j < attIds.length; j++) {
+ str.append(attIds[j]);
+ str.append(", ");
+ }
+ str.append(")\n");
+
+ str.append(" input list: cnt = ");
+ str.append(data.statData[i].getInListCount());
+ str.append(", events in = ");
+ str.append(data.statData[i].getInListIn());
+
+ // if blocking station and not grandcentral ...
+ if (blocking && (data.statData[i].getId() != 0)) {
+ str.append(", events try = ");
+ str.append(data.statData[i].getInListTry());
+ }
+ str.append("\n");
+
+ str.append(" output list: cnt = ");
+ str.append(data.statData[i].getOutListCount());
+ str.append(", events out = ");
+ str.append(data.statData[i].getOutListOut());
+ str.append("\n");
+
+ System.out.println(str.toString());
+ str.delete(0, end);
+
+ // keep track of grandcentral data rate
+ if (i==0) {
+ rate = (data.statData[i].getOutListOut() - prevGcOut)/period;
+ prevGcOut = data.statData[i].getOutListOut();
+ }
+ } // for (int i=0; i < data.statData.length; i++) {
+
+
+ // user processes
+ if (data.procData.length > 0) {
+ str.append(" LOCAL USERS:\n");
+ for (int i=0; i < data.procData.length; i++) {
+ if (data.procData[i].getAttachments() < 1) {
+ str.append(" process id# ");
+ str.append(data.procData[i].getId());
+ str.append(", # attachments(0), ");
+ }
+ else {
+ str.append(" process id# ");
+ str.append(data.procData[i].getId());
+ str.append(", # attachments(");
+ str.append(data.procData[i].getAttachments());
+ str.append("), attach ids(");
+ int[] atIds = data.procData[i].getAttachmentIds();
+ for (int j=0; j < atIds.length; j++) {
+ str.append(atIds[j]);
+ str.append(", ");
+ }
+ str.append("), ");
+ }
+ str.append("pid(");
+ str.append(data.procData[i].getPid());
+ str.append("), hbeat(");
+ str.append(data.procData[i].getHeartbeat());
+ str.append(")\n");
+ }
+ System.out.println(str.toString());
+ str.delete(0, end);
+ }
+
+
+ // user attachments
+ if (data.attData.length > 0) {
+ str.append(" ATTACHMENTS: len = ");
+ str.append(data.attData.length);
+ str.append("\n");
+ for (int i=0; i < data.attData.length; i++) {
+ str.append(" att #");
+ str.append(data.attData[i].getId());
+ str.append(", is at station(");
+ str.append(data.attData[i].getStationName());
+ str.append(") on host(");
+ str.append(data.attData[i].getHost());
+ str.append(") at pid(");
+ str.append(data.attData[i].getPid());
+ str.append(")\n");
+ str.append(" proc(");
+ str.append(data.attData[i].getProc());
+ str.append("), ");
+ if (data.attData[i].blocked()) {
+ str.append("blocked(YES)");
+ }
+ else {
+ str.append("blocked(NO)");
+ }
+ if (data.attData[i].quitting()) {
+ str.append(", told to quit");
+ }
+ str.append("\n events: make(");
+ str.append(data.attData[i].getEventsMake());
+ str.append("), get(");
+ str.append(data.attData[i].getEventsGet());
+ str.append("), put(");
+ str.append(data.attData[i].getEventsPut());
+ str.append("), dump(");
+ str.append(data.attData[i].getEventsDump());
+ str.append(")");
+ System.out.println(str.toString());
+ str.delete(0, end);
+ }
+ }
+
+ str.append("\n EVENTS OWNED BY:\n");
+ str.append(" system (");
+ str.append(data.sysData.getEventsOwned());
+ str.append("),");
+ for (int i=0; i < data.attData.length; i++) {
+ str.append(" att");
+ str.append(data.attData[i].getId());
+ str.append(" (");
+ str.append(data.attData[i].getEventsOwned());
+ str.append("),");
+ if ((i+1)%6 == 0)
+ str.append("\n ");
+ }
+ str.append("\n\n");
+
+ // Event rate
+ str.append(" EVENT RATE of GC = ");
+ str.append(rate);
+ str.append(" events/sec\n\n");
+
+ // idle stations
+ str.append(" IDLE STATIONS: ");
+ for (int i=0; i < data.statData.length; i++) {
+ if (data.statData[i].getStatus() == EtConstants.stationIdle) {
+ str.append(data.statData[i].getName());
+ str.append(", ");
+ }
+ }
+ str.append("\n");
+
+ // stations linked list
+ str.append(" STATION CHAIN: ");
+ for (int i=0; i < data.statData.length; i++) {
+ str.append(data.statData[i].getName());
+ str.append(", ");
+ }
+ str.append("\n");
+
+
+ if (lang != EtConstants.langJava) {
+ // mutexes
+ str.append(" LOCKED MUTEXES: ");
+ if (data.sysData.getMutex() == EtConstants.mutexLocked)
+ str.append("system, ");
+ if (data.sysData.getStatMutex() == EtConstants.mutexLocked)
+ str.append("station, ");
+ if (data.sysData.getStatAddMutex() == EtConstants.mutexLocked)
+ str.append("add_station, ");
+
+ for (int i=0; i < data.statData.length; i++) {
+ if (data.statData[i].getMutex() == EtConstants.mutexLocked) {
+ str.append(data.statData[i].getName());
+ }
+ if (data.statData[i].getInListMutex() == EtConstants.mutexLocked) {
+ str.append(data.statData[i].getName());
+ str.append("-in, ");
+ }
+ if (data.statData[i].getOutListMutex() == EtConstants.mutexLocked) {
+ str.append(data.statData[i].getName());
+ str.append("-out, ");
+ }
+ }
+ str.append("\n");
+ }
+
+ str.append("\n*****************************************\n");
+ System.out.println(str.toString());
+ str.delete(0, end);
+
+ }
+
+
+
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/apps
diff -N EvioProducer.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EvioProducer.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,314 @@
+package org.jlab.coda.et.apps;
+
+import org.jlab.coda.et.*;
+import org.jlab.coda.et.enums.Mode;
+import org.jlab.coda.jevio.*;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: timmer
+ * Date: May 28, 2010
+ * Time: 4:01:01 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class EvioProducer {
+
+
+ public EvioProducer() {
+ }
+
+
+ private static void usage() {
+ System.out.println("\nUsage: java Producer -f <et name> [-p <server port>] [-host <host>]" +
+ " [-d <delay in millisec>] [-g <group #>]\n\n" +
+ " -f ET system's name\n" +
+ " -s size in bytes for requested events\n" +
+ " -p port number for a udp broadcast\n" +
+ " -d delay in millisec between getting and putting events\n" +
+ " -g group number of new events to get\n" +
+ " -host host the ET system resides on (defaults to anywhere)\n\n" +
+ " This consumer works by making a connection to the\n" +
+ " ET system's tcp server port.\n");
+ }
+
+ /** Setting this to false will make the buffer be recreated from scratch for each event. */
+ static boolean fastMode = true;
+
+ /** Buffer to use for generated evio data. */
+ static ByteBuffer buffie;
+
+ /**
+ * Create an evio bank for sending.
+ */
+ public static ByteBuffer evioBytes() throws EvioException {
+
+ if (fastMode && buffie != null) {
+ buffie.flip();
+ return buffie;
+ }
+
+ // count the events we make for testing
+ int eventNumber = 1;
+
+ // use a tag of 11 for events--for no particular reason
+ int tag = 11;
+
+ // second event, more traditional bank of banks
+ EventBuilder eventBuilder = new EventBuilder(tag, DataType.BANK, eventNumber++);
+ EvioEvent event2 = eventBuilder.getEvent();
+
+ // add a bank of doubles
+ EvioBank bank1 = new EvioBank(22, DataType.DOUBLE64, 0);
+ eventBuilder.appendDoubleData(bank1, new double[] {1.1,2.2,-3.3, 1.12345678912345678912, -1.2e-99, -2.2e-11, -6.7e-10});
+ eventBuilder.addChild(event2, bank1);
+
+ // add a bank of floats
+ EvioBank bank4 = new EvioBank(22, DataType.FLOAT32, 0);
+ eventBuilder.appendFloatData(bank4, new float[] {1.1F,2.2F,-3.3F, 1.12345678912345678912F, -1.2e+38F, -2.2e-38F, -6.7e-29F});
+ eventBuilder.addChild(event2, bank4);
+
+ // add a bank of longs
+ EvioBank bank5 = new EvioBank(22, DataType.LONG64, 0);
+ eventBuilder.appendLongData(bank5, new long[] {1L,2L,3L, 1000000000000000000L, -1000000000000000000L, -2L, -3L});
+ eventBuilder.addChild(event2, bank5);
+
+ // add a bank of ints
+ EvioBank bank6 = new EvioBank(22, DataType.INT32, 0);
+ eventBuilder.appendIntData(bank6, new int[] {1,2,3, 1000000000, -1000000000, -2, -3});
+ eventBuilder.addChild(event2, bank6);
+
+ // add a bank of bytes
+ EvioBank bank7 = new EvioBank(22, DataType.CHAR8, 0);
+ eventBuilder.appendByteData(bank7, new byte[] {1,2,3});
+ eventBuilder.addChild(event2, bank7);
+
+ // lets modify event2
+ event2.getHeader().setNumber(eventNumber++);
+ EvioBank bank2 = new EvioBank(33, DataType.BANK, 0);
+ eventBuilder.addChild(event2, bank2);
+
+ EvioBank subBank1 = new EvioBank(34, DataType.INT32, 1);
+ eventBuilder.addChild(bank2, subBank1);
+ eventBuilder.appendIntData(subBank1, new int[] {4,5,6});
+
+ // now add a bank of segments
+ EvioBank subBank2 = new EvioBank(33, DataType.SEGMENT, 0);
+ eventBuilder.addChild(bank2, subBank2);
+
+ EvioSegment segment1 = new EvioSegment(34, DataType.SHORT16);
+ eventBuilder.addChild(subBank2, segment1);
+ eventBuilder.appendShortData(segment1, new short[] {7,8,9,10, 10000, 20000});
+
+ // now add a bank of tag segments
+ EvioBank subBank3 = new EvioBank(45, DataType.TAGSEGMENT, 0);
+ eventBuilder.addChild(bank2, subBank3);
+
+ // now add a tag segment of tag segments
+ EvioTagSegment tagsegment2 = new EvioTagSegment(35, DataType.TAGSEGMENT);
+ eventBuilder.addChild(subBank3, tagsegment2);
+
+ EvioTagSegment tagsegment3 = new EvioTagSegment(36, DataType.CHARSTAR8);
+ eventBuilder.addChild(tagsegment2, tagsegment3);
+ eventBuilder.appendStringData(tagsegment3, "This is a string");
+
+ event2.setAllHeaderLengths();
+
+
+ // write the event
+ buffie = ByteBuffer.allocate(event2.getTotalBytes());
+ event2.write(buffie);
+ buffie.flip();
+
+ //System.out.println("Event = \n"+ event2.toXML());
+ return buffie;
+ }
+
+
+ /**
+ * Main program for testing.
+ */
+ public static void main(String[] args) {
+
+ String etName = null, host = null;
+ int port = EtConstants.serverPort;
+ int group = 1;
+ int delay = 0;
+ int size = 32;
+
+ try {
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].equalsIgnoreCase("-f")) {
+ etName = args[++i];
+ }
+ else if (args[i].equalsIgnoreCase("-host")) {
+ host = args[++i];
+ }
+ else if (args[i].equalsIgnoreCase("-p")) {
+ try {
+ port = Integer.parseInt(args[++i]);
+ if ((port < 1024) || (port > 65535)) {
+ System.out.println("Port number must be between 1024 and 65535.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper port number.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-s")) {
+ try {
+ size = Integer.parseInt(args[++i]);
+ if (size < 1) {
+ System.out.println("Size needs to be positive int.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper size.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-g")) {
+ try {
+ group = Integer.parseInt(args[++i]);
+ if ((group < 1) || (group > 10)) {
+ System.out.println("Group number must be between 0 and 10.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper group number.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-d")) {
+ try {
+ delay = Integer.parseInt(args[++i]);
+ if (delay < 1) {
+ System.out.println("delay must be > 0.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper delay.");
+ usage();
+ return;
+ }
+ }
+ else {
+ usage();
+ return;
+ }
+ }
+
+ if (host == null) {
+ host = EtConstants.hostAnywhere;
+ /*
+ try {
+ host = InetAddress.getLocalHost().getHostName();
+ }
+ catch (UnknownHostException ex) {
+ System.out.println("Host not specified and cannot find local host name.");
+ usage();
+ return;
+ }
+ */
+ }
+
+ if (etName == null) {
+ usage();
+ return;
+ }
+
+ // make a direct connection to ET system's tcp server
+ EtSystemOpenConfig config = new EtSystemOpenConfig(etName, host, port);
+
+ // create ET system object with verbose debugging output
+ EtSystem sys = new EtSystem(config, EtConstants.debugInfo);
+ sys.open();
+
+ // get GRAND_CENTRAL station object
+ EtStation gc = sys.stationNameToObject("GRAND_CENTRAL");
+
+ // attach to grandcentral
+ EtAttachment att = sys.attach(gc);
+
+ // array of events
+ EtEvent[] mevs;
+
+ int chunk = 1, count = 0, startingVal = 0;
+ long t1, t2, counter = 0, totalT = 0, totalCount = 0;
+ double rate, avgRate;
+ int[] con = {1, 2, 3, 4};
+ String s;
+ ByteBuffer buf;
+
+ // keep track of time for event rate calculations
+ t1 = System.currentTimeMillis();
+
+ for (int i = 0; i < 50; i++) {
+ while (count < 30000L) {
+ // get array of new events
+ mevs = sys.newEvents(att, Mode.SLEEP, false, 0, chunk, size, group);
+
+ if (delay > 0) Thread.sleep(delay);
+
+ // example of how to manipulate events
+ if (true) {
+ for (int j = 0; j < mevs.length; j++) {
+ // put integer (j) into front of data buffer
+ //int swappedData = j + startingVal;
+ //swappedData = Integer.reverseBytes(swappedData);
+ buf = evioBytes();
+
+ mevs[j].getDataBuffer().put(buf);
+ int len = buf.position();
+ //mevs[j].setByteOrder(ByteOrder.LITTLE_ENDIAN);
+ // set data length to be 4 bytes (1 integer)
+ mevs[j].setLength(len);
+ // set every other event's priority as high
+ //if (j % 2 == 0) mevs[j].setPriority(Priority.HIGH);
+ // set event's control array
+ //mevs[j].setControl(con);
+ }
+ startingVal++;
+ }
+
+ // put events back into ET system
+ sys.putEvents(att, mevs);
+ count += mevs.length;
+
+ }
+
+ // calculate the event rate
+ t2 = System.currentTimeMillis();
+ rate = 1000.0 * ((double) count) / ((double) (t2 - t1));
+ totalCount += count;
+ totalT += t2 - t1;
+ avgRate = 1000.0 * ((double) totalCount) / totalT;
+ System.out.println("rate = " + String.format("%.3g", rate) +
+ " Hz, avg = " + String.format("%.3g", avgRate));
+ count = 0;
+ t1 = System.currentTimeMillis();
+ }
+ System.out.println("End of producing events, now close");
+ sys.close();
+ }
+ catch (Exception ex) {
+ System.out.println("Error using ET system as producer");
+ ex.printStackTrace();
+ }
+ }
+
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/apps
diff -N Producer.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Producer.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,271 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.apps;
+
+
+import java.lang.*;
+import java.nio.ByteOrder;
+
+import org.jlab.coda.et.*;
+import org.jlab.coda.et.enums.Mode;
+
+/**
+ * This class is an example of an event producer for an ET system.
+ *
+ * @author Carl Timmer
+ */
+public class Producer {
+
+ public Producer() {
+ }
+
+
+ private static void usage() {
+ System.out.println("\nUsage: java Producer -f <ET name> -host <ET host> [-h] [-v] [-r] [-c <chunk size>] [-d <delay>]\n" +
+ " [-s <event size>] [-g <group>] [-p <ET server port>] [-i <interface address>]\n\n" +
+ " -host ET system's host\n" +
+ " -f ET system's (memory-mapped file) name\n" +
+ " -h help\n" +
+ " -v verbose output\n" +
+ " -r act as remote (TCP) client even if ET system is local\n" +
+ " -c number of events in one get/put array\n" +
+ " -d delay in millisec between each round of getting and putting events\n" +
+ " -s event size in bytes\n" +
+ " -g group from which to get new events (1,2,...)\n" +
+ " -p ET server port\n" +
+ " -i outgoing network interface IP address (dot-decimal)\n\n" +
+ " This consumer works by making a direct connection to the\n" +
+ " ET system's server port.\n");
+ }
+
+
+ public static void main(String[] args) {
+
+ String etName = null, host = null, netInterface = null;
+ int port = EtConstants.serverPort;
+ int group = 1;
+ int delay = 0;
+ int size = 32;
+ int chunk = 1;
+ boolean verbose = false;
+ boolean remote = false;
+
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].equalsIgnoreCase("-f")) {
+ etName = args[++i];
+ }
+ else if (args[i].equalsIgnoreCase("-i")) {
+ netInterface = args[++i];
+ }
+ else if (args[i].equalsIgnoreCase("-host")) {
+ host = args[++i];
+ }
+ else if (args[i].equalsIgnoreCase("-p")) {
+ try {
+ port = Integer.parseInt(args[++i]);
+ if ((port < 1024) || (port > 65535)) {
+ System.out.println("Port number must be between 1024 and 65535.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper port number.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-c")) {
+ try {
+ chunk = Integer.parseInt(args[++i]);
+ if ((chunk < 1) || (chunk > 1000)) {
+ System.out.println("Chunk size may be 1 - 1000.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper chunk size.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-s")) {
+ try {
+ size = Integer.parseInt(args[++i]);
+ if (size < 1) {
+ System.out.println("Size needs to be positive int.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper size.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-g")) {
+ try {
+ group = Integer.parseInt(args[++i]);
+ if ((group < 1) || (group > 10)) {
+ System.out.println("Group number must be between 0 and 10.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper group number.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-d")) {
+ try {
+ delay = Integer.parseInt(args[++i]);
+ if (delay < 1) {
+ System.out.println("delay must be > 0.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper delay.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-v")) {
+ verbose = true;
+ }
+ else if (args[i].equalsIgnoreCase("-r")) {
+ remote = true;
+ }
+ else {
+ usage();
+ return;
+ }
+ }
+
+ if (host == null || etName == null) {
+ usage();
+ return;
+ }
+
+ try {
+ // Make a direct connection to ET system's tcp server
+ EtSystemOpenConfig config = new EtSystemOpenConfig(etName, host, port);
+ config.setConnectRemotely(remote);
+
+ // EXAMPLE: Broadcast to find ET system
+ //EtSystemOpenConfig config = new EtSystemOpenConfig();
+ //config.setHost(host);
+ //config.setEtName(etName);
+ //config.addBroadcastAddr("129.57.29.255"); // this call is not necessary
+
+ // EXAMPLE: Multicast to find ET system
+ //ArrayList<String> mAddrs = new ArrayList<String>();
+ //mAddrs.add(EtConstants.multicastAddr);
+ //EtSystemOpenConfig config = new EtSystemOpenConfig(etName, host,
+ // mAddrs, EtConstants.multicastPort, 32);
+
+ if (netInterface != null) config.setNetworkInterface(netInterface);
+
+ // create ET system object with verbose debugging output
+ EtSystem sys = new EtSystem(config);
+ if (verbose) sys.setDebug(EtConstants.debugInfo);
+ sys.open();
+
+ // get GRAND_CENTRAL station object
+ EtStation gc = sys.stationNameToObject("GRAND_CENTRAL");
+
+ // attach to GRAND_CENTRAL
+ EtAttachment att = sys.attach(gc);
+
+ // array of events
+ EtEvent[] mevs;
+
+ int count = 0, startingVal = 0;
+ long t1, t2, time, totalT = 0, totalCount = 0;
+ double rate, avgRate;
+
+ // create control array of correct size
+ int[] con = new int[EtConstants.stationSelectInts];
+ for (int i=0; i < EtConstants.stationSelectInts; i++) {
+ con[i] = i+1;
+ }
+
+ // keep track of time for event rate calculations
+ t1 = System.currentTimeMillis();
+
+ while (true) {
+ // get array of new events
+ mevs = sys.newEvents(att, Mode.SLEEP, false, 0, chunk, size, group);
+
+ if (delay > 0) Thread.sleep(delay);
+
+ // example of how to manipulate events
+ if (false) {
+ for (int j = 0; j < mevs.length; j++) {
+ // put integer (j + startingVal) into data buffer
+ int swappedData = Integer.reverseBytes(j + startingVal);
+ mevs[j].getDataBuffer().putInt(swappedData);
+
+ // big endian by default
+ mevs[j].setByteOrder(ByteOrder.LITTLE_ENDIAN);
+
+ // set data length to be 4 bytes (1 integer)
+ mevs[j].setLength(4);
+
+ // set event's control array
+ mevs[j].setControl(con);
+ }
+ startingVal += mevs.length;
+ }
+
+ // put events back into ET system
+ sys.putEvents(att, mevs);
+ count += mevs.length;
+
+ // calculate the event rate
+ t2 = System.currentTimeMillis();
+ time = t2 - t1;
+
+ if (time > 5000) {
+ // reset things if necessary
+ if ( (totalCount >= (Long.MAX_VALUE - count)) ||
+ (totalT >= (Long.MAX_VALUE - time)) ) {
+ totalT = totalCount = count = 0;
+ t1 = System.currentTimeMillis();
+ continue;
+ }
+ rate = 1000.0 * ((double) count) / time;
+ totalCount += count;
+ totalT += time;
+ avgRate = 1000.0 * ((double) totalCount) / totalT;
+ System.out.println("rate = " + String.format("%.3g", rate) +
+ " Hz, avg = " + String.format("%.3g", avgRate));
+ count = 0;
+ t1 = System.currentTimeMillis();
+ }
+ }
+ }
+ catch (Exception ex) {
+ System.out.println("Error using ET system as producer");
+ ex.printStackTrace();
+ }
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/apps
diff -N StartEt.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ StartEt.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,226 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.apps;
+
+import java.io.File;
+import java.lang.*;
+
+import org.jlab.coda.et.*;
+import org.jlab.coda.et.system.*;
+
+/**
+ * This class is an example of starting up an ET system.
+ *
+ * @author Carl Timmer
+ * @version 7.0
+ */
+public class StartEt {
+
+ /** Method to print out correct program command line usage. */
+ private static void usage() {
+
+ System.out.println("\nUsage: java StartEt [-h] [-v] [-d] [-f <file>] [-n <events>] [-s <evenSize>]\n" +
+ " [-g <groups>] [-p <TCP server port>] [-u <UDP port>]\n" +
+ " [-m <UDP multicast port>] [-a <multicast address>]\n" +
+ " [-rb <buf size>] [-sb <buf size>] [-nd]\n\n" +
+
+ " -h for help\n" +
+ " -v for verbose output\n" +
+ " -d deletes an existing file first\n" +
+ " -f sets memory-mapped file name\n" +
+ " -n sets number of events\n" +
+ " -s sets event size in bytes\n" +
+ " -g sets number of groups to divide events into\n" +
+ " -p sets TCP server port #\n" +
+ " -u sets UDP broadcast port #\n" +
+ " -m sets UDP multicast port #\n" +
+ " -a sets multicast address\n" +
+ " -rb TCP receive buffer size (bytes)\n" +
+ " -sb TCP send buffer size (bytes)\n" +
+ " -nd use TCP_NODELAY option\n");
+
+ }
+
+
+ public StartEt() {
+ }
+
+ public static void main(String[] args) {
+ int numEvents = 3000, size = 128;
+ int serverPort = EtConstants.serverPort;
+ int udpPort = EtConstants.broadcastPort;
+ int multicastPort = EtConstants.multicastPort;
+ int recvBufSize = 0, sendBufSize = 0;
+ int numGroups = 1;
+ boolean debug = false;
+ boolean noDelay = false;
+ boolean deleteFile = false;
+ String file = null;
+ String mcastAddr = null;
+
+ // loop over all args
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].equalsIgnoreCase("-h")) {
+ usage();
+ System.exit(-1);
+ }
+ else if (args[i].equalsIgnoreCase("-n")) {
+ numEvents = Integer.parseInt(args[i + 1]);
+ i++;
+ }
+ else if (args[i].equalsIgnoreCase("-f")) {
+ file = args[i + 1];
+ i++;
+ }
+ else if (args[i].equalsIgnoreCase("-p")) {
+ serverPort = Integer.parseInt(args[i + 1]);
+ i++;
+ }
+ else if (args[i].equalsIgnoreCase("-u")) {
+ udpPort = Integer.parseInt(args[i + 1]);
+ i++;
+ }
+ else if (args[i].equalsIgnoreCase("-m")) {
+ multicastPort = Integer.parseInt(args[i + 1]);
+ i++;
+ }
+ else if (args[i].equalsIgnoreCase("-s")) {
+ size = Integer.parseInt(args[i + 1]);
+ i++;
+ }
+ else if (args[i].equalsIgnoreCase("-rb")) {
+ recvBufSize = Integer.parseInt(args[i + 1]);
+ i++;
+ }
+ else if (args[i].equalsIgnoreCase("-sb")) {
+ sendBufSize = Integer.parseInt(args[i + 1]);
+ i++;
+ }
+ else if (args[i].equalsIgnoreCase("-nd")) {
+ noDelay = true;
+ }
+ else if (args[i].equalsIgnoreCase("-v")) {
+ debug = true;
+ }
+ else if (args[i].equalsIgnoreCase("-g")) {
+ numGroups = Integer.parseInt(args[i + 1]);
+ i++;
+ }
+ else if (args[i].equalsIgnoreCase("-a")) {
+ mcastAddr = args[i + 1];
+ i++;
+ }
+ else if (args[i].equalsIgnoreCase("-d")) {
+ deleteFile = true;
+ }
+ else {
+ usage();
+ System.exit(-1);
+ }
+ }
+
+ if (file == null) {
+ String et_filename = System.getenv("SESSION");
+ if (et_filename == null) {
+ System.out.println("No ET file name given and SESSION env variable not defined");
+ usage();
+ System.exit(-1);
+ }
+
+ file = "/tmp/et_sys_" + et_filename;
+ }
+
+ // check length of name
+ if (file.length() >= EtConstants.fileNameLengthMax) {
+ System.out.println("ET file name is too long");
+ usage();
+ System.exit(-1);
+ }
+
+ if (deleteFile) {
+ File f = new File(file);
+ f.delete();
+ }
+
+ try {
+ System.out.println("STARTING ET SYSTEM");
+ // ET system configuration object
+ SystemConfig config = new SystemConfig();
+
+ // listen for multicasts at this address
+ if (mcastAddr != null) {
+ config.addMulticastAddr(mcastAddr);
+ }
+ // set tcp server port
+ config.setServerPort(serverPort);
+ // set port for listening for udp packets
+ config.setUdpPort(udpPort);
+ // set port for listening for multicast udp packets
+ // (on Java this must be different than the udp port)
+ config.setMulticastPort(multicastPort);
+ // set total number of events
+ config.setNumEvents(numEvents);
+ // set size of events in bytes
+ config.setEventSize(size);
+ // set tcp receive buffer size in bytes
+ if (recvBufSize > 0) {
+ config.setTcpRecvBufSize(recvBufSize);
+ }
+ // set tcp send buffer size in bytes
+ if (sendBufSize > 0) {
+ config.setTcpSendBufSize(sendBufSize);
+ }
+ // set tcp no-delay
+ if (noDelay) {
+ config.setNoDelay(noDelay);
+ }
+ // set debug level
+ if (debug) {
+ config.setDebug(EtConstants.debugInfo);
+ }
+
+ // divide events into equal groups and any leftovers into another group */
+ if (numGroups > 1) {
+ int addgroup=0;
+
+ int n = numEvents / numGroups;
+ int r = numEvents % numGroups;
+ if (r > 0) {
+ addgroup = 1;
+ }
+
+ int[] groups = new int[numGroups+addgroup];
+
+ for (int i=0; i < numGroups; i++) {
+ groups[i] = n;
+ }
+
+ if (addgroup > 0) {
+ groups[numGroups] = r;
+ }
+
+ config.setGroups(groups);
+ }
+
+ // create an active ET system
+ SystemCreate sys = new SystemCreate(file, config);
+ }
+ catch (Exception ex) {
+ System.out.println("ERROR STARTING ET SYSTEM");
+ ex.printStackTrace();
+ }
+
+ }
+}
hps-et-java/src/main/java/org/jlab/coda/et/data
diff -N AllData.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ AllData.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,52 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.data;
+
+
+/**
+ * This class holds all the information about an ET system. This includes
+ * information about attachments, stations, processes, and the system
+ * level.
+ *
+ * @author Carl Timmer
+ */
+public class AllData {
+
+ /**
+ * Creates the bare minimum needed to hold the information of an ET system.
+ * Information about stations, attachments, and processes are added by
+ * other methods.
+ *
+ * @see org.jlab.coda.et.EtSystem#getData
+ */
+ public AllData() {
+ sysData = new SystemData();
+ }
+
+ /** Holds system information. */
+ public SystemData sysData;
+
+ /** Holds station information. */
+ public StationData statData[];
+
+ /** Holds attachment information. */
+ public AttachmentData attData[];
+
+ /**
+ * Hold process information. There are no processes (local processes which
+ * have direct access to the ET shared memory) in Java language ET.
+ */
+ public ProcessData procData[];
+}
hps-et-java/src/main/java/org/jlab/coda/et/data
diff -N AttachmentData.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ AttachmentData.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,214 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.data;
+
+import org.jlab.coda.et.EtConstants;
+import org.jlab.coda.et.EtUtils;
+
+import java.io.*;
+
+/**
+ * This class holds all information about an attachment. It parses
+ * the information from a stream of data sent by an ET system.
+ *
+ * @author Carl Timmer
+ */
+public class AttachmentData {
+
+ /** Attachment's id number.
+ * @see org.jlab.coda.et.EtAttachment#id
+ * @see org.jlab.coda.et.system.AttachmentLocal#id */
+ private int num;
+
+ /** Id number of ET process that created this attachment
+ * (only relevant in C-based ET systems). */
+ private int proc;
+
+ /** Id number of the attachment's station.
+ * @see org.jlab.coda.et.EtAttachment#station
+ * @see org.jlab.coda.et.system.AttachmentLocal#station */
+ private int stat;
+
+ /** Unix process id of the program that created this attachment
+ * (only relevant in C-based ET systems).
+ * @see org.jlab.coda.et.system.AttachmentLocal#pid */
+ private int pid;
+
+ /** Flag indicating if this attachment is blocked waiting to read events. Its
+ * value is {@link org.jlab.coda.et.EtConstants#attBlocked} if blocked and
+ * {@link org.jlab.coda.et.EtConstants#attUnblocked} otherwise.
+ * This is not boolean for C ET system compatibility.
+ * @see org.jlab.coda.et.system.AttachmentLocal#waiting */
+ private int blocked;
+
+ /** Flag indicating if this attachment has been told to quit trying to read
+ * events and return. Its value is {@link org.jlab.coda.et.EtConstants#attQuit} if it has been
+ * told to quit and {@link org.jlab.coda.et.EtConstants#attContinue} otherwise.
+ * This is not boolean for C ET system compatibility.
+ * @see org.jlab.coda.et.system.AttachmentLocal#wakeUp */
+ private int quit;
+
+ /** The number of events owned by this attachment */
+ private int eventsOwned;
+
+ /** Number of events put back into the station.
+ * @see org.jlab.coda.et.EtAttachment#getEventsPut
+ * @see org.jlab.coda.et.system.AttachmentLocal#eventsPut */
+ private long eventsPut;
+
+ /** Number of events gotten from the station.
+ * @see org.jlab.coda.et.EtAttachment#getEventsGet
+ * @see org.jlab.coda.et.system.AttachmentLocal#eventsGet */
+ private long eventsGet;
+
+ /** Number of events dumped (recycled by returning to GRAND_CENTRAL) through the station.
+ * @see org.jlab.coda.et.EtAttachment#getEventsDump
+ * @see org.jlab.coda.et.system.AttachmentLocal#eventsDump */
+ private long eventsDump;
+
+ /** Number of new events gotten from the station.
+ * @see org.jlab.coda.et.EtAttachment#getEventsMake
+ * @see org.jlab.coda.et.system.AttachmentLocal#eventsMake */
+ private long eventsMake;
+
+ /** Name of the host running this attachment.
+ * @see org.jlab.coda.et.system.AttachmentLocal#host */
+ private String host;
+
+ /** Name of the station this attachment is associated with. */
+ private String stationName;
+
+ /** IP address of the network interface the attachment is sending data through. */
+ private String ipAddress;
+
+
+ // getters
+
+
+ /** Get the attachment's id number.
+ * @return attachment's id number
+ * @see org.jlab.coda.et.EtAttachment#id
+ * @see org.jlab.coda.et.system.AttachmentLocal#id */
+ public int getId() {return num;}
+
+ /** Get the id number of ET process that created this attachment
+ * (only relevant in C-based ET systems).
+ * @return id number of ET process that created this attachment */
+ public int getProc() {return proc;}
+
+ /** Get the id number of the station to which this attachment belongs.
+ * @return id number of station to which this attachment belongs
+ * @see org.jlab.coda.et.EtAttachment#station
+ * @see org.jlab.coda.et.system.AttachmentLocal#station */
+ public int getStationId() {return stat;}
+
+ /** Get the Unix process id of the program that created this attachment
+ * (only relevant in C-based ET systems).
+ * @return Unix process id of the program that created this attachment
+ * @see org.jlab.coda.et.system.AttachmentLocal#pid */
+ public int getPid() {return pid;}
+
+ /** Indicates if this attachment is blocked waiting to read events.
+ * @return <code>true</code> if blocked waiting to read events, else <code>false</code>
+ * @see org.jlab.coda.et.system.AttachmentLocal#waiting */
+ public boolean blocked() {return blocked == EtConstants.attBlocked;}
+
+ /** Indicates if this attachment has been told to quit trying to read events and return.
+ * @return <code>true</code> if this attachment has been told to quit trying to read
+ * events and return, else <code>false</code>
+ * @see org.jlab.coda.et.system.AttachmentLocal#wakeUp */
+ public boolean quitting() {return quit == EtConstants.attQuit;}
+
+
+ /** Get the number of events owned by this attachment.
+ * @return number of events owned by this attachment */
+ public int getEventsOwned() {return eventsOwned;}
+
+ /** Get the number of events put back into the station.
+ * @return number of events put back into the station
+ * @see org.jlab.coda.et.EtAttachment#getEventsPut
+ * @see org.jlab.coda.et.system.AttachmentLocal#eventsPut */
+ public long getEventsPut() {return eventsPut;}
+
+ /** Get the number of events gotten from the station.
+ * @return number of events gotten from the station
+ * @see org.jlab.coda.et.EtAttachment#getEventsGet
+ * @see org.jlab.coda.et.system.AttachmentLocal#eventsGet */
+ public long getEventsGet() {return eventsGet;}
+
+ /** Get the number of events dumped (recycled by returning to GRAND_CENTRAL)
+ * through the station.
+ * @return number of events dumped through the station
+ * @see org.jlab.coda.et.EtAttachment#getEventsDump
+ * @see org.jlab.coda.et.system.AttachmentLocal#eventsDump */
+ public long getEventsDump() {return eventsDump;}
+
+ /** Get the number of new events gotten from the station.
+ * @return number of new events gotten from the station
+ * @see org.jlab.coda.et.EtAttachment#getEventsMake
+ * @see org.jlab.coda.et.system.AttachmentLocal#eventsMake */
+ public long getEventsMake() {return eventsMake;}
+
+ /** Get the name of the host running this attachment.
+ * @return name of the host running this attachment
+ * @see org.jlab.coda.et.system.AttachmentLocal#host */
+ public String getHost() {return host;}
+
+ /** Get the name of the station this attachment is associated with.
+ * @return name of the station this attachment is associated with */
+ public String getStationName() {return stationName;}
+
+ /** Get the IP address of the network interface the attachment is sending data through.
+ * @return IP address of the network interface the attachment is sending data through. */
+ public String getIpAddress() {return ipAddress;}
+
+ /**
+ * Reads the attachment information from an ET system over the network.
+ * @param dis data input stream
+ * @throws IOException if data read error
+ */
+ public void read(DataInputStream dis) throws IOException {
+ byte[] info = new byte[72];
+ dis.readFully(info);
+
+ num = EtUtils.bytesToInt(info, 0);
+ proc = EtUtils.bytesToInt(info, 4);
+ stat = EtUtils.bytesToInt(info, 8);
+ pid = EtUtils.bytesToInt(info, 12);
+ blocked = EtUtils.bytesToInt(info, 16);
+ quit = EtUtils.bytesToInt(info, 20);
+ eventsOwned = EtUtils.bytesToInt(info, 24);
+ eventsPut = EtUtils.bytesToLong(info, 28);
+ eventsGet = EtUtils.bytesToLong(info, 36);
+ eventsDump = EtUtils.bytesToLong(info, 44);
+ eventsMake = EtUtils.bytesToLong(info, 52);
+
+ // read strings, lengths first
+ int length1 = EtUtils.bytesToInt(info, 60);
+ int length2 = EtUtils.bytesToInt(info, 64);
+ int length3 = EtUtils.bytesToInt(info, 68);
+
+ if (length1 + length2 + length3 > 72) {
+ info = new byte[length1 + length2 + length3];
+ }
+ dis.readFully(info, 0, length1 + length2 + length3);
+ host = new String(info, 0, length1 - 1, "US-ASCII");
+ stationName = new String(info, length1, length2 - 1, "US-ASCII");
+ ipAddress = new String(info, length1+length2, length3 - 1, "US-ASCII");
+ }
+}
+
+
+
hps-et-java/src/main/java/org/jlab/coda/et/data
diff -N ProcessData.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ProcessData.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,114 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.data;
+
+import org.jlab.coda.et.EtConstants;
+
+import java.io.*;
+
+/**
+ * This class holds all information about an ET process. It parses
+ * the information from a stream of data sent by an ET system. There
+ * are no processes in Java ET systems.
+ *
+ * @author Carl Timmer
+ */
+public class ProcessData {
+
+ /** Unique id number. */
+ private int num;
+
+ /** Heartbeat count. */
+ private int heartbeat;
+
+ /** Unix process id. */
+ private int pid;
+
+ /** Number of attachments this process created. */
+ private int attachments;
+
+ /**
+ * An array of attachment id numbers. Only the first "attachments"
+ * number of elements are meaningful.
+ */
+ private int attIds[] = new int[EtConstants.attachmentsMax];
+
+
+ // get methods
+
+
+ /**
+ * Get the process' unique id number.
+ * @return process' unique id number
+ */
+ public int getId() {
+ return num;
+ }
+
+ /**
+ * Get the heartbeat count.
+ * @return heartbeat count
+ */
+ public int getHeartbeat() {
+ return heartbeat;
+ }
+
+ /**
+ * Get the Unix process id.
+ * @return Unix process id
+ */
+ public int getPid() {
+ return pid;
+ }
+
+ /**
+ * Get the number of attachments this process created.
+ * @return number of attachments this process created
+ */
+ public int getAttachments() {
+ return attachments;
+ }
+
+ /**
+ * Get the array of attachment id numbers.
+ * @return array of attachment id numbers
+ */
+ public int[] getAttachmentIds() {
+ return attIds.clone();
+ }
+
+ /**
+ * Reads the process information from an ET system over the network.
+ *
+ * @param dis data input stream
+ * @throws java.io.IOException if data read error
+ */
+ public void read(DataInputStream dis) throws IOException {
+ attachments = dis.readInt();
+ num = dis.readInt();
+ heartbeat = dis.readInt();
+ pid = dis.readInt();
+ for (int i = 0; i < attachments; i++) {
+ attIds[i] = dis.readInt();
+ }
+ }
+}
+
+
+
+
+
+
+
hps-et-java/src/main/java/org/jlab/coda/et/data
diff -N StationData.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ StationData.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,347 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.data;
+
+import org.jlab.coda.et.EtConstants;
+
+import java.lang.*;
+import java.io.*;
+
+/**
+ * This class holds all information about an station. It parses
+ * the information from a stream of data sent by an ET system.
+ *
+ * @author Carl Timmer
+ */
+public class StationData {
+
+ /** Station's id number.
+ * @see org.jlab.coda.et.EtStation#id
+ * @see org.jlab.coda.et.system.StationLocal#id */
+ private int num;
+
+ /** Station's status. It may have the values {@link org.jlab.coda.et.EtConstants#stationUnused},
+ * {@link org.jlab.coda.et.EtConstants#stationIdle}, or {@link org.jlab.coda.et.EtConstants#stationActive}.
+ * @see org.jlab.coda.et.system.StationLocal#status */
+ private int status;
+
+ /** Transfer mutex status. It has the value {@link org.jlab.coda.et.EtConstants#mutexLocked} if
+ * locked and {@link org.jlab.coda.et.EtConstants#mutexUnlocked} otherwise. This is only
+ * relevant in C-based ET systems, since in Java, mutexes cannot be tested without
+ * possibility of blocking. This is not boolean for C-based ET system compatibility.
+ * @see org.jlab.coda.et.system.StationLocal#stopTransferLock */
+ private int mutex;
+
+ /** Number of attachments to this station.
+ * @see org.jlab.coda.et.system.StationLocal#attachments */
+ private int attachments;
+
+ /** Array of attachment id numbers. Only the first "attachments"
+ * number of elements are meaningful.
+ * @see org.jlab.coda.et.system.StationLocal#attachments */
+ private int attIds[] = new int[EtConstants.attachmentsMax];
+
+
+ /** Input list mutex status. It has the value {@link org.jlab.coda.et.EtConstants#mutexLocked} if
+ * locked and {@link org.jlab.coda.et.EtConstants#mutexUnlocked} otherwise. This is only relevant
+ * in C-based ET systems, since in Java, mutexes cannot be tested without the
+ * chance of blocking. This is not boolean for C-based ET system compatibility. */
+ private int inListMutex;
+
+ /** Number of events in the input list.
+ * @see org.jlab.coda.et.system.EventList#events */
+ private int inListCount;
+
+ /** Number of events that were attempted to be put into the input list. This is
+ * relevant only when there is prescaling.
+ * @see org.jlab.coda.et.system.EventList#eventsTry */
+ private long inListTry;
+
+ /** Number of events that were put into the input list.
+ * @see org.jlab.coda.et.system.EventList#eventsIn */
+ private long inListIn;
+
+
+ /** Output list mutex status. It has the value {@link org.jlab.coda.et.EtConstants#mutexLocked} if
+ * locked and {@link org.jlab.coda.et.EtConstants#mutexUnlocked} otherwise. This is only relevant
+ * in C-based ET systems, since in Java, mutexes cannot be tested without the
+ * chance of blocking. This is not boolean for C-based ET system compatibility. */
+ private int outListMutex;
+
+ /** Number of events in the output list.
+ * @see org.jlab.coda.et.system.EventList#events */
+ private int outListCount;
+
+ /** Number of events that were taken out of the output list.
+ * @see org.jlab.coda.et.system.EventList#eventsOut */
+ private long outListOut;
+
+
+ // station configuration
+
+
+ /** Station configuration's flow mode.
+ * @see org.jlab.coda.et.EtStationConfig#userMode */
+ private int flowMode;
+
+ /** Station configuration's user mode.
+ * @see org.jlab.coda.et.EtStationConfig#userMode */
+ private int userMode;
+
+ /** Station configuration's restore mode.
+ * @see org.jlab.coda.et.EtStationConfig#restoreMode */
+ private int restoreMode;
+
+ /** Station configuration's blocking mode.
+ * @see org.jlab.coda.et.EtStationConfig#blockMode */
+ private int blockMode;
+
+ /** Station configuration's prescale value.
+ * @see org.jlab.coda.et.EtStationConfig#prescale */
+ private int prescale;
+
+ /** Station configuration's input cue size.
+ * @see org.jlab.coda.et.EtStationConfig#cue */
+ private int cue;
+
+ /** Station configuration's select mode.
+ * @see org.jlab.coda.et.EtStationConfig#selectMode */
+ private int selectMode;
+
+ /** Station configuration's select array.
+ * @see org.jlab.coda.et.EtStationConfig#select */
+ private int select[] = new int[EtConstants.stationSelectInts];
+
+ /** Name of user select function in C-based ET library.
+ * @see org.jlab.coda.et.EtStationConfig#selectFunction */
+ private String selectFunction;
+
+ /** Name of C library containing user select function in C-based ET system.
+ * @see org.jlab.coda.et.EtStationConfig#selectLibrary */
+ private String selectLibrary;
+
+ /** Name of Java class containing user select method in Java-based ET system.
+ * @see org.jlab.coda.et.EtStationConfig#selectClass */
+ private String selectClass;
+
+ /** Name of station.
+ * @see org.jlab.coda.et.EtStation#name
+ * @see org.jlab.coda.et.system.StationLocal#name */
+ private String name;
+
+
+ // get methods
+
+
+ /** Get the station's id number.
+ * @return station's id number
+ * @see org.jlab.coda.et.EtStation#id
+ * @see org.jlab.coda.et.system.StationLocal#id */
+ public int getId() {return num;}
+
+ /** Get the station's status. It may have the values {@link org.jlab.coda.et.EtConstants#stationUnused},
+ * {@link org.jlab.coda.et.EtConstants#stationIdle}, or {@link org.jlab.coda.et.EtConstants#stationActive}.
+ * @return station's status
+ * @see org.jlab.coda.et.system.StationLocal#status */
+ public int getStatus() {return status;}
+
+ /** Get the transfer mutex status. It has the value {@link org.jlab.coda.et.EtConstants#mutexLocked}
+ * if locked and {@link org.jlab.coda.et.EtConstants#mutexUnlocked} otherwise. This is only
+ * relevant in C-based ET systems.
+ * @return transfer mutex status */
+ public int getMutex() {return mutex;}
+
+ /** Get the number of attachments to this station.
+ * @return number of attachments to this station
+ * @see org.jlab.coda.et.system.StationLocal#attachments */
+ public int getAttachments() {return attachments;}
+
+ /** Get the array of attachment id numbers.
+ * @return array of attachment id numbers
+ * @see org.jlab.coda.et.system.StationLocal#attachments */
+ public int[] getAttachmentIds() {return attIds.clone();}
+
+
+ /** Get the input list mutex status. It has the value {@link org.jlab.coda.et.EtConstants#mutexLocked}
+ * if locked and {@link org.jlab.coda.et.EtConstants#mutexUnlocked} otherwise. This is only relevant
+ * in C-based ET systems.
+ * @return input list mutex status */
+ public int getInListMutex() {return inListMutex;}
+
+ /** Get the number of events in the input list.
+ * @return number of events in the input list
+ * @see org.jlab.coda.et.system.EventList#events */
+ public int getInListCount() {return inListCount;}
+
+ /** Get the number of events that were attempted to be put into the input list.
+ * This is relevant only when there is prescaling.
+ * @return number of events that were attempted to be put into the input list
+ * @see org.jlab.coda.et.system.EventList#eventsTry */
+ public long getInListTry() {return inListTry;}
+
+ /** Get the number of events that were put into the input list.
+ * @return number of events that were put into the input list
+ * @see org.jlab.coda.et.system.EventList#eventsIn */
+ public long getInListIn() {return inListIn;}
+
+
+ /** Get the output list mutex status. It has the value {@link org.jlab.coda.et.EtConstants#mutexLocked}
+ * if locked and {@link org.jlab.coda.et.EtConstants#mutexUnlocked} otherwise. This is only relevant
+ * in C ET systems.
+ * @return output list mutex status */
+ public int getOutListMutex() {return outListMutex;}
+
+ /** Get the number of events in the output list.
+ * @return number of events in the output list
+ * @see org.jlab.coda.et.system.EventList#events */
+ public int getOutListCount() {return outListCount;}
+
+ /** Get the number of events that were taken out of the output list.
+ * @return number of events that were taken out of the output list
+ * @see org.jlab.coda.et.system.EventList#eventsOut */
+ public long getOutListOut() {return outListOut;}
+
+
+ // station configuration parameters ...
+
+
+ /** Get the station configuration's flow mode.
+ * @return station configuration's flow mode
+ * @see org.jlab.coda.et.EtStationConfig#flowMode */
+ public int getFlowMode() {return flowMode;}
+
+ /** Get the station configuration's user mode.
+ * @return station configuration's user mode
+ * @see org.jlab.coda.et.EtStationConfig#userMode */
+ public int getUserMode() {return userMode;}
+
+ /** Get the station configuration's restore mode.
+ * @return station configuration's restore mode
+ * @see org.jlab.coda.et.EtStationConfig#restoreMode */
+ public int getRestoreMode() {return restoreMode;}
+
+ /** Get the station configuration's blocking mode.
+ * @return station configuration's blocking mode
+ * @see org.jlab.coda.et.EtStationConfig#blockMode */
+ public int getBlockMode() {return blockMode;}
+
+ /** Get the station configuration's prescale value.
+ * @return station configuration's prescale value
+ * @see org.jlab.coda.et.EtStationConfig#prescale */
+ public int getPrescale() {return prescale;}
+
+ /** Get the station configuration's input cue size.
+ * @return station configuration's input cue size
+ * @see org.jlab.coda.et.EtStationConfig#cue */
+ public int getCue() {return cue;}
+
+ /** Get the station configuration's select mode.
+ * @return station configuration's select mode
+ * @see org.jlab.coda.et.EtStationConfig#selectMode */
+ public int getSelectMode() {return selectMode;}
+
+ /** Get the station configuration's select array.
+ * @return station configuration's select array
+ * @see org.jlab.coda.et.EtStationConfig#select */
+ public int[] getSelect() {return select.clone();}
+
+ /** Get the name of the user select function in the C-based ET library.
+ * @return name of the user select function in the C-based ET library
+ * @see org.jlab.coda.et.EtStationConfig#selectFunction */
+ public String getSelectFunction() {return selectFunction;}
+
+ /** Get the name of the C library containing the user select function in
+ * the C-based ET system.
+ * @return name of the C library containing the user select function
+ * @see org.jlab.coda.et.EtStationConfig#selectLibrary */
+ public String getSelectLibrary() {return selectLibrary;}
+
+ /** Get the name of the Java class containing the user select method in
+ * the Java-based ET system.
+ * @return name of the Java class containing the user select method
+ * @see org.jlab.coda.et.EtStationConfig#selectClass */
+ public String getSelectClass() {return selectClass;}
+
+ /** Get the name of the station.
+ * @return name of the station
+ * @see org.jlab.coda.et.EtStation#name
+ * @see org.jlab.coda.et.system.StationLocal#name */
+ public String getName() {return name;}
+
+
+ /**
+ * Reads the station information from an ET system over the network.
+ * @param dis data input stream
+ * @throws IOException if data read error
+ */
+ public void read(DataInputStream dis) throws IOException {
+ attachments = dis.readInt();
+ num = dis.readInt();
+ status = dis.readInt();
+ mutex = dis.readInt();
+ for (int i=0; i < attachments; i++) {
+ attIds[i] = dis.readInt();
+ }
+
+ inListMutex = dis.readInt();
+ inListCount = dis.readInt();
+ inListTry = dis.readLong();
+ inListIn = dis.readLong();
+ outListMutex = dis.readInt();
+ outListCount = dis.readInt();
+ outListOut = dis.readLong();
+
+ flowMode = dis.readInt();
+ userMode = dis.readInt();
+ restoreMode = dis.readInt();
+ blockMode = dis.readInt();
+ prescale = dis.readInt();
+ cue = dis.readInt();
+ selectMode = dis.readInt();
+
+ for (int i=0; i < EtConstants.stationSelectInts; i++) {
+ select[i] = dis.readInt();
+ }
+
+ // read strings, lengths first
+ int length1 = dis.readInt();
+ int length2 = dis.readInt();
+ int length3 = dis.readInt();
+ int length4 = dis.readInt();
+ int length = length1 + length2 + length3 + length4;
+
+ byte[] buf = new byte[length];
+ dis.readFully(buf, 0, length);
+ int off = 0;
+
+ if (length1 > 0) {
+ selectFunction = new String(buf, off, length1-1, "US-ASCII");
+ off += length1;
+ }
+ if (length2 > 0) {
+ selectLibrary = new String(buf, off, length2-1, "US-ASCII");
+ off += length2;
+ }
+ if (length3 > 0) {
+ selectClass = new String(buf, off, length3-1, "US-ASCII");
+ off += length3;
+ }
+ if (length4 > 0) {
+ name = new String(buf, off, length4-1, "US-ASCII");
+ }
+
+ }
+}
+
hps-et-java/src/main/java/org/jlab/coda/et/data
diff -N SystemData.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ SystemData.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,398 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.data;
+
+import org.jlab.coda.et.EtUtils;
+
+import java.io.*;
+
+/**
+ * This class holds all system level information about an ET system. It parses
+ * the information from a stream of data sent by an ET system.
+ *
+ * @author Carl Timmer
+ */
+public class SystemData {
+
+
+ // values which can change
+
+
+ /** Flag which specifying whether the ET system is alive. A value of 1 means
+ * alive and 0 means dead. */
+ private int alive;
+
+ /** Heartbeat count of the ET system process. It is not relevant in Java-based ET
+ * systems. */
+ private int heartbeat;
+
+ /** Count of the current amount of temporary events. It is not relevant in
+ * Java-based ET systems. */
+ private int temps;
+
+ /** Count of the current number of stations in the linked list (are either
+ * active or idle).
+ * @see org.jlab.coda.et.system.SystemCreate#stations */
+ private int stations;
+
+ /** Count of the current number of attachments.
+ * @see org.jlab.coda.et.system.SystemCreate#attachments */
+ private int attachments;
+
+ /** Count of the current number of processes. It is not relevant in Java-based ET
+ * systems. */
+ private int processes;
+
+ /** Number of events owned by the system (as opposed to attachments). */
+ private int eventsOwned;
+
+
+ /** System mutex status. It has the value {@link org.jlab.coda.et.EtConstants#mutexLocked} if
+ * locked and {@link org.jlab.coda.et.EtConstants#mutexUnlocked} otherwise. This is only
+ * relevant in C-based ET systems, since in Java, mutexes cannot be tested without
+ * possibility of blocking. This is not boolean for C-based ET system compatibility.
+ * {@link org.jlab.coda.et.system.SystemCreate#systemLock}. */
+ private int mutex;
+
+ /** Station mutex status. It has the value {@link org.jlab.coda.et.EtConstants#mutexLocked} if
+ * locked and {@link org.jlab.coda.et.EtConstants#mutexUnlocked} otherwise. This is only
+ * relevant in C-based ET systems, since in Java, mutexes cannot be tested without
+ * possibility of blocking. This is not boolean for C-based ET system compatibility.
+ * {@link org.jlab.coda.et.system.SystemCreate#stationLock}. */
+ private int statMutex;
+
+ /** Add-station mutex status. It has the value {@link org.jlab.coda.et.EtConstants#mutexLocked}
+ * if locked and {@link org.jlab.coda.et.EtConstants#mutexUnlocked} otherwise. This is only
+ * relevant in C-based ET systems as this mutex is not used in Java systems. */
+ private int statAddMutex;
+
+
+ // values which do NOT change
+
+
+ /** Endian of host running the ET system. This can have values of either
+ * {@link org.jlab.coda.et.EtConstants#endianBig} or
+ * {@link org.jlab.coda.et.EtConstants#endianLittle}. */
+ private int endian;
+
+ /** Flag specifying whether the operating system can share mutexes between
+ * processes. It has the value {@link org.jlab.coda.et.EtConstants#mutexShare} if they can be
+ * shared and {@link org.jlab.coda.et.EtConstants#mutexNoShare} otherwise. This is not
+ * relevant in Java-based ET systems. */
+ private int share;
+
+ /** Unix pid of the ET system process. This is not relevant for Java-based ET
+ * systems, and C-based ET systems on Linux may have several pids. */
+ private int mainPid;
+
+ /** The number of ints in a station's select array.
+ * @see org.jlab.coda.et.EtConstants#stationSelectInts */
+ private int selects;
+
+ /** Total number of events in a system.
+ * @see org.jlab.coda.et.system.SystemConfig#numEvents
+ * @see org.jlab.coda.et.system.SystemCreate#events */
+ private int events;
+
+ /** Size of "normal" events in bytes.
+ * @see org.jlab.coda.et.system.SystemConfig#eventSize */
+ private long eventSize;
+
+ /** Is the operating system running the ET system 64 bit? */
+ private boolean bit64;
+
+ /** Maximum number of temporary events allowed in the ET system. This is not
+ * relevant in Java-based ET systems. */
+ private int tempsMax;
+
+ /** Maximum number of stations allowed in the ET system.
+ * @see org.jlab.coda.et.system.SystemConfig#stationsMax */
+ private int stationsMax;
+
+ /** Maximum number of attachments allowed in the ET system.
+ * @see org.jlab.coda.et.system.SystemConfig#attachmentsMax */
+ private int attachmentsMax;
+
+ /** Maximum number of processes allowed in the ET system. This is not
+ * relevant in Java-based ET systems. */
+ private int processesMax;
+
+
+ /** Port number of the ET TCP server.
+ * @see org.jlab.coda.et.system.SystemConfig#serverPort */
+ private int tcpPort;
+
+ /** Port number of the ET UDP broadcast listening thread.
+ * @see org.jlab.coda.et.system.SystemConfig#udpPort */
+ private int udpPort;
+
+ /** Port number of the ET UDP multicast listening thread.
+ * @see org.jlab.coda.et.system.SystemConfig#multicastPort */
+ private int multicastPort;
+
+ /** Number of network interfaces on the host computer. */
+ private int interfaceCount;
+
+ /** Number of multicast addresses the UDP server listens on. */
+ private int multicastCount;
+
+ /** Dotted-decimal IP addresses of network interfaces on the host. */
+ private String interfaceAddresses[];
+
+ /** Dotted-decimal multicast addresses the UDP server listens on.
+ * @see org.jlab.coda.et.system.SystemConfig#getMulticastStrings()
+ * @see org.jlab.coda.et.system.SystemConfig#getMulticastAddrs()
+ * @see org.jlab.coda.et.system.SystemConfig#addMulticastAddr(String)
+ * @see org.jlab.coda.et.system.SystemConfig#removeMulticastAddr(String) */
+ private String multicastAddresses[];
+
+ /** The ET system (file) name.
+ * @see org.jlab.coda.et.system.SystemCreate#SystemCreate(String)
+ * @see org.jlab.coda.et.system.SystemCreate#name */
+ private String etName;
+
+
+ // Getters
+
+
+ /** Specifies whether the ET system is alive.
+ * @return <code>true</code> if ET system alive, else <code>false</code> */
+ public boolean alive() {return alive == 1;}
+
+ /** Get the heartbeat count of the ET system process. It is not relevant
+ * in Java-based ET systems.
+ * @return heartbeat count of the ET system process */
+ public int getHeartbeat() {return heartbeat;}
+
+ /** Get the current number of temporary events.
+ * @return current number of temporary events */
+ public int getTemps() {return temps;}
+
+ /** Get the current number of stations in the linked list
+ * (either active or idle).
+ * @return current number of stations in the linked list */
+ public int getStations() {return stations;}
+
+ /** Get the current number of attachments.
+ * @return current number of attachments */
+ public int getAttachments() {return attachments;}
+
+ /** Get the current number of processes. It is not relevant in Java-based ET systems.
+ * @return current number of processes */
+ public int getProcesses() {return processes;}
+
+ /** Get the number of events owned by the system (not by attachments).
+ * @return number of events owned by the system */
+ public int getEventsOwned() {return eventsOwned;}
+
+
+ /** Get the system mutex status. It has the value {@link org.jlab.coda.et.EtConstants#mutexLocked}
+ * if locked and {@link org.jlab.coda.et.EtConstants#mutexUnlocked} otherwise. This is only
+ * relevant in C-based ET systems as this mutex is not used in Java-based systems.
+ * @return system mutex status */
+ public int getMutex() {return mutex;}
+
+ /** Get the station mutex status. It has the value {@link org.jlab.coda.et.EtConstants#mutexLocked}
+ * if locked and {@link org.jlab.coda.et.EtConstants#mutexUnlocked} otherwise. This is only
+ * relevant in C-based ET systems as this mutex is not used in Java-based systems.
+ * @return station mutex status */
+ public int getStatMutex() {return statMutex;}
+
+ /** Get the add-station mutex status. It has the value {@link org.jlab.coda.et.EtConstants#mutexLocked}
+ * if locked and {@link org.jlab.coda.et.EtConstants#mutexUnlocked} otherwise. This is only
+ * relevant in C-based ET systems as this mutex is not used in Java-based systems.
+ * @return add-station mutex status */
+ public int getStatAddMutex() {return statAddMutex;}
+
+
+ /** Get the endian value of the host running the ET system. This can
+ * have values of either {@link org.jlab.coda.et.EtConstants#endianBig} or
+ * {@link org.jlab.coda.et.EtConstants#endianLittle}.
+ * @return endian value of the host running the ET system */
+ public int getEndian() {return endian;}
+
+ /** Get the value specifying whether the operating system can share
+ * mutexes between processes. It has the value {@link org.jlab.coda.et.EtConstants#mutexShare}
+ * if they can be shared and {@link org.jlab.coda.et.EtConstants#mutexNoShare} otherwise.
+ * It is not relevant in Java ET systems.
+ * @return value specifying whether the operating system can share
+ * mutexes between processes */
+ public int getShare() {return share;}
+
+ /** Get the Unix pid of the ET system process. Java-based ET systems return
+ * -1, and C-based ET systems on Linux may have several, additional pids
+ * not given here.
+ * @return Unix pid of the ET system process */
+ public int getMainPid() {return mainPid;}
+
+ /** Get the number of ints in a station's select array.
+ * @return number of ints in a station's select array
+ * @see org.jlab.coda.et.EtConstants#stationSelectInts */
+ public int getSelects() {return selects;}
+
+ /** Get the total number of events in a system.
+ * @return total number of events in a system
+ * @see org.jlab.coda.et.system.SystemConfig#numEvents
+ * @see org.jlab.coda.et.system.SystemCreate#events */
+ public int getEvents() {return events;}
+
+ /** Get the size of "normal" events in bytes.
+ * @return size of "normal" events in bytes
+ * @see org.jlab.coda.et.system.SystemConfig#eventSize */
+ public long getEventSize() {return eventSize;}
+
+ /** Gets whether the number of bits of the operating system running the ET system
+ * is 64 bits. If not, then it's 32 bits.
+ * @return <code>true</code> if the operating system running the ET system
+ * is 64 bits, else <code>false</code> */
+ public boolean isBit64() {return bit64;}
+
+ /** Get the maximum number of temporary events allowed in the ET system.
+ * This is not relevant in Java ET systems.
+ * @return maximum number of temporary events allowed in the ET system */
+ public int getTempsMax() {return tempsMax;}
+
+ /** Get the maximum number of stations allowed in the ET system.
+ * @return maximum number of stations allowed in the ET system
+ * @see org.jlab.coda.et.system.SystemConfig#stationsMax */
+ public int getStationsMax() {return stationsMax;}
+
+ /** Get the maximum number of attachments allowed in the ET system.
+ * @return maximum number of attachments allowed in the ET system
+ * @see org.jlab.coda.et.system.SystemConfig#attachmentsMax */
+ public int getAttachmentsMax() {return attachmentsMax;}
+
+ /** Get the maximum number of processes allowed in the ET system.
+ * @return maximum number of processes allowed in the ET system
+ * This is not relevant in Java ET systems. */
+ public int getProcessesMax() {return processesMax;}
+
+
+ /** Get the port number of the ET TCP server.
+ * @return port number of the ET TCP server
+ * @see org.jlab.coda.et.system.SystemConfig#serverPort */
+ public int getTcpPort() {return tcpPort;}
+
+ /** Get the port number of the ET UDP broadcast listening thread.
+ * @return port number of the ET UDP broadcase listening thread
+ * @see org.jlab.coda.et.system.SystemConfig#udpPort */
+ public int getUdpPort() {return udpPort;}
+
+ /** Get the port number of the ET UDP multicast listening thread.
+ * @return port number of the ET UDP multicast listening thread
+ * @see org.jlab.coda.et.system.SystemConfig#multicastPort */
+ public int getMulticastPort() {return multicastPort;}
+
+ /** Get the number of network interfaces on the host computer.
+ * @return number of network interfaces on the host computer */
+ public int getInterfaces() {return interfaceCount;}
+
+ /** Get the number of multicast addresses the UDP server listens on.
+ * @return number of multicast addresses the UDP server listens on */
+ public int getMulticasts() {return multicastCount;}
+
+ /** Get the dotted-decimal IP addresses of network interfaces on the host.
+ * @return dotted-decimal IP addresses of network interfaces on the host */
+ public String[] getInterfaceAddresses() {return interfaceAddresses.clone();}
+
+ /** Get the dotted-decimal multicast addresses the UDP server listens on.
+ * @return dotted-decimal multicast addresses the UDP server listens on
+ * @see org.jlab.coda.et.system.SystemConfig#getMulticastStrings()
+ * @see org.jlab.coda.et.system.SystemConfig#getMulticastAddrs()
+ * @see org.jlab.coda.et.system.SystemConfig#addMulticastAddr(String)
+ * @see org.jlab.coda.et.system.SystemConfig#removeMulticastAddr(String) */
+ public String[] getMulticastAddresses() {return multicastAddresses.clone();}
+
+ /** Get the ET system (file) name.
+ * @return ET system (file) name
+ * @see org.jlab.coda.et.system.SystemCreate#SystemCreate(String)
+ * @see org.jlab.coda.et.system.SystemCreate#name */
+ public String getEtName() {return etName;}
+
+
+ /**
+ * Reads the system level information from an ET system over the network.
+ * @param dis data input stream
+ * @throws IOException if data read error
+ */
+ public void read(DataInputStream dis) throws IOException {
+ int off = 0;
+ byte[] info = new byte[108];
+ dis.readFully(info);
+
+ alive = EtUtils.bytesToInt(info, off);
+ heartbeat = EtUtils.bytesToInt(info, off+=4);
+ temps = EtUtils.bytesToInt(info, off+=4);
+ stations = EtUtils.bytesToInt(info, off+=4);
+ attachments = EtUtils.bytesToInt(info, off+=4);
+ processes = EtUtils.bytesToInt(info, off+=4);
+ eventsOwned = EtUtils.bytesToInt(info, off+=4);
+ mutex = EtUtils.bytesToInt(info, off+=4);
+ statMutex = EtUtils.bytesToInt(info, off+=4);
+ statAddMutex = EtUtils.bytesToInt(info, off+=4);
+
+ endian = EtUtils.bytesToInt(info, off+=4);
+ share = EtUtils.bytesToInt(info, off+=4);
+ mainPid = EtUtils.bytesToInt(info, off+=4);
+ selects = EtUtils.bytesToInt(info, off+=4);
+ events = EtUtils.bytesToInt(info, off+=4);
+ eventSize = EtUtils.bytesToLong(info, off+=4);
+ bit64 = EtUtils.bytesToInt(info, off+=8) == 1;
+
+ tempsMax = EtUtils.bytesToInt(info, off+=4);
+ stationsMax = EtUtils.bytesToInt(info, off+=4);
+ attachmentsMax = EtUtils.bytesToInt(info, off+=4);
+ processesMax = EtUtils.bytesToInt(info, off+=4);
+
+ tcpPort = EtUtils.bytesToInt(info, off+=4);
+ udpPort = EtUtils.bytesToInt(info, off+=4);
+ multicastPort = EtUtils.bytesToInt(info, off+=4);
+
+ interfaceCount = EtUtils.bytesToInt(info, off+=4);
+ multicastCount = EtUtils.bytesToInt(info, off+=4);
+
+ // read string lengths first
+ off = 0;
+ int lengthTotal = 0;
+ int lengths[] = new int[interfaceCount+multicastCount+1];
+ for (int i=0; i < interfaceCount+multicastCount+1; i++) {
+ lengths[i] = dis.readInt();
+ lengthTotal += lengths[i];
+ }
+
+ if (lengthTotal > 100) {
+ info = new byte[lengthTotal];
+ }
+ dis.readFully(info, 0, lengthTotal);
+
+ // read network interface addresses
+ interfaceAddresses = new String[interfaceCount];
+ for (int i=0; i < interfaceCount; i++) {
+ interfaceAddresses[i] = new String(info, off, lengths[i]-1, "US-ASCII");
+ off += lengths[i];
+ }
+
+ // read multicast addresses
+ multicastAddresses = new String[multicastCount];
+ for (int i=0; i < multicastCount; i++) {
+ multicastAddresses[i] = new String(info, off, lengths[i+interfaceCount]-1, "US-ASCII");
+ off += lengths[i+interfaceCount];
+ }
+
+ // read et name
+ etName = new String(info, off, lengths[interfaceCount+multicastCount]-1, "US-ASCII");
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/enums
diff -N Age.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Age.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,79 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2010 Jefferson Science Associates, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.enums;
+
+import org.jlab.coda.et.EtConstants;
+
+/**
+ * This enum indicates whether an event is a new or unused event, obtained by a call to
+ * {@link org.jlab.coda.et.EtSystem#newEvents}, or whether it is an existing or used event, obtained by
+ * a call to {@link org.jlab.coda.et.EtSystem#getEvents}.
+ *
+ * @author timmer
+ */
+public enum Age {
+
+ /** Existing event with data, obtained throug getEvents(). */
+ USED (EtConstants.eventUsed),
+ /** New event with no data, obtained throug newEvents(). */
+ NEW (EtConstants.eventNew);
+
+
+ private int value;
+
+ private Age(int value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the enum's value.
+ * @return the value
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Obtain the name from the value.
+ *
+ * @param value the value to match.
+ * @return the name, or null.
+ */
+ public static String getName(int value) {
+ Age ages[] = Age.values();
+ for (Age a : ages) {
+ if (a.value == value) {
+ return a.name();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Obtain the enum from the value.
+ *
+ * @param value the value to match.
+ * @return the matching enum, or <code>null</code>.
+ */
+ public static Age getAge(int value) {
+ Age ages[] = Age.values();
+ for (Age a : ages) {
+ if (a.value == value) {
+ return a;
+ }
+ }
+ return null;
+ }
+}
hps-et-java/src/main/java/org/jlab/coda/et/enums
diff -N DataStatus.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ DataStatus.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,80 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2010 Jefferson Science Associates, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.enums;
+
+import org.jlab.coda.et.EtConstants;
+
+/**
+ * This enum represents the 3 possible states of an event's data's status.
+ * OK is default. CORRUPT is never used. POSSIBLYCORRUPT is assigned to events
+ * whose owning process crashed and were recovered by the system.
+ *
+ * @author timmer
+ */
+public enum DataStatus {
+ /** Data is OK or uncorrupted. */
+ OK (EtConstants.dataOk),
+ /** Data is worthless or corrupted. */
+ CORRUPT (EtConstants.dataCorrupt),
+ /** Data status is unkown and might be corrupted. */
+ POSSIBLYCORRUPT (EtConstants.dataPossiblyCorrupt);
+
+ private int value;
+
+ private DataStatus(int value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the enum's value.
+ * @return the value
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Obtain the name from the value.
+ *
+ * @param value the value to match.
+ * @return the name, or null.
+ */
+ public static String getName(int value) {
+ DataStatus stats[] = DataStatus.values();
+ for (DataStatus s : stats) {
+ if (s.value == value) {
+ return s.name();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Obtain the enum from the value.
+ *
+ * @param value the value to match.
+ * @return the matching enum, or <code>null</code>.
+ */
+ public static DataStatus getStatus(int value) {
+ DataStatus stats[] = DataStatus.values();
+ for (DataStatus s : stats) {
+ if (s.value == value) {
+ return s;
+ }
+ }
+ return null;
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/enums
diff -N Mode.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Mode.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,82 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2010 Jefferson Science Associates, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.enums;
+
+import org.jlab.coda.et.EtConstants;
+
+/**
+ * This enum represents 3 possible modes in which to get new or existing events
+ * when no events are currently available (in calls newEvents() or getEvents()).
+ * SLEEP indicates that the user will wait (forever if necessary) until some
+ * are available. TIMED means the user will wait up to the given delay time, and
+ * ASYNC means that the call will return immediately.
+ *
+ * @author timmer
+ */
+public enum Mode {
+ /** Wait forever for events to become available. */
+ SLEEP (EtConstants.sleep),
+ /** Wait up to a given delay time for events to become available. */
+ TIMED (EtConstants.timed),
+ /** Do not wait for events to become available. */
+ ASYNC (EtConstants.async);
+
+ private int value;
+
+ private Mode(int value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the enum's value.
+ * @return the value
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Obtain the name from the value.
+ *
+ * @param value the value to match.
+ * @return the name, or null.
+ */
+ public static String getName(int value) {
+ Mode modes[] = Mode.values();
+ for (Mode m : modes) {
+ if (m.value == value) {
+ return m.name();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Obtain the enum from the value.
+ *
+ * @param value the value to match.
+ * @return the matching enum, or <code>null</code>.
+ */
+ public static Mode getMode(int value) {
+ Mode modes[] = Mode.values();
+ for (Mode m : modes) {
+ if (m.value == value) {
+ return m;
+ }
+ }
+ return null;
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/enums
diff -N Modify.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Modify.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,85 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2010 Jefferson Science Associates, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.enums;
+
+import org.jlab.coda.et.EtConstants;
+
+/**
+ * This enum represents the 3 possible modifications a networked user can make to
+ * an event. NOTHING means no changes will be made. HEADER means only information
+ * in the event header (non-data) will possibly be modified. ANYTHING means that either
+ * header or data will possibly be modified. If the user gets events in which NOTHING will
+ * be modified, the server sends a copy of the event to the user over the network
+ * and immediately puts the originals back into the system. This greatly increases
+ * performance.
+ *
+ * @author timmer
+ */
+public enum Modify {
+ /** Network user will make no changes to data or header (non-data). Event is readonly. */
+ NOTHING (0),
+ /** Network user may make changes to data and/or header (non-data). Event is read-write. */
+ ANYTHING (EtConstants.modify),
+ /** Network user may make changes to header (non-data) only. */
+ HEADER (EtConstants.modifyHeader);
+
+ private int value;
+
+ private Modify(int value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the enum's value.
+ * @return the value
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Obtain the name from the value.
+ *
+ * @param value the value to match.
+ * @return the name, or null.
+ */
+ public static String getName(int value) {
+ Modify mods[] = Modify.values();
+ for (Modify m : mods) {
+ if (m.value == value) {
+ return m.name();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Obtain the enum from the value.
+ *
+ * @param value the value to match.
+ * @return the matching enum, or <code>null</code>.
+ */
+ public static Modify getModify(int value) {
+ Modify mods[] = Modify.values();
+ for (Modify m : mods) {
+ if (m.value == value) {
+ return m;
+ }
+ }
+ return null;
+ }
+
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/enums
diff -N Priority.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Priority.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,76 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2010 Jefferson Science Associates, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.enums;
+
+import org.jlab.coda.et.EtConstants;
+
+/**
+ * This enum represents the 2 possible priorities an event can have.
+ * Low is normal, but high puts events to the front of station input/output lists.
+ * @author timmer
+ */
+public enum Priority {
+ /** Low or normal priority, events take their proper turn. */
+ LOW (EtConstants.low),
+ /** High priority, events cut in and move to the front of the list. */
+ HIGH (EtConstants.high);
+
+ private int value;
+
+ private Priority(int value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the enum's value.
+ * @return the value
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Obtain the name from the value.
+ *
+ * @param value the value to match.
+ * @return the name, or null.
+ */
+ public static String getName(int value) {
+ Priority pris[] = Priority.values();
+ for (Priority p : pris) {
+ if (p.value == value) {
+ return p.name();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Obtain the enum from the value.
+ *
+ * @param value the value to match.
+ * @return the matching enum, or <code>null</code>.
+ */
+ public static Priority getPriority(int value) {
+ Priority pris[] = Priority.values();
+ for (Priority p : pris) {
+ if (p.value == value) {
+ return p;
+ }
+ }
+ return null;
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/exception
diff -N EtBusyException.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtBusyException.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,38 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.exception;
+import java.lang.*;
+
+/**
+ * This class represents an error of an ET system when a user cannot access a
+ * station's input list because another thread or process is accessing it.
+ *
+ * @author Carl Timmer
+ */
+
+public class EtBusyException extends Exception {
+
+ /**
+ * Create an exception indicating when a user cannot access a
+ * station's input list because another thread or process is accessing it.
+ * {@inheritDoc}<p/>
+ *
+ * @param message {@inheritDoc}<p/>
+ */
+ public EtBusyException(String message) {
+ super(message);
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/exception
diff -N EtDeadException.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtDeadException.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,20 @@
+package org.jlab.coda.et.exception;
+
+/**
+ * This class represents an error of an ET system when its processes are dead.
+ *
+ * @author Carl Timmer
+ */
+public class EtDeadException extends Exception {
+
+ /**
+ * Create an exception indicating an error of an ET system when its processes are dead.
+ * {@inheritDoc}<p/>
+ *
+ * @param message {@inheritDoc}<p/>
+ */
+ public EtDeadException(String message) {
+ super(message);
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/exception
diff -N EtEmptyException.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtEmptyException.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,37 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.exception;
+import java.lang.*;
+
+/**
+ * This class represents an error of an ET system when a station's input list
+ * is empty.
+ *
+ * @author Carl Timmer
+ */
+
+public class EtEmptyException extends Exception {
+
+ /**
+ * Create an exception indicating an error of an ET system when a station's input list is empty.
+ * {@inheritDoc}<p/>
+ *
+ * @param message {@inheritDoc}<p/>
+ */
+ public EtEmptyException(String message) {
+ super(message);
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/exception
diff -N EtException.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtException.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.exception;
+import java.lang.*;
+
+/**
+ * This class represents a general error of an ET system.
+ *
+ * @author Carl Timmer
+ */
+
+public class EtException extends Exception {
+
+ /**
+ * Create an exception indicating an error specific to the ET system.
+ * {@inheritDoc}<p/>
+ *
+ * @param message {@inheritDoc}<p/>
+ */
+ public EtException(String message) {
+ super(message);
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/exception
diff -N EtExistsException.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtExistsException.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,37 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.exception;
+import java.lang.*;
+
+/**
+ * This class represents an error of an ET system when an item to be created
+ * already exists.
+ *
+ * @author Carl Timmer
+ */
+
+public class EtExistsException extends Exception {
+
+ /**
+ * Create an exception indicating when an item to be created already exists.
+ * {@inheritDoc}<p/>
+ *
+ * @param message {@inheritDoc}<p/>
+ */
+ public EtExistsException(String message) {
+ super(message);
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/exception
diff -N EtReadException.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtReadException.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.exception;
+import java.lang.*;
+
+/**
+ * This class represents a network read error of an ET system.
+ *
+ * @author Carl Timmer
+ */
+
+public class EtReadException extends Exception {
+
+ /**
+ * Create an exception indicating a network read error of an ET system.
+ * {@inheritDoc}<p/>
+ *
+ * @param message {@inheritDoc}<p/>
+ */
+ public EtReadException(String message) {
+ super(message);
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/exception
diff -N EtTimeoutException.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtTimeoutException.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.exception;
+import java.lang.*;
+
+/**
+ * This class represents a timeout error of an ET system.
+ *
+ * @author Carl Timmer
+ */
+
+public class EtTimeoutException extends Exception {
+
+ /**
+ * Create an exception indicating a timeout error of an ET system.
+ * {@inheritDoc}<p/>
+ *
+ * @param message {@inheritDoc}<p/>
+ */
+ public EtTimeoutException(String message) {
+ super(message);
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/exception
diff -N EtTooManyException.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtTooManyException.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,39 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.exception;
+import java.lang.*;
+
+/**
+ * This class represents an error of an ET system when creating an item would
+ * result in too many such items existing.
+ *
+ * @author Carl Timmer
+ */
+
+public class EtTooManyException extends Exception {
+
+ /**
+ * Create an exception indicating an error of an ET system when
+ * creating an item would result in too many such items existing.
+ * {@inheritDoc}<p/>
+ *
+ * @param message {@inheritDoc}<p/>
+ */
+ public EtTooManyException(String message) {
+ super(message);
+ }
+
+}
+
hps-et-java/src/main/java/org/jlab/coda/et/exception
diff -N EtWakeUpException.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtWakeUpException.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,38 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.exception;
+import java.lang.*;
+
+/**
+ * This class represents an error of an ET system when an attachment has been
+ * told to wake up from a blocking read.
+ *
+ * @author Carl Timmer
+ */
+
+public class EtWakeUpException extends Exception {
+
+ /**
+ * Create an exception indicating an error of an ET system
+ * when an attachment has been told to wake up from a blocking read.
+ * {@inheritDoc}<p/>
+ *
+ * @param message {@inheritDoc}<p/>
+ */
+ public EtWakeUpException(String message) {
+ super(message);
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/exception
diff -N EtWriteException.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EtWriteException.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.exception;
+import java.lang.*;
+
+/**
+ * This class represents a network write error of an ET system.
+ *
+ * @author Carl Timmer
+ */
+
+public class EtWriteException extends Exception {
+
+ /**
+ * Create an exception indicating a network write error of an ET system.
+ * {@inheritDoc}<p/>
+ *
+ * @param message {@inheritDoc}<p/>
+ */
+ public EtWriteException(String message) {
+ super(message);
+ }
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/monitorGui
diff -N Monitor.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Monitor.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,2048 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2002 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.monitorGui;
+
+import java.lang.*;
+import java.net.*;
+import java.io.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.tree.*;
+import javax.swing.border.*;
+import javax.swing.event.*;
+
+import org.xml.sax.SAXException;
+import org.jlab.coda.et.*;
+import org.jlab.coda.et.exception.*;
+
+/**
+ * This class implements a monitor of ET systems.
+ *
+ * @author Carl Timmer
+ */
+
+public class Monitor extends JFrame {
+ // static variables
+ private static MonitorConfiguration config;
+ private static File configurationFile;
+
+ // important widgets' names
+ private final JTabbedPane tabbedPane;
+ private final JFrame openFrame;
+ private final JMenu disconnectMenu, loadConnectionParametersMenu;
+ private JComboBox bAddress, mAddress, etName, hostname, cast;
+ private WholeNumberField ttl, udpPort, mcastPort, tcpPort, period;
+ private JButton connect;
+
+ // other variables
+ private String currentMonitorKey;
+ private int defaultPeriod;
+
+ // keep track of connections to & monitors of ET systems
+ public final Map<String, EtSystem> connections =
+ Collections.synchronizedMap(new HashMap<String, EtSystem>(20));
+ public final Map<String,MonitorSingleSystem> monitors =
+ Collections.synchronizedMap(new HashMap<String,MonitorSingleSystem>(20));
+
+ // Default colors
+ public final Color textColorDefault = Color.black;
+ public final Color textBackgroundColorDefault = Color.white;
+ public final Color titleColorDefault = Color.black;
+ public final Color backgroundColorDefault = new Color(238, 220, 130); // lightGoldenrod2
+ public final Color selectedTabColorDefault = Color.yellow;
+ public final Color tabsBackgroundColorDefault = Color.cyan;
+ // Colors used
+ private Color textColor = textColorDefault;
+ private Color textBackgroundColor = textBackgroundColorDefault;
+ private Color titleColor = titleColorDefault;
+ private Color backgroundColor = backgroundColorDefault;
+ private Color selectedTabColor = selectedTabColorDefault;
+ private Color tabsBackgroundColor = tabsBackgroundColorDefault;
+
+
+ public Monitor() {
+ this(null, null, null);
+ }
+
+
+ public Monitor(Color[] colors, Dimension frameSize, Point frameLocation) {
+ super("ET System Monitor");
+
+ // Set application colors.
+ if (colors != null) {
+ if (colors[0] != null) titleColor = colors[0];
+ if (colors[1] != null) backgroundColor = colors[1];
+ if (colors[2] != null) selectedTabColor = colors[2];
+ if (colors[3] != null) tabsBackgroundColor = colors[3];
+ if (colors[4] != null) textColor = colors[4];
+ if (colors[5] != null) textBackgroundColor = colors[5];
+ }
+ // Set window location.
+ if (frameLocation != null) {
+ setLocation(frameLocation);
+ }
+ // Default data update period in seconds.
+ defaultPeriod = 5;
+
+ // To change some colors, the following is the only way to do it.
+ UIManager.put("ComboBox.foreground", textColor);
+ UIManager.put("ComboBox.background", textBackgroundColor);
+ // UIManager.put("ComboBox.disabledForeground", Color.blue);
+ // UIManager.put("ComboBox.selectionForeground", Color.cyan);
+ // UIManager.put("ComboBox.selectionBackground", Color.magenta);
+
+ // tabbedPane stuff
+ UIManager.put("TabbedPane.selected", selectedTabColor);
+ tabbedPane = new JTabbedPane();
+ tabbedPane.setFont(MonitorFonts.buttonTabMenuFont);
+ tabbedPane.setBackground(backgroundColor);
+ tabbedPane.setForeground(titleColor);
+ if (frameSize == null) {
+ frameSize = new Dimension(1100, 700);
+ }
+ tabbedPane.setPreferredSize(frameSize);
+ // Keep track of which ET system we're currently looking at.
+ tabbedPane.addChangeListener(
+ new ChangeListener() {
+ public void stateChanged(ChangeEvent e) {
+ JTabbedPane source = (JTabbedPane) e.getSource();
+ int tabIndex = source.getSelectedIndex();
+ // if help pane is showing, reset period & return
+ if (tabIndex < 1) {
+ period.setValue(defaultPeriod);
+ currentMonitorKey = "Help";
+ return;
+ }
+ currentMonitorKey = source.getTitleAt(tabIndex);
+ int updatePeriod = ((MonitorSingleSystem) (monitors.get(currentMonitorKey))).getUpdatePeriod();
+ period.setValue(updatePeriod);
+ }
+ }
+ );
+ getContentPane().setBackground(tabsBackgroundColor);
+ getContentPane().add(tabbedPane, BorderLayout.CENTER);
+
+ // Final members need to be initialized in all constructors.
+ openFrame = new JFrame("Open ET System");
+ disconnectMenu = new JMenu("Disconnect");
+ loadConnectionParametersMenu = new JMenu("Load Connection Parameters");
+
+ // Make window used to input data needed to connect to an ET system.
+ makeEtOpenWindow();
+ // Define this window's menubar.
+ makeMenubar();
+ // Add to help screen to main window's tabbed pane
+ tabbedPane.addTab("Help", null, makeHelpPane(), "help");
+ currentMonitorKey = "Help";
+ }
+
+ // Change the update period of current single system monitor.
+ private void setUpdatePeriod() {
+ if (currentMonitorKey.equals("Help")) return;
+ int updatePeriod = period.getValue();
+ MonitorSingleSystem mon = (MonitorSingleSystem) monitors.get(currentMonitorKey);
+ mon.setUpdatePeriod(updatePeriod);
+ return;
+ }
+
+ //===================
+ // Getters & Setters
+ //===================
+
+ // add ET file names to combo box
+ public void addFileName(String name) {
+ boolean nameIsThere = false;
+ int count = etName.getItemCount();
+
+ for (int i = 0; i < count; i++) {
+ if (name.equals((String) etName.getItemAt(i))) {
+ return;
+ }
+ }
+ if (!nameIsThere) {
+ etName.addItem(name);
+ }
+ return;
+ }
+
+ // add host names to combo box
+ public boolean addHostname(String name) {
+ if (name.equals(EtConstants.hostLocal) ||
+ name.equals(EtConstants.hostRemote) ||
+ name.equals(EtConstants.hostAnywhere)) {
+ return false;
+ }
+ boolean nameIsThere = false;
+ int count = hostname.getItemCount();
+ for (int i = 0; i < count; i++) {
+ if (name.equals((String) hostname.getItemAt(i))) {
+ return true;
+ }
+ }
+ if (!nameIsThere) {
+ hostname.addItem(name);
+ }
+ return true;
+ }
+
+ // add addresses to combo boxes
+ public void addBroadcastAddress(String addr) {
+ bAddress.addItem(addr);
+ }
+
+ public void addMulticastAddress(String addr) {
+ mAddress.addItem(addr);
+ }
+
+ //get ET names from combo box
+ public String[] getFileNames() {
+ int count = etName.getItemCount();
+ if (count == 0) return null;
+ String[] names = new String[count];
+ for (int i = 0; i < count; i++) {
+ names[i] = (String) etName.getItemAt(i);
+ }
+ return names;
+ }
+
+ //get host names from combo box
+ public String[] getHostnames() {
+ // Skip the first 3 items as they never change.
+ int count = hostname.getItemCount() - 3;
+ if (count < 1) return null;
+ String[] names = new String[count];
+ for (int i = 0; i < count; i++) {
+ names[i] = (String) hostname.getItemAt(i + 3);
+ }
+ return names;
+ }
+
+ public int getMonitorWidth() {
+ return tabbedPane.getWidth();
+ }
+
+ public int getMonitorHeight() {
+ return tabbedPane.getHeight();
+ }
+
+ public Color getTextColor() {
+ return new Color(textColor.getRGB());
+ }
+
+ public Color getTextBackgroundColor() {
+ return new Color(textBackgroundColor.getRGB());
+ }
+
+ public Color getTitleColor() {
+ return new Color(titleColor.getRGB());
+ }
+
+ public Color getBackgroundColor() {
+ return new Color(backgroundColor.getRGB());
+ }
+
+ public Color getSelectedTabColor() {
+ return new Color(selectedTabColor.getRGB());
+ }
+
+ public Color getTabsBackgroundColor() {
+ return new Color(tabsBackgroundColor.getRGB());
+ }
+
+ private boolean isValidIpAddress(String addr) {
+ StringTokenizer tok = new StringTokenizer(addr, ".");
+ if (tok.countTokens() != 4) {
+ return false;
+ }
+
+ int number;
+ String num;
+ try {
+ while (tok.hasMoreTokens()) {
+ num = tok.nextToken();
+ number = Integer.parseInt(num);
+ if (number < 0 || number > 255) {
+ return false;
+ }
+ if (num.charAt(0) == '0' && (number != 0 || num.length() > 1)) {
+ return false;
+ }
+ }
+ }
+ catch (NumberFormatException ex) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isValidMulticastAddress(String addr) {
+ InetAddress address = null;
+ try {
+ address = InetAddress.getByName(addr);
+ }
+ catch (UnknownHostException e) {
+ return false;
+ }
+
+ return (address.isMulticastAddress());
+
+ /*
+ StringTokenizer tok = new StringTokenizer(addr, ".");
+ if (tok.countTokens() != 4) {
+ return false;
+ }
+
+ int number, round = 1;
+ String num;
+ try {
+ while (tok.hasMoreTokens()) {
+ num = tok.nextToken();
+ number = Integer.parseInt(num);
+ if ((round++ == 1) && (number < 224 || number > 239)) {
+ return false;
+ }
+ if (number < 0 || number > 255) {
+ return false;
+ }
+ if (num.charAt(0) == '0' && (number != 0 || num.length() > 1)) {
+ return false;
+ }
+ }
+ }
+ catch (NumberFormatException ex) {
+ return false;
+ }
+ return true;
+ */
+ }
+
+ public static void main(String[] args) {
+ try {
+ Monitor frame = null;
+
+ // allow for a configuration file argument
+ if (args.length > 0) {
+ if (args.length != 2) {
+ System.out.println("Usage: java Monitor [-f,-file <configFile>]");
+ return;
+ }
+ if (!(args[0].equalsIgnoreCase("-f") || args[0].equalsIgnoreCase("-file"))) {
+ System.out.println("Usage: java Monitor [-f,-file <configFile>]");
+ return;
+ }
+ configurationFile = new File(args[1]);
+
+ // Read config file once to get main application window &
+ // color data only.
+ // This is done because the frame needs to have the colors,
+ // size, and position BEFORE it displays anything.
+ config = new MonitorConfiguration(null);
+ config.loadWindowParameters(configurationFile);
+ Color[] colors = config.getWindowColors();
+ Dimension size = config.getWindowSize();
+ Point location = config.getWindowLocation();
+ frame = new Monitor(colors, size, location);
+ // Read config file again to get the rest of the data.
+ // This needs the application to have already started
+ // (as in the previous line) - the reason being that
+ // connections to ET systems need to be made etc.
+ config.setMonitor(frame);
+ config.load(configurationFile);
+ }
+ else {
+ frame = new Monitor();
+ config = new MonitorConfiguration(frame);
+ }
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ System.exit(0);
+ }
+ });
+
+ frame.pack();
+ frame.setVisible(true);
+
+ MonitorSingleSystem mon = null;
+ DefaultMutableTreeNode monNode = null;
+
+ // Class designed to run graphics commands in the Swing thread.
+ class Updater extends Thread {
+ MonitorSingleSystem mon; // single system monitor of interest
+
+ public void setMonitor(MonitorSingleSystem m) {
+ mon = m;
+ }
+
+ public Updater(MonitorSingleSystem m) {
+ mon = m;
+ }
+
+ public void run() {
+ if (mon.isInitialized()) {
+ mon.updateDisplay();
+ mon.treeDidChange();
+ }
+ else {
+ mon.staticDisplay();
+ mon.updateDisplay();
+ mon.updateUI();
+ }
+ }
+ }
+
+ Updater updater = new Updater(mon);
+
+ while (true) {
+ // While we're in the iterator, we CANNOT have monitors added
+ // (and thereby change the structure of the HashMap).
+ synchronized (frame.monitors) {
+ for (Iterator i = frame.monitors.entrySet().iterator(); i.hasNext();) {
+ // get monitor object
+ mon = (MonitorSingleSystem) (((Map.Entry) i.next()).getValue());
+ monNode = mon.getNode();
+
+ try {
+ // only update if enough time has elapsed
+ if (mon.timeToUpdate()) {
+ // get data
+ mon.getData();
+ updater.setMonitor(mon);
+ // display new data
+ SwingUtilities.invokeLater(updater);
+ }
+ }
+ catch (EtException ex) {
+ //System.out.print("\n*****************************************\n");
+ //System.out.print("* Error getting data from ET system *");
+ //System.out.print("\n*****************************************\n");
+ //ex.printStackTrace();
+ }
+ catch (Exception ex) {
+ //System.out.print("\n*****************************************\n");
+ //System.out.print("* I/O error getting data from ET system *");
+ //System.out.print("\n*****************************************\n");
+ String key = mon.getKey();
+ // Remove connection with the IO problem.
+ frame.removeConnection(frame, mon, key, false);
+ // Remove single system monitor from hash table.
+ i.remove();
+ // Remove EtSystem object from hash table.
+ frame.connections.remove(key);
+
+ //ex.printStackTrace();
+ }
+ }
+ }
+ Thread.sleep(500);
+ }
+ }
+
+ catch (Exception ex) {
+ System.out.println("Unrecoverable error in ET monitor:");
+ ex.printStackTrace();
+ }
+
+ }
+
+
+ private void makeMenubar() {
+
+ JMenuBar menuBar = new JMenuBar();
+ menuBar.setBackground(backgroundColor);
+ setJMenuBar(menuBar);
+
+ // file menu
+ JMenu fileMenu = new JMenu("File");
+ fileMenu.setFont(MonitorFonts.buttonTabMenuFont);
+ fileMenu.setBackground(backgroundColor);
+ fileMenu.setForeground(titleColor);
+ menuBar.add(fileMenu);
+
+ // Create a file chooser
+ final JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
+
+ // file menu item to save configuration
+ JMenuItem menuItem = new JMenuItem("Save Configuration");
+ menuItem.setFont(MonitorFonts.buttonTabMenuFont);
+ menuItem.setBackground(backgroundColor);
+ menuItem.setForeground(titleColor);
+ fileMenu.add(menuItem);
+ menuItem.addActionListener(
+ new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ File file;
+ if (configurationFile == null) {
+ if (fc.showSaveDialog(Monitor.this) == JFileChooser.CANCEL_OPTION) {
+ return;
+ }
+ file = fc.getSelectedFile();
+ }
+ else {
+ file = configurationFile;
+ }
+
+ try {
+ config.save(file);
+ }
+ catch (IOException ex) {
+ JOptionPane.showMessageDialog(new JFrame(),
+ "Cannot write to file \"" + file.getName() + "\"",
+ "Error",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ configurationFile = file;
+
+ }
+ }
+ );
+
+ // file menu item to save configuration
+ menuItem = new JMenuItem("Save Configuration As");
+ menuItem.setFont(MonitorFonts.buttonTabMenuFont);
+ menuItem.setBackground(backgroundColor);
+ menuItem.setForeground(titleColor);
+ fileMenu.add(menuItem);
+ menuItem.addActionListener(
+ new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ int returnVal = fc.showSaveDialog(Monitor.this);
+
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File file = fc.getSelectedFile();
+ try {
+ if (file.exists()) {
+ int n = JOptionPane.showConfirmDialog(
+ new JFrame(),
+ "Overwrite existing file?",
+ "WARNING",
+ JOptionPane.YES_NO_OPTION);
+ if (n == JOptionPane.NO_OPTION) return;
+ }
+ config.save(file);
+ }
+ catch (IOException ex) {
+ JOptionPane.showMessageDialog(new JFrame(),
+ "Cannot write to file \"" + file.getName() + "\"",
+ "Error",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ configurationFile = file;
+ }
+ }
+ }
+ );
+
+ // file menu item to load configuration
+ menuItem = new JMenuItem("Load Configuration");
+ menuItem.setFont(MonitorFonts.buttonTabMenuFont);
+ menuItem.setBackground(backgroundColor);
+ menuItem.setForeground(titleColor);
+ fileMenu.add(menuItem);
+ menuItem.addActionListener(
+ new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ int returnVal = fc.showDialog(Monitor.this, "Load");
+
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File file = fc.getSelectedFile();
+ try {
+ config.load(file);
+ }
+ catch (SAXException ex) {
+ JOptionPane.showMessageDialog(new JFrame(),
+ "Cannot load file \"" + file.getName() + "\"",
+ "Error",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ catch (IOException ex) {
+ JOptionPane.showMessageDialog(new JFrame(),
+ "Cannot load file \"" + file.getName() + "\"",
+ "Error",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ }
+ }
+ }
+ );
+
+ // File menu item to quit.
+ menuItem = new JMenuItem("Quit");
+ menuItem.setFont(MonitorFonts.buttonTabMenuFont);
+ menuItem.setBackground(backgroundColor);
+ menuItem.setForeground(titleColor);
+ fileMenu.add(menuItem);
+ menuItem.addActionListener(
+ new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ System.exit(0);
+ }
+ }
+ );
+
+ // View menu to change update period of monitored ET system.
+ JMenu viewMenu = new JMenu("View");
+ viewMenu.setFont(MonitorFonts.buttonTabMenuFont);
+ viewMenu.setBackground(backgroundColor);
+ viewMenu.setForeground(titleColor);
+ menuBar.add(viewMenu);
+
+ period = new WholeNumberField(defaultPeriod, 5, 1, Integer.MAX_VALUE);
+ period.setFont(MonitorFonts.inputFont);
+ period.setAlignmentX(Component.LEFT_ALIGNMENT);
+ period.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ WholeNumberField source = (WholeNumberField) e.getSource();
+ source.correctValue();
+ setUpdatePeriod();
+ }
+ }
+ );
+ period.addMouseListener(new MouseAdapter() {
+ public void mouseExited(MouseEvent e) {
+ WholeNumberField source = (WholeNumberField) e.getSource();
+ source.correctValue();
+ setUpdatePeriod();
+ }
+ }
+ );
+
+ JMenu updatePeriod = new JMenu("Update Period (sec)");
+ updatePeriod.setFont(MonitorFonts.buttonTabMenuFont);
+ updatePeriod.setBackground(backgroundColor);
+ updatePeriod.setForeground(titleColor);
+ updatePeriod.add(period);
+ viewMenu.add(updatePeriod);
+
+ // menu to load connection parameters from a specific, existing connection
+ loadConnectionParametersMenu.setFont(MonitorFonts.buttonTabMenuFont);
+ loadConnectionParametersMenu.setBackground(backgroundColor);
+ loadConnectionParametersMenu.setForeground(titleColor);
+ viewMenu.add(loadConnectionParametersMenu);
+
+ // menuitem to switch JSplitPane orientation
+ menuItem = new JMenuItem("Change Orientation");
+ menuItem.setFont(MonitorFonts.buttonTabMenuFont);
+ menuItem.setBackground(backgroundColor);
+ menuItem.setForeground(titleColor);
+ viewMenu.add(menuItem);
+ menuItem.addActionListener(
+ new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ if (currentMonitorKey.equals("Help")) return;
+ MonitorSingleSystem mon = (MonitorSingleSystem) monitors.get(currentMonitorKey);
+ int orient = mon.getOrientation();
+ if (orient == JSplitPane.HORIZONTAL_SPLIT) {
+ mon.setOrientation(JSplitPane.VERTICAL_SPLIT);
+ }
+ else {
+ mon.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
+ }
+ }
+ }
+ );
+
+ // connect menu
+ JMenu connectMenu = new JMenu("Connections");
+ connectMenu.setFont(MonitorFonts.buttonTabMenuFont);
+ connectMenu.setBackground(backgroundColor);
+ connectMenu.setForeground(titleColor);
+ menuBar.add(connectMenu);
+
+ menuItem = new JMenuItem("Connect to ET System");
+ menuItem.setFont(MonitorFonts.buttonTabMenuFont);
+ menuItem.setBackground(backgroundColor);
+ menuItem.setForeground(titleColor);
+ connectMenu.add(menuItem);
+ menuItem.addActionListener(
+ new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ openFrame.setVisible(true);
+ openFrame.setState(Frame.NORMAL);
+ }
+ }
+ );
+
+ // menu to disconnect existing connections
+ disconnectMenu.setFont(MonitorFonts.buttonTabMenuFont);
+ disconnectMenu.setBackground(backgroundColor);
+ disconnectMenu.setForeground(titleColor);
+ connectMenu.add(disconnectMenu);
+ }
+
+
+ private JScrollPane makeHelpPane() {
+ // Put this into the tabbedPane.
+ JTextArea text = new JTextArea(10, 200);
+ text.setFont(MonitorFonts.helpFont);
+ text.setLineWrap(true);
+ text.setWrapStyleWord(true);
+ text.setTabSize(3);
+ text.setEditable(false);
+ text.setBorder(new EmptyBorder(20, 20, 20, 20));
+ JScrollPane pane = new JScrollPane(text);
+
+ // Put stuff into the text area.
+ text.append(
+ "CONNECTING TO AN ET SYSTEM\n" +
+
+ "Select the \"Connect to ET System\" option of the \"Connections\" menu. " +
+ "There are a number of options on the appearing window which must be set.\n\n" +
+
+ "1) ET Name\nThis is the name of the ET system (actually, its file) that you " +
+ "want to connect to. The names of several ET systems can be stored in its " +
+ "list. The \"X\" button is for removing unwanted entries.\n\n" +
+
+ "2) ET Location\nTo look for the named ET system on the local computer or host, " +
+ "select \"local\". To look only on another computer, select \"remote\", " +
+ "or \"anywhere\" if you don't care where the ET system is. If you know the " +
+ "name of the computer, this is the place to type it in.\n\n" +
+
+ "3) Find ET by\n" +
+ "There are several ways to connect to an ET system. The following list showing " +
+ "the available choices:\n\n" +
+
+ "\ta) broadcasting\nThis selection is generally chosen when the name of the host " +
+ "that the ET system is residing on is unknown or if the user wants to write a very " +
+ "general application with no hostnames \"hardcoded\" or input in some fashion. " +
+ "(If a specific hostname is used, a UDP packet is sent directly to that host in " +
+ "addition to a broadcast being made.)\n" +
+ "A UDP broadcast is made on all the subnet broadcast addresses listed in the " +
+ "\"Subnet Addresses\" entry. Items can be removed with the \"X\" button. " +
+ "This broadcast is sent to the port found in the \"UDP Port\" entry. " +
+ "Once an ET system receives the broadcast, it responds by sending its host name " +
+ "and the tcp port on which it is listening. This information is used " +
+ "to establish a permanent tcp connection.\n\n" +
+
+ "\tb) multicasting\nAs in broadcasting, this selection is generally chosen when " +
+ "the name of the host that the ET system is residing on is unknown or if the user " +
+ "wants to write a very general application with no hostnames \"hardcoded\" or input " +
+ "in some fashion. (If a specific hostname is used, a UDP packet is sent directly to " +
+ "that host on the port in the \"UDP Port\" entry in addition to a multicast " +
+ "being made.)\n" +
+ "A UDP multicast is made on all the multicast addresses " +
+ "listed in the \"Multicast Addresses\" entry. Items can be removed with the \"X\" " +
+ "button. This multicast is sent to the port found in the \"Multicast Port\" " +
+ "entry, and its \"ttl\" value can be set as well. (It defaults to \"1\" which " +
+ "should limit its scope to the local subnets.) " +
+ "Once an ET system receives the multicast, it responds by sending its host name " +
+ "and the tcp port on which it is listening. This information is used " +
+ "to establish a permanent tcp connection.\n\n" +
+
+ "\tc) broad & multicasting\nThis selection can simultaneously UDP broadcast " +
+ "and UDP multicast.\n\n" +
+
+ "\td) direct connection\nA direct, permanent tcp connection is made between the ET " +
+ "system and the user. In this case, a specific hostname must be used (not \"local\", " +
+ "\"remote\", or \"anywhere\"). The \"TCP Port\" entry is used for the port number.\n\n" +
+
+ "RESETTING CONNECTION PARAMETERS\n" +
+ "Reseting all connection parameters to those previously used to make an actual " +
+ "connection can be done by selecting the \"Load connection parameters\" item from " +
+ "the \"View\" menu. Simply select from the list of existing connections.\n\n\n\n" +
+
+ "VIEWING AN ET SYSTEM\n" +
+
+ "After connecting to an ET system, a tab appears with the ET system's name on it. " +
+ "By selecting this tab, the user can see all the system parameters in text form on " +
+ "the left side of the window and a visual representation on the right side. Not all " +
+ "text information is relevant for all systems. For example, the ET systems written in " +
+ "Java do not have process or mutex information available. Text information " +
+ "is divided into sections with a short explanation of each following:\n\n" +
+
+ "1) System - general ET system parameters\n" +
+ "\ta) Static Info - information that does NOT change\n" +
+ "\t\tHost - host system is running on, language code was written in, and unix pid\n" +
+ "\t\tPorts - the tcp, udp, and multicast port numbers\n" +
+ "\t\tEvents - total # of events, size of each, # of temporary (extra large) events\n" +
+ "\t\tMax - maximum number of stations, attachments, and processes allowed\n" +
+ "\t\tNetwork interfaces - list of host's network interfaces\n" +
+ "\t\tMulticast addreses - list of multicast addresses the system is listening on\n\n" +
+
+ "\tb) Dynamic Info - information that can or will change in time\n" +
+ "\t\tEvents rate - rate of events leaving GRAND_CENTRAL station\n" +
+ "\t\tEvents owned by - number of events owned by each attachment & system.\n" +
+ "\t\tIdle stations - list of stations with no attachments (receive no events)\n" +
+ "\t\tAll stations - list of all stations in proper order\n" +
+ "\t\tStations - current number of stations, attachments, and temporary events\n" +
+ "\t\tProcesses - # of non-system, unix processes with access to shared memory (Solaris)\n" +
+ "\t\tHeartbeat - value of non-Java system's counter in shared memory (changes if alive)\n" +
+ "\t\tLocked Mutexes - on non-Java systems, locked pthread mutexes.\n\n" +
+
+ "2) Stations - stations are listed by name under this heading\n" +
+ "\ta) Configuration - parameters which define station behavior\n" +
+ "\t\t- active or idle, blocking or nonblocking, prescale & cue values\n" +
+ "\t\t- single user, multiple users, or the exact number of allowed users\n" +
+ "\t\t- events restored to station's input, output, or to GRAND_CENTRAL station\n" +
+ "\t\t- select all events, those matching default condition, or matching user condition\n" +
+ "\t\t- values of integers in selection array\n" +
+ "\t\t- class or library & function of user's matching condition\n\n" +
+
+ "\tb) Statistics - \n" +
+ "\t\t- total number of attachments and their id numbers\n" +
+ "\t\t- current # of events in input list, total # put in input, # tried to put in input\n" +
+ "\t\t- current # of events in output list, total # put in output list\n\n" +
+
+ "3) Processes - on Solaris, local unix processes with attachments are listed by id #\n" +
+ "\t- total # of attachments, list of attachments' ids, unix pid, current heartbeat value\n\n" +
+
+ "4) Attachments - attachments are listed by their id numbers\n" +
+ "\t- name of station attached to, host attachment is running on\n" +
+ "\t- is attachment blocked waiting to read events?\n" +
+ "\t- has attachment been told to quit reading events and return?\n" +
+ "\t- unix pid and process id (non-Java)\n" +
+ "\t- # events currently owned, total #: newly made, gotten, put, and dumped\n\n\n\n" +
+
+ "SETTING AN UPDATE PERIOD\n" +
+ "Each ET system has its information updated at a regular period which can be set " +
+ "by selecting the \"View\" menu item and typing in the period value.\n\n\n\n" +
+
+ "DISCONNECTING AN ET SYSTEM\n" +
+ "Each ET system can be removed from the monitor by selecting the \"Connections\" " +
+ "menu item followed by selecting the \"Disconnect\" item, and then selecting the " +
+ "system to be removed.\n\n\n\n" +
+
+ "CONFIGURATION FILES\n" +
+ "Configuration files can be created, saved, and loaded through the \"File\" menu item. " +
+ "The configuration files are in XML format and use a schema defined in " +
+ "the file \"monitorConfiguration.xsd\". Without going into great detail, configuration " +
+ "files store all current connections and the current state of the application. Colors " +
+ "used in this application, as well as the " +
+ "main window's size and placement, can be set in the configuration file. These particular " +
+ "parameters, however, will only be set in the application if the configuration file is " +
+ "given on the command line (-f or -file). Once the monitor is up and running, loading a " +
+ "configuration file simply adds any additional ET system connections listed there as well " +
+ "as adding items to the \"ET Name\" or \"ET Location\" lists.\n\n" +
+
+ "Setting colors in a configuration file can only be done by hand-editing it. Modifying the colors " +
+ "in the main application can be done by inserting the following lines (without the explanation) " +
+ "in any order, under the \"<graphics>\" element. Simply change the red, green, and blue " +
+ "values (between 0 and 255 inclusive) to suit:\n\n" +
+
+ "\tText on menus, titles, buttons, tabs (default black):\n" +
+ "\t\t<titleColor red=\"0\" green=\"0\" blue=\"0\"/>\n\n" +
+ "\tGeneral background: (default lightGoldenrod2)\n" +
+ "\t\t<backgroundColor red=\"238\" green=\"220\" blue=\"130\"/>\n\n" +
+ "\tSelected tab background (default yellow):\n" +
+ "\t\t<selectedTabColor red=\"255\" green=\"255\" blue=\"0\"/>\n\n" +
+ "\tBehind all tabs background (default cyan):\n" +
+ "\t\t<tabsBackgroundColor red=\"150\" green=\"255\" blue=\"255\"/>\n\n" +
+ "\tText in entry widgets (default black):\n" +
+ "\t\t<textColor red=\"0\" green=\"0\" blue=\"0\"/>\n\n" +
+ "\tText entry widget background (default white):\n" +
+ "\t\t<textBackgroundColor red=\"255\" green=\"255\" blue=\"255\"/>\n\n" +
+
+ "Colors may also be changed in the view of a monitored ET system. To do so, the following " +
+ "lines may be added. HOWEVER, THEY MAY ONLY BE ADDED AT THE END OF EACH \"<etConnection>\" " +
+ "ELEMENT AND ONLY IN THE GIVEN ORDER:\n\n" +
+
+ "\tEvents (default red):\n" +
+ "\t\t<eventColor red=\"255\" green=\"0\" blue=\"0\"/>\n\n" +
+ "\tStations Active (default cyan):\n" +
+ "\t\t<stationColor red=\"0\" green=\"255\" blue=\"255\"/>\n\n" +
+ "\tStations Idle (default pink):\n" +
+ "\t\t<stationIdleColor red=\"255\" green=\"192\" blue=\"203\"/>\n\n" +
+ "\tAttachments (default magenta):\n" +
+ "\t\t<attachmentColor red=\"255\" green=\"0\" blue=\"255\"/>\n\n" +
+ "\tLines between stations and attachments (default black):\n" +
+ "\t\t<lineColor red=\"0\" green=\"0\" blue=\"0\"/>\n\n" +
+ "\tText in stations and attachments (default black):\n" +
+ "\t\t<textColor red=\"0\" green=\"0\" blue=\"0\"/>\n\n" +
+ "\tStation and attachment text background (default white):\n" +
+ "\t\t<textBackgroundColor red=\"255\" green=\"255\" blue=\"255\"/>\n\n" +
+ "\tGraph background (default white):\n" +
+ "\t\t<backgroundColor red=\"255\" green=\"255\" blue=\"255\"/>\n\n" +
+ "\tText of tree widget (default black):\n" +
+ "\t\t<treeTextColor red=\"0\" green=\"0\" blue=\"0\"/>\n\n" +
+ "\tTree widget background (default white):\n" +
+ "\t\t<treeBackgroundColor red=\"255\" green=\"255\" blue=\"255\"/>"
+
+ );
+ return pane;
+ }
+
+
+ private void makeEtOpenWindow() {
+ // widget sizes & spacings
+ int edge1 = 20,
+ edge2 = 10,
+ edge3 = 5,
+ prefWidth = 500,
+ maxWidth = 800,
+ indent = 15,
+ horSpace = 10,
+ verSpace = 10,
+ prefRemBut = 50,
+ maxRemBut = 70,
+ prefHeight1 = 50,
+ maxHeight = 60,
+ prefHeight2 = 40;
+ // convenient sizes
+ int prefHalf = prefWidth / 2 - edge2 - horSpace / 2,
+ maxHalf = maxWidth / 2 - edge2 - horSpace / 2;
+
+ // Several combo boxes use this to filter input.
+ ActionListener al = new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ JComboBox jcb = (JComboBox) e.getSource();
+ String listItem;
+ String selectedItem = (String) jcb.getSelectedItem();
+ int numItems = jcb.getItemCount();
+ boolean addNewItem = true;
+
+ if (selectedItem == null || selectedItem.equals("")) {
+ addNewItem = false;
+ }
+ else if (numItems == 0) {
+ addNewItem = true;
+ }
+ else {
+ for (int i = 0; i < numItems; i++) {
+ listItem = (String) jcb.getItemAt(i);
+ if (listItem.equals(selectedItem) == true) {
+ addNewItem = false;
+ break;
+ }
+ }
+ }
+
+ if (addNewItem) {
+ jcb.addItem(selectedItem);
+ }
+ }
+ };
+
+ // put main panel into one main window
+ JPanel openPanel = new JPanel();
+ openPanel.setBackground(backgroundColor);
+ openPanel.setLayout(new BoxLayout(openPanel, BoxLayout.Y_AXIS));
+ openPanel.setBorder(new EmptyBorder(edge1, edge1, edge1, edge1));
+
+ // setting ET name
+ TitledBorder border1 = new TitledBorder(new EmptyBorder(0, 0, 0, 0),
+ "ET Name",
+ TitledBorder.LEFT,
+ TitledBorder.ABOVE_TOP,
+ MonitorFonts.titleFont,
+ titleColor);
+
+ JPanel p1 = new JPanel();
+ p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS));
+ p1.setBorder(border1);
+ p1.setBackground(backgroundColor);
+ p1.setPreferredSize(new Dimension(prefWidth, prefHeight1 + edge3));
+ p1.setMaximumSize(new Dimension(maxWidth, maxHeight + edge3));
+ p1.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+ etName = new JComboBox();
+ etName.setBackground(textBackgroundColor);
+ etName.setEditable(true);
+ etName.setFont(MonitorFonts.inputFont);
+ etName.setAlignmentX(Component.CENTER_ALIGNMENT);
+ etName.setPreferredSize(new Dimension(prefWidth - indent, prefHeight1));
+ etName.setMaximumSize(new Dimension(maxWidth - indent, maxHeight));
+ etName.addActionListener(al);
+ // Set editable comboBox colors
+ Component c = etName.getEditor().getEditorComponent();
+ c.setBackground(textBackgroundColor);
+ c.setForeground(textColor);
+
+ // button for ET name removal
+ final JButton removeName = new JButton("X");
+ removeName.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ int index = etName.getSelectedIndex();
+ if (index > -1) {
+ etName.removeItemAt(index);
+ }
+ }
+ });
+ removeName.setAlignmentX(Component.LEFT_ALIGNMENT);
+ removeName.setForeground(titleColor);
+ removeName.setBackground(backgroundColor);
+ removeName.setPreferredSize(new Dimension(prefRemBut, prefHeight2));
+ removeName.setMaximumSize(new Dimension(maxRemBut, maxHeight));
+
+ p1.add(Box.createRigidArea(new Dimension(indent, 0)));
+ p1.add(etName);
+ p1.add(removeName);
+
+ // setting ET location
+ TitledBorder border2 = new TitledBorder(new EmptyBorder(0, 0, 0, 0),
+ "ET Location",
+ TitledBorder.LEFT,
+ TitledBorder.ABOVE_TOP,
+ MonitorFonts.titleFont,
+ titleColor);
+
+ JPanel p2 = new JPanel();
+ p2.setLayout(new BoxLayout(p2, BoxLayout.X_AXIS));
[truncated at 1000 lines; 1052 more skipped]
hps-et-java/src/main/java/org/jlab/coda/et/monitorGui
diff -N MonitorConfiguration.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ MonitorConfiguration.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,814 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2002 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.monitorGui;
+
+import java.io.*;
+import java.util.*;
+import java.awt.*;
+import javax.swing.JSplitPane;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.XMLConstants;
+
+import org.jlab.coda.et.*;
+import org.jlab.coda.et.exception.*;
+import org.xml.sax.*;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * A SAX2 ContentHandler.
+ *
+ */
+public class MonitorConfiguration extends DefaultHandler {
+ // Defaults
+ private SAXParser parser;
+ private static boolean setValidation = true;
+ private static boolean setNameSpaces = true;
+ private static boolean setSchemaSupport = true;
+ private static boolean setSchemaFullSupport = true;
+
+ private StringBuffer buffer = new StringBuffer(100);
+ private HashMap<String,Object> dataStorage = new HashMap<String,Object>(100);
+
+ private Monitor monitor;
+ private boolean isColor;
+ private boolean readWindowParametersOnly;
+ private boolean finishedReadingWindowParameters;
+ private String currentElement;
+ private String findMethod;
+ private Color[] mainColors = new Color[6];
+ private Point windowLocation;
+ private Dimension windowSize;
+
+
+ /** Constructor. */
+ public MonitorConfiguration(Monitor mon) {
+ monitor = mon;
+
+ // Use the validating parser
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ Schema schema = null;
+ try {
+ schema = sf.newSchema(new File("monitorConfiguration.xsd"));
+ }
+ catch (SAXException e) {
+ e.printStackTrace();
+ }
+
+ factory.setSchema(schema);
+
+ // Parse the input
+ try {
+ parser = factory.newSAXParser();
+ }
+ catch (ParserConfigurationException e) {
+ e.printStackTrace();
+ }
+ catch (SAXException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+
+ public void setMonitor(Monitor mon) {monitor = mon;}
+
+ // Methods for getting application window & color data from
+ // window parameter reading of config file.
+ public Point getWindowLocation() {return new Point(windowLocation);}
+ public Dimension getWindowSize() {return new Dimension(windowSize);}
+ public Color[] getWindowColors() {return mainColors.clone();}
+
+ // Methods for parsing window & color data from config file.
+ public void loadWindowParameters(File file) throws IOException, SAXException {
+ loadWindowParameters(file.getPath());
+ }
+ public void loadWindowParameters(String fileName) throws IOException, SAXException {
+ File f = new File(fileName);
+
+ readWindowParametersOnly = true;
+ parser.parse(f,this);
+ readWindowParametersOnly = false;
+ finishedReadingWindowParameters = false;
+ return;
+ }
+
+ // Methods for reading the rest of the config information.
+ public void load(String fileName) throws IOException, SAXException {
+ File f = new File(fileName);
+ parser.parse(f, this);
+ }
+ public void load(File file) throws IOException, SAXException {
+ load(file.getPath());
+ }
+
+
+ //=============================
+ // SAX DocumentHandler methods
+ //=============================
+ // Start element.
+ public void startElement(String uri, String local, String qname,
+ Attributes attrs) {
+ // keep track of the current element
+ currentElement = local;
+ // If we're setting a color, its attributes give red, green, & blue.
+ if (local.indexOf("Color") > -1) {
+ try {
+ // Get rgb components.
+ Color c = new Color(Integer.parseInt(attrs.getValue("red")),
+ Integer.parseInt(attrs.getValue("green")),
+ Integer.parseInt(attrs.getValue("blue")));
+ dataStorage.put(currentElement, c);
+ isColor = true;
+ }
+ catch (NumberFormatException ex) {
+ }
+ }
+ // Keep track of method used to find ET system.
+ else if (local.equals("broadcasting") ||
+ local.equals("multicasting") ||
+ local.equals("broadAndMulticasting") ||
+ local.equals("direct") ||
+ local.equals("udpToHost")) {
+ findMethod = currentElement;
+ }
+ }
+
+ // Characters. This may be called more than once for each item.
+ public void characters(char ch[], int start, int length) {
+ if (finishedReadingWindowParameters || ch == null || length == 0) {
+ return;
+ }
+ // put data into a buffer
+ buffer.append(ch, start, length);
+ }
+
+
+ // End element. Note that white space is ignored when validating an element's
+ // value. So, white space gets passed on to the user and must be trimmed off.
+ public void endElement(String uri, String local, String qname) {
+ if (finishedReadingWindowParameters) {
+ return;
+ }
+
+ if (isColor) {
+ isColor = false;
+ }
+ else if (buffer.length() > 0) {
+ // put data (as string) into hash table
+ dataStorage.put(currentElement, buffer.toString());
+ // erase buffer for next element
+ buffer.setLength(0);
+ }
+
+ // adjust GUI parameters
+ if (local.equals("graphics")) {
+ // First, handle case of only reading main application's window's parameters.
+ if (readWindowParametersOnly) {
+ // optional elements
+ if (dataStorage.containsKey("titleColor")) {
+ mainColors[0] = (Color) dataStorage.get("titleColor");
+ }
+ if (dataStorage.containsKey("backgroundColor")) {
+ mainColors[1] = (Color) dataStorage.get("backgroundColor");
+ }
+ if (dataStorage.containsKey("selectedTabColor")) {
+ mainColors[2] = (Color) dataStorage.get("selectedTabColor");
+ }
+ if (dataStorage.containsKey("tabsBackgroundColor")) {
+ mainColors[3] = (Color) dataStorage.get("tabsBackgroundColor");
+ }
+ if (dataStorage.containsKey("textColor")) {
+ mainColors[4] = (Color) dataStorage.get("textColor");
+ }
+ if (dataStorage.containsKey("textBackgroundColor")) {
+ mainColors[5] = (Color) dataStorage.get("textBackgroundColor");
+ }
+
+ // mandatory elements
+ int w = Integer.parseInt(((String) dataStorage.get("width")).trim());
+ int h = Integer.parseInt(((String) dataStorage.get("height")).trim());
+ int x = Integer.parseInt(((String) dataStorage.get("xPosition")).trim());
+ int y = Integer.parseInt(((String) dataStorage.get("yPosition")).trim());
+ windowLocation = new Point(x, y);
+ windowSize = new Dimension(w, h);
+ finishedReadingWindowParameters = true;
+
+ dataStorage.clear();
+ return;
+ }
+
+ // optional elements
+ if (dataStorage.containsKey("fileNameList")) {
+ // Divide list - items separated by white space - into component parts.
+ StringTokenizer tok = new StringTokenizer((String) dataStorage.get("fileNameList"));
+ while (tok.hasMoreTokens()) {
+ monitor.addFileName(tok.nextToken());
+ }
+ }
+ if (dataStorage.containsKey("hostList")) {
+ StringTokenizer tok = new StringTokenizer((String) dataStorage.get("hostList"));
+ while (tok.hasMoreTokens()) {
+ monitor.addHostname(tok.nextToken());
+ }
+ }
+
+ dataStorage.clear();
+ }
+
+ // try to make connection to ET system
+ else if (local.equals("etConnection")) {
+ String etSystem = (String) dataStorage.get("fileName");
+ int period = Integer.parseInt((String) dataStorage.get("period"));
+ int divider = Integer.parseInt((String) dataStorage.get("dividerPosition"));
+ int orientation = JSplitPane.HORIZONTAL_SPLIT;
+ if (((String) dataStorage.get("orientation")).equals("vertical")) {
+ orientation = JSplitPane.VERTICAL_SPLIT;
+ }
+
+ Color[] colors = new Color[10];
+ if (dataStorage.containsKey("stationColor")) {
+ colors[0] = (Color) dataStorage.get("stationColor");
+ }
+ if (dataStorage.containsKey("stationIdleColor")) {
+ colors[1] = (Color) dataStorage.get("stationIdleColor");
+ }
+ if (dataStorage.containsKey("attachmentColor")) {
+ colors[2] = (Color) dataStorage.get("attachmentColor");
+ }
+ if (dataStorage.containsKey("eventColor")) {
+ colors[3] = (Color) dataStorage.get("eventColor");
+ }
+ if (dataStorage.containsKey("lineColor")) {
+ colors[4] = (Color) dataStorage.get("lineColor");
+ }
+ if (dataStorage.containsKey("textColor")) {
+ colors[5] = (Color) dataStorage.get("textColor");
+ }
+ if (dataStorage.containsKey("textBackgroundColor")) {
+ colors[6] = (Color) dataStorage.get("textBackgroundColor");
+ }
+ if (dataStorage.containsKey("backgroundColor")) {
+ colors[7] = (Color) dataStorage.get("backgroundColor");
+ }
+ if (dataStorage.containsKey("treeTextColor")) {
+ colors[8] = (Color) dataStorage.get("treeTextColor");
+ }
+ if (dataStorage.containsKey("treeBackgroundColor")) {
+ colors[9] = (Color) dataStorage.get("treeBackgroundColor");
+ }
+
+ int index = 0, ttl = 0, dummy = 11111;
+ int broadcastPort = 0, multicastPort = 0, port = 0;
+ String host = null;
+ EtSystemOpenConfig config = null;
+
+ try {
+ if (findMethod.equals("broadcasting")) {
+ if (dataStorage.containsKey("location")) {
+ host = (String) dataStorage.get("location");
+ if (host.equals("local")) {
+ host = EtConstants.hostLocal;
+ }
+ else if (host.equals("remote")) {
+ host = EtConstants.hostRemote;
+ }
+ else {
+ host = EtConstants.hostAnywhere;
+ }
+ }
+ else {
+ host = (String) dataStorage.get("host");
+ monitor.addHostname(host);
+ }
+ broadcastPort = Integer.parseInt((String) dataStorage.get("broadcastPort"));
+ // Can dispense with the address list which now only contains "255.255.255.255"
+ StringTokenizer tok = new StringTokenizer((String) dataStorage.get("broadcastAddressList"));
+ String[] addrs = new String[tok.countTokens()];
+ while (tok.hasMoreTokens()) {
+ addrs[index++] = tok.nextToken();
+ }
+ config = new EtSystemOpenConfig(etSystem, broadcastPort, host);
+ }
+ else if (findMethod.equals("multicasting")) {
+ if (dataStorage.containsKey("location")) {
+ host = (String) dataStorage.get("location");
+ if (host.equals("local")) {
+ host = EtConstants.hostLocal;
+ }
+ else if (host.equals("remote")) {
+ host = EtConstants.hostRemote;
+ }
+ else {
+ host = EtConstants.hostAnywhere;
+ }
+ }
+ else {
+ host = (String) dataStorage.get("host");
+ monitor.addHostname(host);
+ }
+ ttl = Integer.parseInt((String) dataStorage.get("ttl"));
+ multicastPort = Integer.parseInt((String) dataStorage.get("multicastPort"));
+ StringTokenizer tok = new StringTokenizer((String) dataStorage.get("multicastAddressList"));
+ String[] addrs = new String[tok.countTokens()];
+ while (tok.hasMoreTokens()) {
+ addrs[index++] = tok.nextToken();
+ }
+
+ int udpPort = EtConstants.broadcastPort;
+ if (dataStorage.containsKey("udpPort")) {
+ udpPort = Integer.parseInt((String) dataStorage.get("udpPort"));
+ }
+ config = new EtSystemOpenConfig(etSystem, host,
+ Arrays.asList(addrs),
+ udpPort, multicastPort, ttl);
+ }
+ else if (findMethod.equals("broadAndMulticasting")) {
+ if (dataStorage.containsKey("location")) {
+ host = (String) dataStorage.get("location");
+ if (host.equals("local")) {
+ host = EtConstants.hostLocal;
+ }
+ else if (host.equals("remote")) {
+ host = EtConstants.hostRemote;
+ }
+ else {
+ host = EtConstants.hostAnywhere;
+ }
+ }
+ else {
+ host = (String) dataStorage.get("host");
+ monitor.addHostname(host);
+ }
+ ttl = Integer.parseInt((String) dataStorage.get("ttl"));
+ broadcastPort = Integer.parseInt((String) dataStorage.get("broadcastPort"));
+ multicastPort = Integer.parseInt((String) dataStorage.get("multicastPort"));
+ StringTokenizer tok = new StringTokenizer((String) dataStorage.get("broadcastAddressList"));
+ String[] bAddrs = new String[tok.countTokens()];
+ while (tok.hasMoreTokens()) {
+ bAddrs[index++] = tok.nextToken();
+ }
+ index = 0;
+ tok = new StringTokenizer((String) dataStorage.get("multicastAddressList"));
+ String[] mAddrs = new String[tok.countTokens()];
+ while (tok.hasMoreTokens()) {
+ mAddrs[index++] = tok.nextToken();
+ }
+ config = new EtSystemOpenConfig(etSystem, host, null,
+ Arrays.asList(mAddrs), true,
+ EtConstants.broadAndMulticast,
+ dummy, broadcastPort, multicastPort, ttl,
+ EtConstants.policyError);
+ }
+ else if (findMethod.equals("direct")) {
+ if (dataStorage.containsKey("location")) {
+ host = (String) dataStorage.get("location");
+ if (host.equals("local")) {
+ host = EtConstants.hostLocal;
+ }
+ }
+ else {
+ host = (String) dataStorage.get("host");
+ monitor.addHostname(host);
+ }
+ port = Integer.parseInt((String) dataStorage.get("tcpPort"));
+ config = new EtSystemOpenConfig(etSystem, host, port);
+ }
+
+ }
+ catch (EtException ex) {
+ // Should never occur. All problems should be caught by schema validation.
+ }
+
+ monitor.addFileName(etSystem);
+ monitor.addEtSystem(config, period, divider, orientation, colors);
+ dataStorage.clear();
+ }
+ }
+
+
+ // Warning.
+ public void warning(SAXParseException ex) {
+ System.err.println("[Warning] "+
+ getLocationString(ex)+": "+
+ ex.getMessage());
+ }
+
+
+ // Error.
+ public void error(SAXParseException ex) throws SAXException {
+ System.err.println("[Error] "+
+ getLocationString(ex)+": "+
+ ex.getMessage());
+ throw ex;
+ }
+
+
+ // Fatal error.
+ public void fatalError(SAXParseException ex) throws SAXException {
+ System.err.println("[Fatal Error] "+
+ getLocationString(ex)+": "+
+ ex.getMessage());
+ throw ex;
+ }
+
+ //===================================
+ // End of SAX DocumentHandler methods
+ //===================================
+
+
+
+ // Returns a string of the location.
+ private String getLocationString(SAXParseException ex) {
+ StringBuffer str = new StringBuffer();
+ String systemId = ex.getSystemId();
+ if (systemId != null) {
+ int index = systemId.lastIndexOf('/');
+ if (index != -1)
+ systemId = systemId.substring(index + 1);
+ str.append(systemId);
+ }
+ str.append(": line ");
+ str.append(ex.getLineNumber());
+ str.append(" :col ");
+ str.append(ex.getColumnNumber());
+
+ return str.toString();
+ }
+
+
+ // Saves data nto a proper xml format configuration file.
+ public void save(File file) throws FileNotFoundException {
+ String fileName = file.getPath();
+ try {
+ FileOutputStream fos = new FileOutputStream(fileName);
+ OutputStreamWriter osw = new OutputStreamWriter(fos, "ASCII");
+
+ StringBuffer text = new StringBuffer(1000);
+
+ // Configuration file is in XML format.
+ text.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
+ text.append("<configuration xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
+ text.append(" xsi:noNamespaceSchemaLocation=\"monitorConfiguration.xsd\">\n\n");
+ text.append(" <graphics>\n <width>");
+ text.append(monitor.getMonitorWidth());
+ text.append("</width>\n <height>");
+ text.append(monitor.getMonitorHeight());
+ text.append("</height>\n <xPosition>");
+ text.append(monitor.getX());
+ text.append("</xPosition>\n <yPosition>");
+ text.append(monitor.getY());
+ text.append("</yPosition>\n");
+
+ // Only put non-default colors into config file.
+ Color monColor = monitor.getTitleColor();
+ if (monColor.getRGB() != monitor.titleColorDefault.getRGB()) {
+ text.append(" <titleColor red=\"");
+ text.append(monColor.getRed());
+ text.append("\" green=\"");
+ text.append(monColor.getGreen());
+ text.append("\" blue=\"");
+ text.append(monColor.getBlue());
+ text.append("\"/>\n");
+ }
+ monColor = monitor.getBackgroundColor();
+ if (monColor.getRGB() != monitor.backgroundColorDefault.getRGB()) {
+ text.append(" <backgroundColor red=\"");
+ text.append(monColor.getRed());
+ text.append("\" green=\"");
+ text.append(monColor.getGreen());
+ text.append("\" blue=\"");
+ text.append(monColor.getBlue());
+ text.append("\"/>\n");
+ }
+ monColor = monitor.getSelectedTabColor();
+ if (monColor.getRGB() != monitor.selectedTabColorDefault.getRGB()) {
+ text.append(" <selectedTabColor red=\"");
+ text.append(monColor.getRed());
+ text.append("\" green=\"");
+ text.append(monColor.getGreen());
+ text.append("\" blue=\"");
+ text.append(monColor.getBlue());
+ text.append("\"/>\n");
+ }
+ monColor = monitor.getTabsBackgroundColor();
+ if (monColor.getRGB() != monitor.tabsBackgroundColorDefault.getRGB()) {
+ text.append(" <tabsBackgroundColor red=\"");
+ text.append(monColor.getRed());
+ text.append("\" green=\"");
+ text.append(monColor.getGreen());
+ text.append("\" blue=\"");
+ text.append(monColor.getBlue());
+ text.append("\"/>\n");
+ }
+ monColor = monitor.getTextBackgroundColor();
+ if (monColor.getRGB() != monitor.textBackgroundColorDefault.getRGB()) {
+ text.append(" <textBackgroundColor red=\"");
+ text.append(monColor.getRed());
+ text.append("\" green=\"");
+ text.append(monColor.getGreen());
+ text.append("\" blue=\"");
+ text.append(monColor.getBlue());
+ text.append("\"/>\n");
+ }
+ monColor = monitor.getTextColor();
+ if (monColor.getRGB() != monitor.textColorDefault.getRGB()) {
+ text.append(" <textColor red=\"");
+ text.append(monColor.getRed());
+ text.append("\" green=\"");
+ text.append(monColor.getGreen());
+ text.append("\" blue=\"");
+ text.append(monColor.getBlue());
+ text.append("\"/>\n");
+ }
+
+ osw.write(text.toString());
+ text.setLength(0);
+
+ // Lists of host and ET names
+ String[] names = monitor.getHostnames();
+ if (names != null) {
+ text.append(" <hostList>");
+ for (int i=0; i < names.length; i++) {
+ text.append("\n ");
+ text.append(names[i]);
+ }
+ text.append("\n </hostList>\n");
+ }
+
+ names = monitor.getFileNames();
+ if (names != null) {
+ text.append(" <fileNameList>");
+ for (int i=0; i < names.length; i++) {
+ text.append("\n ");
+ text.append(names[i]);
+ }
+ text.append("\n </fileNameList>\n");
+ }
+ text.append(" </graphics>\n\n");
+
+ osw.write(text.toString());
+ text.setLength(0);
+
+ // Connections to ET systems
+ String key;
+ EtSystem use=null;
+ EtSystemOpenConfig config;
+ for (Map.Entry<String, EtSystem> entry : monitor.connections.entrySet()) {
+ // Get object with connection info in it.
+ use = entry.getValue();
+ key = entry.getKey();
+ config = use.getConfig();
+
+ text.append(" <etConnection>\n <fileName>");
+ // ET name.
+ text.append(config.getEtName());
+ text.append("</fileName>\n");
+
+ // Method of finding ET system.
+ int method = config.getNetworkContactMethod();
+ if (method == EtConstants.broadcast) {
+ text.append(" <broadcasting>\n");
+ // Location or host?
+ String host = config.getHost();
+ if (host.equals(EtConstants.hostLocal)) {
+ text.append(" <location>local</location>\n");
+ }
+ else if (host.equals(EtConstants.hostRemote)) {
+ text.append(" <location>remote</location>\n");
+ }
+ else if (host.equals(EtConstants.hostAnywhere)) {
+ text.append(" <location>anywhere</location>\n");
+ }
+ else {
+ text.append(" <host>");
+ text.append(host);
+ text.append("</host>\n");
+ }
+ // List of subnet addresses to broadcast on.
+ text.append(" <broadcastAddressList>");
+ text.append("\n 255.255.255.255");
+ text.append("\n </broadcastAddressList>\n <broadcastPort>");
+ text.append(config.getUdpPort());
+ text.append("</broadcastPort>\n </broadcasting>\n");
+ }
+ else if (method == EtConstants.multicast) {
+ text.append(" <multicasting>\n");
+ // Location or host?
+ String host = config.getHost();
+ if (host.equals(EtConstants.hostLocal)) {
+ text.append(" <location>local</location>\n");
+ }
+ else if (host.equals(EtConstants.hostRemote)) {
+ text.append(" <location>remote</location>\n");
+ }
+ else if (host.equals(EtConstants.hostAnywhere)) {
+ text.append(" <location>anywhere</location>\n");
+ }
+ else {
+ text.append(" <host>");
+ text.append(host);
+ text.append("</host>\n");
+ }
+ // List of multicast addresses to multicast on.
+ text.append(" <multicastAddressList>");
+ for (Iterator j=config.getMulticastAddrs().iterator(); j.hasNext();) {
+ text.append("\n ");
+ text.append((String)j.next());
+ }
+ text.append("\n </multicastAddressList>\n <multicastPort>");
+ text.append(config.getMulticastPort());
+ text.append("</multicastPort>\n <ttl>");
+ text.append(config.getTTL());
+ text.append("</ttl>\n </multicasting>\n");
+ }
+ else if (method == EtConstants.broadAndMulticast) {
+ text.append(" <broadAndMulticasting>\n");
+ // Location or host?
+ String host = config.getHost();
+ if (host.equals(EtConstants.hostLocal)) {
+ text.append(" <location>local</location>\n");
+ }
+ else if (host.equals(EtConstants.hostRemote)) {
+ text.append(" <location>remote</location>\n");
+ }
+ else if (host.equals(EtConstants.hostAnywhere)) {
+ text.append(" <location>anywhere</location>\n");
+ }
+ else {
+ text.append(" <host>");
+ text.append(host);
+ text.append("</host>\n");
+ }
+ // List of subnet addresses to broadcast on.
+ text.append(" <broadcastAddressList>");
+ text.append("\n 255.255.255.255");
+ text.append("\n </broadcastAddressList>\n <broadcastPort>");
+ text.append(config.getUdpPort());
+ text.append("</broadcastPort>\n");
+ // List of multicast addresses to multicast on.
+ text.append(" <multicastAddressList>");
+ for (Iterator j=config.getMulticastAddrs().iterator(); j.hasNext();) {
+ text.append("\n ");
+ text.append((String)j.next());
+ }
+ text.append("\n </multicastAddressList>\n <multicastPort>");
+ text.append(config.getMulticastPort());
+ text.append("</multicastPort>\n <ttl>");
+ text.append(config.getTTL());
+ text.append("</ttl>\n </broadAndMulticasting>\n");
+ }
+ else if (method == EtConstants.direct) {
+ text.append(" <direct>\n");
+ String host = config.getHost();
+ if (host.equals(EtConstants.hostLocal)) {
+ text.append(" <location>local</location>\n");
+ }
+ else {
+ text.append(" <host>");
+ text.append(host);
+ text.append("</host>\n");
+ }
+ text.append(" <tcpPort>");
+ text.append(config.getTcpPort());
+ text.append("</tcpPort>\n");
+ text.append(" </direct>\n");
+ }
+ else {
+ text.append(" <udpToHost>\n");
+ String host = config.getHost();
+ if (host.equals(EtConstants.hostLocal)) {
+ text.append(" <location>local</location>\n");
+ }
+ else {
+ text.append(" <host>");
+ text.append(host);
+ text.append("</host>\n");
+ }
+ text.append(" <udpPort>");
+ text.append(config.getUdpPort());
+ text.append("</udpPort>\n");
+ text.append(" </udpToHost>\n");
+ }
+
+ // Update period & splitPane divider position & orientation
+ MonitorSingleSystem singleMonitor = monitor.monitors.get(key);
+ text.append(" <period>");
+ text.append(singleMonitor.getUpdatePeriod());
+ text.append("</period>\n <dividerPosition>");
+ text.append(singleMonitor.getDividerPosition());
+ text.append("</dividerPosition>\n <orientation>");
+ if (singleMonitor.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
+ text.append("horizontal");
+ }
+ else {
+ text.append("vertical");
+ }
+ text.append("</orientation>\n");
+
+ // Only put non-default colors into config file.
+ monColor = singleMonitor.getEventColor();
+ if (monColor.getRGB() != singleMonitor.eventColorDefault.getRGB()) {
+ text.append(" <eventColor red=\"");
+ text.append(monColor.getRed());
+ text.append("\" green=\"");
+ text.append(monColor.getGreen());
+ text.append("\" blue=\"");
+ text.append(monColor.getBlue());
+ text.append("\"/>\n");
+ }
+ monColor = singleMonitor.getStationColor();
+ if (monColor.getRGB() != singleMonitor.stationColorDefault.getRGB()) {
+ text.append(" <stationColor red=\"");
+ text.append(monColor.getRed());
+ text.append("\" green=\"");
+ text.append(monColor.getGreen());
+ text.append("\" blue=\"");
+ text.append(monColor.getBlue());
+ text.append("\"/>\n");
+ }
+ monColor = singleMonitor.getStationIdleColor();
+ if (monColor.getRGB() != singleMonitor.stationIdleColorDefault.getRGB()) {
+ text.append(" <stationIdleColor red=\"");
+ text.append(monColor.getRed());
+ text.append("\" green=\"");
+ text.append(monColor.getGreen());
+ text.append("\" blue=\"");
+ text.append(monColor.getBlue());
+ text.append("\"/>\n");
+ }
+ monColor = singleMonitor.getAttachmentColor();
+ if (monColor.getRGB() != singleMonitor.attachColorDefault.getRGB()) {
+ text.append(" <attachmentColor red=\"");
+ text.append(monColor.getRed());
+ text.append("\" green=\"");
+ text.append(monColor.getGreen());
+ text.append("\" blue=\"");
+ text.append(monColor.getBlue());
+ text.append("\"/>\n");
+ }
+ monColor = singleMonitor.getLineColor();
+ if (monColor.getRGB() != singleMonitor.lineColorDefault.getRGB()) {
+ text.append(" <lineColor red=\"");
+ text.append(monColor.getRed());
+ text.append("\" green=\"");
+ text.append(monColor.getGreen());
+ text.append("\" blue=\"");
+ text.append(monColor.getBlue());
+ text.append("\"/>\n");
+ }
+ monColor = singleMonitor.getTextColor();
+ if (monColor.getRGB() != singleMonitor.textColorDefault.getRGB()) {
+ text.append(" <textColor red=\"");
+ text.append(monColor.getRed());
+ text.append("\" green=\"");
+ text.append(monColor.getGreen());
+ text.append("\" blue=\"");
+ text.append(monColor.getBlue());
+ text.append("\"/>\n");
+ }
+ monColor = singleMonitor.getTextBackgroundColor();
+ if (monColor.getRGB() != singleMonitor.textBackgroundColorDefault.getRGB()) {
+ text.append(" <textBackgroundColor red=\"");
+ text.append(monColor.getRed());
+ text.append("\" green=\"");
+ text.append(monColor.getGreen());
+ text.append("\" blue=\"");
+ text.append(monColor.getBlue());
+ text.append("\"/>\n");
+ }
+
+ text.append(" </etConnection>\n\n");
+ osw.write(text.toString());
+ text.setLength(0);
+ }
+
+ text.append("</configuration>\n");
+
+ osw.write(text.toString());
+ osw.close();
+ fos.close();
+ }
+ catch (UnsupportedEncodingException ex) {}
+ catch (IOException ex) {}
+ }
+
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/monitorGui
diff -N MonitorFonts.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ MonitorFonts.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2002 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.monitorGui;
+
+import java.lang.*;
+import java.awt.*;
+
+public class MonitorFonts {
+ // cannot construct object
+ private MonitorFonts () {
+ }
+
+ private static final Font default30 = new Font((String)null, Font.BOLD, 30);
+ private static final Font default16 = new Font((String)null, Font.BOLD, 16);
+ private static final Font default14 = new Font((String)null, Font.BOLD, 14);
+ private static final Font default12 = new Font((String)null, Font.PLAIN, 12);
+
+ public static final Font titleFont = default16;
+ public static final Font inputFont = default14;
+ public static final Font helpFont = default12;
+ public static final Font treeFont = default12;
+ public static final Font graphFont = null;
+ public static final Font buttonTabMenuFont = default14;
+}
hps-et-java/src/main/java/org/jlab/coda/et/monitorGui
diff -N MonitorSingleSystem.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ MonitorSingleSystem.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,1826 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2002 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.monitorGui;
+
+import java.lang.*;
+import java.io.*;
+import java.awt.*;
+import java.awt.geom.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.tree.*;
+
+import org.jlab.coda.et.*;
+import org.jlab.coda.et.data.*;
+import org.jlab.coda.et.exception.*;
+import com.loox.jloox.*;
+import com.loox.jloox.layout.*;
+
+/**
+ * This class implements a view of a single ET system.
+ *
+ * @author Carl Timmer
+ */
+
+public class MonitorSingleSystem {
+ // general stuff
+ private int updatePeriod; // in seconds
+ private int dividerPosition, graphHeight, orientation;
+ private double attWidth, stationWidth, stationGap;
+ private String key;
+ private EtSystem sys;
+ private AllData data;
+ private boolean initialized, updated;
+ private boolean isSolaris, isJava, isLinux;
+ private boolean debug = false;
+
+ // rate stuff
+ private long rate, prevGcOut, time1, time2, updateTime;
+ private final JSplitPane splitPane;
+ private JScrollPane graphPane;
+
+ // tree stuff
+ private final JTree tree;
+ private final DefaultTreeModel treeModel;
+
+ // JLoox widgets
+ private final LxView view;
+ private final LxGraph graph;
+ private final LxAlignLayout layout;
+ private final LxLink mainLink1, mainLink2;
+
+ // nodes
+ private final DefaultMutableTreeNode topNode;
+ private final DefaultMutableTreeNode systemNode;
+ private final DefaultMutableTreeNode systemStaticNode;
+ private final DefaultMutableTreeNode systemDynamicNode;
+ private final DefaultMutableTreeNode stationNode;
+ private final DefaultMutableTreeNode attachNode;
+ private final DefaultMutableTreeNode processNode;
+
+ // object storage
+ private final HashMap stations;
+ private final HashMap attachments;
+ // private final HashMap stationIcons;
+ private final HashMap attachIcons;
+ private final LinkedList stationManagers;
+ private final LinkedList parallelManagers;
+
+ // Default colors
+ public final Color stationColorDefault = Color.cyan;
+ public final Color stationIdleColorDefault = Color.pink;
+ public final Color attachColorDefault = new Color(255, 200 , 255);
+ public final Color eventColorDefault = Color.red;
+ public final Color lineColorDefault = Color.black;
+ public final Color textColorDefault = Color.black;
+ public final Color textBackgroundColorDefault = Color.white;
+ public final Color backgroundColorDefault = Color.white;
+ public final Color treeTextColorDefault = Color.black;
+ public final Color treeBackgroundColorDefault = Color.white;
+ // Colors used
+ private Color stationColor = stationColorDefault;
+ private Color stationIdleColor = stationIdleColorDefault;
+ private Color attachColor = attachColorDefault;
+ private Color eventColor = eventColorDefault;
+ private Color lineColor = lineColorDefault;
+ private Color textColor = textColorDefault;
+ private Color textBackgroundColor = textBackgroundColorDefault;
+ private Color backgroundColor = backgroundColorDefault;
+ private Color treeTextColor = treeTextColorDefault;
+ private Color treeBackgroundColor = treeBackgroundColorDefault;
+
+ // Define constants
+ public static final boolean HORIZONTAL = true;
+ public static final boolean VERTICAL = false;
+
+ // class to hold flow data needed for graphical station layout
+ class StationFlowData {
+ int flowMode;
+ boolean isHead;
+ LxAlignLayout parentLayout;
+ }
+ // class to hold link data needed for graphical station drawing
+ class StationLinkData {
+ LxLink link1;
+ LxLink link2;
+ public StationLinkData(LxLink l1) {
+ link1 = l1;
+ }
+ public StationLinkData(LxLink l1, LxLink l2) {
+ link1 = l1;
+ link2 = l2;
+ }
+ }
+
+ // Constructor
+ public MonitorSingleSystem(EtSystem use, JTabbedPane tabbedPane,
+ int period) {
+ this(use, tabbedPane, period, tabbedPane.getWidth()/2,
+ JSplitPane.HORIZONTAL_SPLIT, null);
+ }
+
+ public MonitorSingleSystem(EtSystem use, JTabbedPane tabbedPane,
+ int period, int divider,
+ int orient, Color[] colors) {
+ sys = use;
+ data = new AllData();
+ updatePeriod = period;
+ dividerPosition = divider;
+
+ if (colors != null) {
+ if (colors[0] != null) stationColor = colors[0];
+ if (colors[1] != null) stationIdleColor = colors[1];
+ if (colors[2] != null) attachColor = colors[2];
+ if (colors[3] != null) eventColor = colors[3];
+ if (colors[4] != null) lineColor = colors[4];
+ if (colors[5] != null) textColor = colors[5];
+ if (colors[6] != null) textBackgroundColor = colors[6];
+ if (colors[7] != null) backgroundColor = colors[7];
+ if (colors[8] != null) treeTextColor = colors[8];
+ if (colors[9] != null) treeBackgroundColor = colors[9];
+ }
+
+ // Create unique name for this ET system - used as key in
+ // Monitor's hash tables.
+ EtSystemOpenConfig config = sys.getConfig();
+ if (sys.getHost().indexOf(".") < 0) {
+ key = new String(config.getEtName() + " (" + sys.getHost() + ")");
+ }
+ else {
+ key = new String(config.getEtName() +
+ " (" + sys.getHost().substring(0, sys.getHost().indexOf(".")) + ")");
+ }
+
+ // Create static tree nodes.
+ topNode = new DefaultMutableTreeNode(key);
+ systemNode = new DefaultMutableTreeNode("System");
+ systemStaticNode = new DefaultMutableTreeNode("Static Info");
+ systemDynamicNode = new DefaultMutableTreeNode("Dynamic Info");
+ stationNode = new DefaultMutableTreeNode("Stations");
+ attachNode = new DefaultMutableTreeNode("Attachments");
+ processNode = new DefaultMutableTreeNode("Proceses");
+ topNode.add(systemNode);
+ systemNode.add(systemStaticNode);
+ systemNode.add(systemDynamicNode);
+ topNode.add(stationNode);
+ topNode.add(attachNode);
+
+ // Create a tree that allows one selection at a time.
+ treeModel = new DefaultTreeModel(topNode);
+ tree = new JTree(treeModel);
+ tree.setFont(MonitorFonts.treeFont);
+ tree.setBackground(treeBackgroundColor);
+ tree.setForeground(treeTextColor);
+ tree.setDoubleBuffered(true);
+ tree.setLargeModel(true);
+ tree.getSelectionModel().setSelectionMode
+ (TreeSelectionModel.SINGLE_TREE_SELECTION);
+ tree.putClientProperty("JTree.lineStyle", "Angled");
+ // Get rid of tree's leaf icon.
+ DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
+ renderer.setLeafIcon(null);
+ renderer.setBackgroundNonSelectionColor(treeBackgroundColor);
+ renderer.setTextNonSelectionColor(treeTextColor);
+ tree.setCellRenderer(renderer);
+
+ // Create the scroll pane and add the tree to it.
+ JScrollPane treePane = new JScrollPane(tree);
+
+ // Graphics panel
+ graph = new LxGraph();
+ // Make graph visible
+ view = (LxView)graph.addView();
+ // Allow user to interact with the objects in EDITOR_MODE
+ view.setEditMode(LxView.STANDARD_MODE);
+ if (debug) {
+ view.setEditMode(LxView.EDITOR_MODE);
+ }
+ // Allow smoother graphics
+ view.setAntialiasingActivated(true);
+ view.setDoubleBuffered(true);
+ // Scrollbars appear when smaller than preferred size.
+ // The preferred width must be reset according to the
+ // number & size of station graphics.
+ graphHeight = 304;
+ view.setPreferredSize(new Dimension(500, graphHeight));
+ view.setBackground(backgroundColor);
+
+ // Create scroll pane and add graph to it.
+ graphPane = new JScrollPane();
+ graphPane.setViewportView(view);
+
+ // Add the split pane to this frame.
+ orientation = orient;
+ splitPane = new JSplitPane(orient);
+ splitPane.setLeftComponent(treePane);
+ splitPane.setRightComponent(graphPane);
+ // Ignored in some releases of Swing. bug 4101306
+ splitPane.setDividerLocation(dividerPosition);
+ // Workaround for bug 4101306:
+ // treePane.setPreferredSize(new Dimension(100, 100));
+ splitPane.setPreferredSize(new Dimension(1100, 700));
+
+ // Add to main window's tabbed pane
+ tabbedPane.addTab(key, null, splitPane, "monitored ET system");
+
+ // JLoox layout of graphics
+ layout = new LxAlignLayout(new Rectangle2D.Double(0., 0., 600., (double)graphHeight));
+ layout.setOrder(LxAlignLayout.LIST_ORDER);
+ layout.setOrientation(LxAlignLayout.HORIZONTAL);
+ layout.setAlignAxisMethod(LxAlignLayout.EVEN_USE_SIZE_METHOD);
+ layout.setNormalAxisMethod(LxAlignLayout.LEFT_TOP_METHOD);
+ layout.setVisible(true);
+ if (debug) {
+ graph.add(layout);
+ }
+
+ // Store objects for future use (more efficient
+ // than always recreating objects)
+ int size1 = EtConstants.defaultStationsMax,
+ size2 = EtConstants.defaultAttsMax;
+ try {
+ size1 = sys.getStationsMax();
+ size2 = sys.getAttachmentsMax();
+ }
+ catch (IOException ex) {
+ }
+ catch (EtException ex) {
+ }
+
+ float loadfactor = 0.75F;
+ stations = new HashMap(size1, loadfactor);
+ attachments = new HashMap(size2, loadfactor);
+ //stationIcons = new HashMap(size1, loadfactor);
+ attachIcons = new HashMap(size2, loadfactor);
+ stationManagers = new LinkedList();
+ parallelManagers = new LinkedList();
+ mainLink1 = new LxLink();
+ mainLink2 = new LxLink();
+ mainLink1.setLineArrow(LxArrowElement.ARROW_END);
+ mainLink1.setLineThickness(2.f);
+ mainLink1.setLineColor(lineColor);
+ mainLink2.setLineArrow(LxArrowElement.ARROW_MIDDLE);
+ mainLink2.setLineThickness(2.f);
+ mainLink2.setLineColor(lineColor);
+ mainLink1.setName("link1");
+ mainLink2.setName("link2");
+ }
+
+
+ // Setters, getters, etc.
+ public void setOrientation(int orient) {
+ if (orient == orientation) {
+ return;
+ }
+ splitPane.setOrientation(orient);
+
+ if (orient == JSplitPane.HORIZONTAL_SPLIT) {
+ splitPane.setDividerLocation(dividerPosition);
+ orientation = JSplitPane.HORIZONTAL_SPLIT;
+ }
+ else {
+ // Give bottom window just enough room to view graph
+ // unless the window is too small. In that case split it.
+ int height = splitPane.getHeight();
+ height = (height < 2*(graphHeight+50)) ? height/2 : height-(graphHeight + 50);
+ splitPane.setDividerLocation(height);
+ orientation = JSplitPane.VERTICAL_SPLIT;
+ }
+ splitPane.updateUI();
+ }
+
+ public int getOrientation() {return orientation;}
+
+ public boolean timeToUpdate() {
+ long currentTime = System.currentTimeMillis();
+ if ((currentTime - updateTime) > 1000*updatePeriod) {
+ return true;
+ }
+ return false;
+ }
+
+ public void setUpdatePeriod(int period) {
+ updatePeriod = (period < 1) ? 1 : period;
+ }
+
+ public int getUpdatePeriod() {return updatePeriod;}
+ public int getDividerPosition() {return splitPane.getDividerLocation();}
+ public Component getDisplayPane() {return splitPane;}
+ public void treeDidChange() {tree.treeDidChange();}
+ public void updateUI() {tree.updateUI();}
+ public boolean isInitialized() {return initialized;}
+ public boolean isUpdated() {return updated;}
+ public DefaultMutableTreeNode getNode() {return topNode;}
+ public void getData() throws EtException, IOException {
+ data = sys.getData();
+ }
+ public void close() {sys.close();}
+ public String getKey() {return key;}
+
+ public Color getEventColor() {return new Color(eventColor.getRGB());}
+ public Color getStationColor() {return new Color(stationColor.getRGB());}
+ public Color getStationIdleColor() {return new Color(stationIdleColor.getRGB());}
+ public Color getAttachmentColor() {return new Color(attachColor.getRGB());}
+ public Color getLineColor() {return new Color(lineColor.getRGB());}
+ public Color getTextColor() {return new Color(textColor.getRGB());}
+ public Color getTextBackgroundColor() {return new Color(textBackgroundColor.getRGB());}
+
+
+ public void staticDisplay()
+ {
+ int end = 499;
+ StringBuffer str = new StringBuffer(500);
+
+ // Display static system data
+ str.append("Host = ");
+ str.append(sys.getHost());
+ int lang = sys.getLanguage();
+ if (lang != EtConstants.langJava) {
+ str.append(", language = C, pid = ");
+ str.append(data.sysData.getMainPid());
+ // processes exist on Solaris only
+ if (data.sysData.getShare() == EtConstants.mutexShare) {
+ isSolaris = true;
+ topNode.add(processNode);
+ }
+ else {
+ isLinux = true;
+ }
+ }
+ else {
+ isJava = true;
+ str.append(", language = Java");
+ }
+ if (data.sysData.isBit64()) {
+ str.append(", bits = 64");
+ }
+ else {
+ str.append(", bits = 32");
+
+ }
+ systemStaticNode.add(new DefaultMutableTreeNode(str.toString()));
+
+ str.delete(0, end);
+ str.append("Ports: tcp = ");
+ str.append(data.sysData.getTcpPort());
+ str.append(", udp = ");
+ str.append(data.sysData.getUdpPort());
+ str.append(", mcast = ");
+ str.append(data.sysData.getMulticastPort());
+ systemStaticNode.add(new DefaultMutableTreeNode(str.toString()));
+
+ str.delete(0, end);
+ str.append("Events: total = ");
+ str.append(data.sysData.getEvents());
+ str.append(", size = ");
+ str.append(data.sysData.getEventSize());
+ str.append(" bytes, temps = ");
+ str.append(data.sysData.getTempsMax());
+ systemStaticNode.add(new DefaultMutableTreeNode(str.toString()));
+
+ str.delete(0, end);
+ str.append("Max #: stations = ");
+ str.append(data.sysData.getStationsMax());
+ str.append(", attachments = ");
+ str.append(data.sysData.getAttachmentsMax());
+ if (isSolaris) {
+ str.append(", processes = ");
+ str.append(data.sysData.getProcessesMax());
+ }
+ systemStaticNode.add(new DefaultMutableTreeNode(str.toString()));
+
+ str.delete(0, end);
+ if (data.sysData.getInterfaces() > 0) {
+ str.append("Network interfaces: ");
+ int limit = data.sysData.getInterfaces();
+ for (int i=0; i < limit; i++) {
+ str.append(data.sysData.getInterfaceAddresses()[i]);
+ if (i == limit-1) break;
+ str.append(", ");
+ }
+ }
+ else {
+ str.append("network interfaces(0): none");
+ }
+ systemStaticNode.add(new DefaultMutableTreeNode(str.toString()));
+
+ if (data.sysData.getMulticasts() > 0) {
+ str.delete(0, end);
+ str.append("Multicast addresses: ");
+ int limit = data.sysData.getMulticasts();
+ for (int i=0; i < limit; i++) {
+ str.append(data.sysData.getMulticastAddresses()[i]);
+ if (i == limit-1) break;
+ str.append(", ");
+ }
+ systemStaticNode.add(new DefaultMutableTreeNode(str.toString()));
+ }
+
+ initialized = true;
+ return;
+ }
+
+
+ public void updateDisplay()
+ {
+ int end = 499;
+ int[] kids3 = {0, 1, 2}, kids4 = {1, 2, 3, 4};
+ int[] kids6 = {1, 2, 3, 4, 5, 6};
+ Integer attId;
+ boolean blocking=false, isNewNode=false;
+ String statName;
+ StringBuffer str = new StringBuffer(end+1);
+ DefaultMutableTreeNode node = null, leaf = null;
+ DefaultMutableTreeNode statsNode = null, configNode = null;
+ // Update system info
+
+ // Event rate
+ if (!updated) {
+ time1 = System.currentTimeMillis();
+ str.append("Event rate = ");
+ str.append(rate);
+ str.append(" Hz");
+ systemDynamicNode.add(new DefaultMutableTreeNode(str.toString()));
+ }
+
+
+ str.delete(0, end);
+ str.append("Events owned by: ");
+ str.append(" sys (");
+ str.append(data.sysData.getEventsOwned());
+ str.append("), atts ");
+ for (int i=0; i < data.attData.length; i++) {
+ str.append(data.attData[i].getId());
+ str.append("(");
+ str.append(data.attData[i].getEventsOwned());
+ str.append(")");
+ if (i == data.attData.length - 1) break;
+ str.append(", ");
+ }
+ if (updated) {
+ leaf = systemDynamicNode.getFirstLeaf().getNextLeaf();
+ leaf.setUserObject(str.toString());
+ }
+ else {
+ systemDynamicNode.add(new DefaultMutableTreeNode(str.toString()));
+ }
+
+ // idle stations
+ str.delete(0, end);
+ str.append("Idle stations: ");
+ boolean gotNone = true;
+ for (int i=0; i < data.statData.length; i++) {
+ if (data.statData[i].getStatus() == EtConstants.stationIdle) {
+ str.append(data.statData[i].getName());
+ str.append(", ");
+ gotNone = false;
+ }
+ }
+ if (gotNone) {
+ str.append("none");
+ }
+ if (updated) {
+ leaf = leaf.getNextLeaf();
+ leaf.setUserObject(str.toString());
+ }
+ else {
+ systemDynamicNode.add(new DefaultMutableTreeNode(str.toString()));
+ }
+
+
+ // stations linked list
+ str.delete(0, end);
+ str.append("All stations: ");
+ for (int i=0; i < data.statData.length; i++) {
+ str.append(data.statData[i].getName());
+ if (i == data.statData.length - 1) break;
+ str.append(", ");
+ }
+ if (updated) {
+ leaf = leaf.getNextLeaf();
+ leaf.setUserObject(str.toString());
+ }
+ else {
+ systemDynamicNode.add(new DefaultMutableTreeNode(str.toString()));
+ }
+
+ str.delete(0, end);
+ str.append("Stations =");
+ str.append(data.sysData.getStations());
+ str.append(", attachments = ");
+ str.append(data.sysData.getAttachments());
+ str.append(", temp events = ");
+ str.append(data.sysData.getTemps());
+ if (updated) {
+ leaf = leaf.getNextLeaf();
+ leaf.setUserObject(str.toString());
+ }
+ else {
+ systemDynamicNode.add(new DefaultMutableTreeNode(str.toString()));
+ }
+
+ if (!isJava) {
+ str.delete(0, end);
+ str.append("Processes = ");
+ str.append(data.sysData.getProcesses());
+ str.append(", hearbeat = ");
+ str.append(data.sysData.getHeartbeat());
+ if (updated) {
+ leaf = leaf.getNextLeaf();
+ leaf.setUserObject(str.toString());
+ }
+ else {
+ systemDynamicNode.add(new DefaultMutableTreeNode(str.toString()));
+ }
+
+ // mutexes
+ str.delete(0, end);
+ str.append("Locked mutexes: ");
+ if (data.sysData.getMutex() == EtConstants.mutexLocked)
+ str.append("sys, ");
+ if (data.sysData.getStatMutex() == EtConstants.mutexLocked)
+ str.append("stat, ");
+ if (data.sysData.getStatAddMutex() == EtConstants.mutexLocked)
+ str.append("add_stat, ");
+
+ for (int i=0; i < data.statData.length; i++) {
+ if (data.statData[i].getMutex() == EtConstants.mutexLocked) {
+ str.append(data.statData[i].getName());
+ str.append(", ");
+ }
+ if (data.statData[i].getInListMutex() == EtConstants.mutexLocked) {
+ str.append(data.statData[i].getName());
+ str.append("-in, ");
+ }
+ if (data.statData[i].getOutListMutex() == EtConstants.mutexLocked) {
+ str.append(data.statData[i].getName());
+ str.append("-out, ");
+ }
+ }
+ if (updated) {
+ leaf = systemDynamicNode.getLastLeaf();
+ leaf.setUserObject(str.toString());
+ treeModel.nodesChanged(systemDynamicNode, kids6);
+ }
+ else {
+ systemDynamicNode.add(new DefaultMutableTreeNode(str.toString()));
+ }
+ }
+ else if (updated) {
+ treeModel.nodesChanged(systemDynamicNode, kids4);
+ }
+
+ // Update station info
+
+ // first remove stations not in current list
+ int numStations = data.statData.length;
+ oldList: for (Iterator i=stations.keySet().iterator(); i.hasNext();) {
+ statName = (String) i.next();
+ newList: for (int j=0; j < numStations; j++) {
+ if (statName.equals(data.statData[j].getName())) {
+ continue oldList;
+ }
+ }
+//System.out.println("Removing node for station " + statName);
+ node = (DefaultMutableTreeNode) stations.get(statName);
+ treeModel.removeNodeFromParent(node);
+ i.remove();
+ }
+
+ // create new stations and update existing stations
+ for (int i=0; i < numStations; i++) {
+
+ // Get station name & find its node object if there is one,
+ // else make a new node and store it in the hash table
+ statName = data.statData[i].getName();
+ if (stations.containsKey(statName)) {
+ isNewNode = false;
+ node = (DefaultMutableTreeNode) stations.get(statName);
+//System.out.println("Node " + node + " has got " + node.getChildCount() + " children");
+ configNode = (DefaultMutableTreeNode)node.getFirstChild();
+ statsNode = (DefaultMutableTreeNode)node.getLastChild();
+//System.out.println("Child 1 = " + configNode);
+//System.out.println("Child 2 = " + statsNode);
+ }
+ else {
+//System.out.println("Adding node for station " + statName);
+ isNewNode = true;
+ node = new DefaultMutableTreeNode(statName);
+ configNode = new DefaultMutableTreeNode("Configuration");
+ statsNode = new DefaultMutableTreeNode("Status");
+ node.add(configNode);
+ node.add(statsNode);
+ stations.put(statName, node);
+ // wait for all "node" changes before inserting into tree
+ }
+
+ // station config (skip GC as it never changes)
+ if ((i != 0) || isNewNode ) {
+ str.delete(0, end);
+ if (data.statData[i].getFlowMode() == EtConstants.stationSerial) {
+ str.append("Serial, ");
+ }
+ else {
+ str.append("Parallel, ");
+ }
+
+ if (data.statData[i].getBlockMode() == EtConstants.stationBlocking) {
+ str.append("blocking, ");
+ blocking = true;
+ str.append("prescale = ");
+ str.append(data.statData[i].getPrescale());
+ str.append(", (cue = ");
+ str.append(data.statData[i].getCue());
+ str.append(")");
+ }
+ else {
+ str.append("nonblocking, ");
+ blocking = false;
+ str.append("cue = ");
+ str.append(data.statData[i].getCue());
+ str.append(", (prescale = ");
+ str.append(data.statData[i].getPrescale());
+ str.append(")");
+ }
+
+ if (isNewNode) {
+//System.out.println("Add first leaf to config node");
+ configNode.add(new DefaultMutableTreeNode(str.toString()));
+ }
+ else {
+//System.out.println("Config has got " + configNode.getLeafCount() + " # of leaves");
+ leaf = configNode.getFirstLeaf();
+//System.out.println("First config leaf = " + leaf);
+ leaf.setUserObject(str.toString());
+ }
+
+
+ str.delete(0, end);
+ if (data.statData[i].getUserMode() == EtConstants.stationUserMulti) {
+ str.append("Users = multi");
+ }
+ else {
+ str.append("Users = ");
+ str.append(data.statData[i].getUserMode());
+ }
+
+ if (data.statData[i].getRestoreMode() == EtConstants.stationRestoreOut)
+ str.append(", restore = out, ");
+ else if (data.statData[i].getRestoreMode() == EtConstants.stationRestoreIn)
+ str.append(", restore = in, ");
+ else
+ str.append(", restore = GC, ");
+
+ if (data.statData[i].getSelectMode() == EtConstants.stationSelectAll)
+ str.append("select = all");
+ else if (data.statData[i].getSelectMode() == EtConstants.stationSelectMatch)
+ str.append("select = match");
+ else if (data.statData[i].getSelectMode() == EtConstants.stationSelectUser)
+ str.append("select = user");
+ else if (data.statData[i].getSelectMode() == EtConstants.stationSelectRRobin)
+ str.append("select = rrobin");
+ else
+ str.append("select = equalcue");
+
+ if (isNewNode) {
+//System.out.println("Add second leaf to config node");
+ configNode.add(new DefaultMutableTreeNode(str.toString()));
+ }
+ else {
+ leaf = leaf.getNextLeaf();
+//System.out.println("Next config leaf = " + leaf);
+ leaf.setUserObject(str.toString());
+ }
+
+
+ str.delete(0, end);
+ str.append("Select words: ");
+ for (int j=0; j < EtConstants.stationSelectInts; j++) {
+ str.append(data.statData[i].getSelect()[j]);
+ if (j == EtConstants.stationSelectInts - 1) break;
+ str.append(", ");
+ }
+ if (isNewNode) {
+//System.out.println("Add third leaf to config node");
+ configNode.add(new DefaultMutableTreeNode(str.toString()));
+ }
+ else {
+ leaf = leaf.getNextLeaf();
+//System.out.println("Next config leaf = " + leaf);
+ leaf.setUserObject(str.toString());
+ }
+
+ // Select mode never changes after station creation,
+ // but station can be removed and then recreated with
+ // a new configuration (in less time than it takes to
+ // update).
+ if (data.statData[i].getSelectMode() == EtConstants.stationSelectUser) {
+ str.delete(0, end);
+ if (isJava) {
+ str.append("Class = ");
+ str.append(data.statData[i].getSelectClass());
+ }
+ else {
+ str.append("Function = ");
+ str.append(data.statData[i].getSelectFunction());
+ str.append(", library = ");
+ str.append(data.statData[i].getSelectLibrary());
+ }
+ if (isNewNode) {
+//System.out.println("Add fourth leaf to config node");
+ configNode.add(new DefaultMutableTreeNode(str.toString()));
+ }
+ else {
+ leaf = leaf.getNextLeaf();
+//System.out.println("Next config leaf = " + leaf);
+ leaf.setUserObject(str.toString());
+ }
+ }
+
+ if (!isNewNode) {
+ treeModel.nodesChanged(configNode, kids3);
+ }
+
+
+ } // if not GC
+
+
+
+ // statistical station info
+
+ str.delete(0, end);
+ if (data.statData[i].getStatus() == EtConstants.stationIdle) {
+ str.append("Idle, ");
+ }
+ else {
+ str.append("Active, ");
+ }
+ str.append("attachments: total = ");
+ str.append(data.statData[i].getAttachments());
+ str.append(", ids = ");
+ int limit = data.statData[i].getAttachments();
+ for (int j=0; j < limit; j++) {
+ str.append(data.statData[i].getAttachmentIds()[j]);
+ if (j == limit - 1) break;
+ str.append(", ");
+ }
+
+ if (isNewNode) {
+//System.out.println("Add first leaf to statistics");
+ statsNode.add(new DefaultMutableTreeNode(str.toString()));
+ }
+ else {
+//System.out.println("Statistics has got " + statsNode.getLeafCount() + " # of leaves");
+ leaf = statsNode.getFirstLeaf();
+//System.out.println("First statistics leaf = " + leaf);
+ leaf.setUserObject(str.toString());
+ }
+
+ str.delete(0, end);
+ str.append("Input events: ");
+ str.append(data.statData[i].getInListCount());
+ str.append(", total = ");
+ str.append(data.statData[i].getInListIn());
+ // if blocking station and not grandcentral ...
+ if (blocking && (data.statData[i].getId() != 0)) {
+ str.append(", try = ");
+ str.append(data.statData[i].getInListTry());
+ }
+ // helps reduce widget flashing
+ str.append(" ");
+
+ if (isNewNode) {
+//System.out.println("Add second leaf to statisics");
+ statsNode.add(new DefaultMutableTreeNode(str.toString()));
+ }
+ else {
+ leaf = leaf.getNextLeaf();
+//System.out.println("Next statistics leaf = " + leaf);
+ leaf.setUserObject(str.toString());
+ }
+
+ str.delete(0, end);
+ str.append("Output events: ");
+ str.append(data.statData[i].getOutListCount());
+ str.append(", total = ");
+ str.append(data.statData[i].getOutListOut());
+ str.append(" ");
+
+ if (isNewNode) {
+//System.out.println("Add third leaf to statisics");
+ statsNode.add(new DefaultMutableTreeNode(str.toString()));
+ // add new station to main tree
+ treeModel.insertNodeInto(node, stationNode, i);
+ }
+ else {
+ leaf = leaf.getNextLeaf();
+//System.out.println("Next statistics leaf = " + leaf);
+ //treeModel.valueForPathChanged(new TreePath(leaf), str.toString());
+ leaf.setUserObject(str.toString());
+ treeModel.nodesChanged(statsNode, kids3);
+ }
+
+ // keep track of grandcentral data rate
+ if ((i==0) && (updated)) {
+ long gcOut = data.statData[i].getOutListOut();
+ time2 = System.currentTimeMillis();
+ rate = ((1000 * (gcOut - prevGcOut))/(time2-time1));
+ prevGcOut = gcOut;
+ time1 = time2;
+ str.delete(0, end);
+ str.append("Event rate = ");
+ str.append(rate);
+ str.append(" Hz");
+ leaf = systemDynamicNode.getFirstLeaf();
+ leaf.setUserObject(str.toString());
+ treeModel.nodeChanged(leaf);
+ }
+ } // for (int i=0; i < numStations; i++) {
+
+ // User processes exist on Solaris only
+ if (isSolaris) {
+ // Processes are only leaves on the tree, so reuse
+ // any that are there, delete or add to suit.
+
+ int numProcs = data.procData.length;
+ int numLeaves = processNode.getChildCount();
+ int leafCounter = numLeaves;
+
+ if (numProcs > 0) {
+ for (int i=0; i < numProcs; i++) {
+ str.delete(0, end);
+ if (data.procData[i].getAttachments() < 1) {
+ str.append("Id = ");
+ str.append(data.procData[i].getId());
+ str.append(", no attachments, ");
+ }
+ else {
+ str.append("Id = ");
+ str.append(data.procData[i].getId());
+ str.append(", ");
+ str.append(data.procData[i].getAttachments());
+ str.append(" attachments, ids = ");
+ for (int j=0; j < data.procData[i].getAttachments(); j++) {
+ str.append(data.procData[i].getAttachmentIds()[j]);
+ str.append(", ");
+ }
+ }
+ str.append("pid = ");
+ str.append(data.procData[i].getPid());
+ str.append(", hbeat = ");
+ str.append(data.procData[i].getHeartbeat());
+
+ if (leafCounter < 1) {
+ node = new DefaultMutableTreeNode(str.toString());
+ treeModel.insertNodeInto(node, processNode, i);
+ }
+ else {
+ node = (DefaultMutableTreeNode) processNode.getChildAt(i);
+ node.setUserObject(str.toString());
+ leafCounter--;
+ }
+ }
+
+ if (numLeaves > 1) {
+//System.out.println("More than one leaf");
+ // update through leaves that were reused
+ leafCounter = numProcs > numLeaves ? numLeaves : numProcs;
+ int[] leaves = new int[leafCounter];
+ for (int i=0; i < leafCounter; i++) {
+ leaves[i] = i;
+ }
+ treeModel.nodesChanged(processNode, leaves);
+
+ // remove leaves that aren't needed
+ if (numLeaves > numProcs) {
+//System.out.println("More leaves than processes");
+ for (int i=0; i < numLeaves-numProcs; i++) {
+ node = (DefaultMutableTreeNode) processNode.getChildAt(i + numProcs);
+//System.out.println("Remove node " + (i+numProcs) + " called " + node);
+ treeModel.removeNodeFromParent(node);
+ }
+ }
+ }
+ }
+ }
+
+ // user attachments
+
+ // first remove attachments not in current list
+ int numAtts = data.attData.length;
+
+ oldList: for (Iterator i=attachments.keySet().iterator(); i.hasNext();) {
+ attId = (Integer) i.next();
+ newList: for (int j=0; j < numAtts; j++) {
+ if (attId.intValue() == data.attData[j].getId()) {
+ continue oldList;
+ }
+ }
+//System.out.println("Removing node for att " + attId);
+ node = (DefaultMutableTreeNode) attachments.get(attId);
+ treeModel.removeNodeFromParent(node);
+ i.remove();
+ }
+
+ if (data.attData.length > 0) {
+ // create new attachments and update existing attachments
+ for (int i=0; i < numAtts; i++) {
+ // Get Attachment Id & find its node object if there is one,
+ // else make a new node and store it in the hash table
+ attId = new Integer(data.attData[i].getId());
+ if (attachments.containsKey(attId)) {
+ isNewNode = false;
+//System.out.println("Using old node for attachment " + attId);
+ node = (DefaultMutableTreeNode) attachments.get(attId);
+ }
+ else {
+//System.out.println("Adding node for attachment " + attId);
+ isNewNode = true;
+ node = new DefaultMutableTreeNode(attId);
+ attachments.put(attId, node);
+ // wait for all "node" changes before inserting into tree
+ }
+
+ // graph attIcons & links
+
+ str.delete(0, end);
+ str.append("Station = ");
+ str.append(data.attData[i].getStationName());
+ str.append(", host = ");
+ str.append(data.attData[i].getHost());
+
+ if (isNewNode) {
+ node.add(new DefaultMutableTreeNode(str.toString()));
+ }
+ else {
+ leaf = node.getFirstLeaf();
+ leaf.setUserObject(str.toString());
+ }
+
+ if (data.attData[i].getIpAddress() != null) {
+ str.delete(0, end);
+ str.append("Sending ip address = ");
+ str.append(data.attData[i].getIpAddress());
+
+ if (isNewNode) {
+ node.add(new DefaultMutableTreeNode(str.toString()));
+ }
+ else {
+ leaf = leaf.getNextLeaf();
+ leaf.setUserObject(str.toString());
+ }
+ }
+
+ str.delete(0, end);
+ if (data.attData[i].blocked() == true) {
+ str.append("Blocked");
+ }
+ else {
+ str.append("Not blocked");
+ }
+ if (data.attData[i].quitting() == true) {
+ str.append(", quitting");
+ }
+
[truncated at 1000 lines; 830 more skipped]
hps-et-java/src/main/java/org/jlab/coda/et/monitorGui
diff -N WholeNumberField.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ WholeNumberField.java 13 Feb 2012 22:50:53 -0000 1.3
@@ -0,0 +1,162 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2002 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.monitorGui;
+
+import java.awt.Toolkit;
+import javax.swing.*;
+import javax.swing.text.*;
+//import java.text.NumberFormat;
+//import java.text.ParseException;
+//import java.util.Locale;
+
+public class WholeNumberField extends JTextField {
+ private Toolkit toolkit;
+ // private NumberFormat integerFormatter;
+ private boolean enforceLimits = false;
+ private int upperLimit=0;
+ private int lowerLimit=0;
+
+ public WholeNumberField(int value, int columns) {
+ super(columns);
+ toolkit = Toolkit.getDefaultToolkit();
+ // integerFormatter = NumberFormat.getNumberInstance(Locale.US);
+ // integerFormatter.setParseIntegerOnly(true);
+ setValue(value);
+ }
+
+ public WholeNumberField(int value, int columns, int limit1, int limit2) {
+ super(columns);
+ toolkit = Toolkit.getDefaultToolkit();
+ // integerFormatter = NumberFormat.getNumberInstance(Locale.US);
+ // integerFormatter.setParseIntegerOnly(true);
+ enforceLimits = true;
+ setLimits(limit1, limit2);
+ setValue(value);
+ }
+
+ private int adjustValue(int value) {
+ if (enforceLimits == true) {
+ if (value > upperLimit) {
+ value = upperLimit;
+ }
+ else if (value < lowerLimit) {
+ value = lowerLimit;
+ }
+ }
+ return value;
+ }
+
+ public int getValue() {
+ int value = 0;
+ try {
+ // value = integerFormatter.parse(getText()).intValue();
+ value = Integer.parseInt(getText());
+ } catch (NumberFormatException e) {
+ // This should never happen because insertString allows
+ // only properly formatted data to get in the field.
+ toolkit.beep();
+ }
+ value = adjustValue(value);
+ return value;
+ }
+
+ public void correctValue() {
+ int value = 0;
+ try {
+ // value = integerFormatter.parse(getText()).intValue();
+ value = Integer.parseInt(getText());
+ } catch (NumberFormatException e) {
+ // This should never happen because insertString allows
+ // only properly formatted data to get in the field.
+ toolkit.beep();
+ }
+ setValue(value);
+ }
+
+ public void setValue(int value) {
+ value = adjustValue(value);
+ setText(""+value);
+ // setText(integerFormatter.format(value));
+ }
+
+ public void setLimits(int limit1, int limit2) {
+ enforceLimits = true;
+ if (limit1 >= limit2) {
+ upperLimit = limit1;
+ lowerLimit = limit2;
+ }
+ else {
+ upperLimit = limit2;
+ lowerLimit = limit1;
+ }
+ }
+
+ public void removeLimits() {
+ enforceLimits = false;
+ }
+
+ public void setUpperLimit(int limit) {
+ enforceLimits = true;
+ upperLimit = limit;
+ }
+
+ public void setLowerLimit(int limit) {
+ enforceLimits = true;
+ lowerLimit = limit;
+ }
+
+ public int getUpperLimit() {
+ return upperLimit;
+ }
+
+ public int getLowerLimit() {
+ return lowerLimit;
+ }
+
+ protected Document createDefaultModel() {
+ return new WholeNumberDocument();
+ }
+
+ protected class WholeNumberDocument extends PlainDocument {
+ public void insertString(int offs, String str, AttributeSet a)
+ throws BadLocationException {
+ char[] source = str.toCharArray();
+ char[] result = new char[source.length];
+ int value, j=0;
+
+ for (int i=0; i < result.length; i++) {
+ // allow for typing in minus sign
+ if ((offs == 0) && (i == 0) && (source[0] == '-')) {
+ result[j++] = source[0];
+ if (result.length == 1) {
+ super.insertString(0, new String(source,0,1), a);
+ return;
+ }
+ }
+ else if (Character.isDigit(source[i]))
+ result[j++] = source[i];
+ else {
+ toolkit.beep();
+ }
+ }
+ String number = new String(getText(0,offs) + new String(result, 0, j));
+ // value = integerFormatter.parse(number).intValue();
+ // value = adjustValue(value);
+ super.remove(0, offs);
+ // super.insertString(0, integerFormatter.format(value), a);
+ super.insertString(0, number, a);
+ }
+ }
+}
hps-et-java/src/main/java/org/jlab/coda/et/system
diff -N AttachmentLocal.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ AttachmentLocal.java 13 Feb 2012 22:50:54 -0000 1.3
@@ -0,0 +1,286 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.system;
+
+
+/**
+ * This class defines an attachment to a station of an ET system for use by the
+ * ET system itself and not the user. Attachments are used to keep track of
+ * event ownership and as places to conveniently keep some statistics and other
+ * information on the "getting" of events. Attachments can only be created by an
+ * ET system's {@link SystemCreate#attach(int)} method.
+ *
+ * @author Carl Timmer
+ */
+
+class AttachmentLocal {
+
+ // TODO: keep a list or set of events we currently have out?
+
+ /** Unique id number. */
+ private int id;
+
+ /** Process id number for attachments written in C language. */
+ private int pid;
+
+ /** Name of the host the attachment is residing on. */
+ private String host;
+
+ /** IP address of the network interface the attachment is sending data through. */
+ private String ipAddress;
+
+ /** Station the attachment is associated with. */
+ private StationLocal station;
+
+ /** Number of events put by a user into the attachment. */
+ private long eventsPut;
+
+ /** Number of events gotten by a user from the attachment. */
+ private long eventsGet;
+
+ /** Number of events dumped (recycled by returning to GRAND_CENTRAL station)
+ * by a user through the attachment. */
+ private long eventsDump;
+
+ /** Number of new events gotten by a user from the attachment. */
+ private long eventsMake;
+
+ /** Flag telling whether the attachment is blocked waiting to read events
+ * from a station that has no events. */
+ private boolean waiting;
+
+ /**
+ * Flag telling whether the attachment is currently in the sleep mode of
+ * getEvents or newEvents. Since the implementation of this mode is
+ * done by using the timed wait mode, it occasionally happens that the
+ * attachment is told to wake up while it is not actually in getEvents or
+ * newEvents. If this flag is true, the command to wake up will go ahead
+ * and set "wakeUp" to true - even if "waiting" is false.
+ */
+ private volatile boolean sleepMode;
+
+ /** Flag telling the attachment blocked on a read to wake up or return. */
+ private volatile boolean wakeUp;
+
+
+ /**
+ * Constructor. Attachments are only created by an ET system's
+ * {@link SystemCreate#attach(int)} method.
+ */
+ AttachmentLocal() {
+ id = -1;
+ pid = -1;
+ }
+
+
+ /**
+ * Gets the attachment id number.
+ * @return attachment id number
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Sets the attachment id number.
+ * @param id attachment id number
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ /**
+ * Gets the process id number for C clients.
+ * @return the process id number for C clients
+ */
+ public int getPid() {
+ return pid;
+ }
+
+ /**
+ * Set the process id number.
+ * @param pid he process id number
+ */
+ public void setPid(int pid) {
+ this.pid = pid;
+ }
+
+ /**
+ * Get the host the attachment is residing on.
+ * @return host the attachment is residing on
+ */
+ public String getHost() {
+ return host;
+ }
+
+ /**
+ * Set the host the attachment is residing on.
+ * @param host host the attachment is residing on
+ */
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ /**
+ * Get the IP address of the network interface the attachment is sending data through.
+ * @return IP address of the network interface the attachment is sending data through.
+ */
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ /**
+ * Set the IP address of the network interface the attachment is sending data through.
+ * @param ipAddress IP address of the network interface the attachment is sending data through.
+ */
+ public void setIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+
+ /**
+ * Is the attachment blocked waiting to read events from a station that has no events?
+ * @return <code>true</code> if attachment is blocked waiting to read events from a station that has no events
+ */
+ public boolean isWaiting() {
+ return waiting;
+ }
+
+ /**
+ * Set if attachment is blocked waiting to read events from a station that has no events
+ * @param waiting is attachment blocked waiting to read events from a station that has no events?
+ */
+ public void setWaiting(boolean waiting) {
+ this.waiting = waiting;
+ }
+
+ /**
+ * Is this attachment to wake up or return after returning from blocking read?
+ * @return <code>true</code> if this attachment is to wake up or return after returning from blocking read
+ */
+ public boolean isWakeUp() {
+ return wakeUp;
+ }
+
+ /**
+ * Set the flag to wake up or return after returning from blocking read.
+ * @param wakeUp flag to wake up or return after returning from blocking read
+ */
+ public void setWakeUp(boolean wakeUp) {
+ this.wakeUp = wakeUp;
+ }
+
+ /**
+ * Is this attachment currently in the sleep mode of getEvents or newEvents?
+ * @return <code>true</code> if this attachment is currently in the sleep mode of getEvents or newEvents
+ */
+ public boolean isSleepMode() {
+ return sleepMode;
+ }
+
+ /**
+ * Set the flag to be in the sleep mode of getEvents or newEvents.
+ * @param sleepMode sleep mode of getEvents or newEvents
+ */
+ public void setSleepMode(boolean sleepMode) {
+ this.sleepMode = sleepMode;
+ }
+
+ /**
+ * Get the station this attachment is associated with.
+ * @return station this attachment is associated with
+ */
+ public StationLocal getStation() {
+ return station;
+ }
+
+ /**
+ * Set the station this attachment is associated with.
+ * @param station station this attachment is associated with
+ */
+ public void setStation(StationLocal station) {
+ this.station = station;
+ }
+
+ /**
+ * Get the number of events put by a user into this attachment.
+ * @return number of events put by a user into this attachment
+ */
+ public long getEventsPut() {
+ return eventsPut;
+ }
+
+ /**
+ * Get the number of events put by a user into this attachment.
+ * @param eventsPut number of events put by a user into this attachment
+ */
+ public void setEventsPut(long eventsPut) {
+ this.eventsPut = eventsPut;
+ }
+
+ /**
+ * Get the number of events gotten by a user from this attachment.
+ * @return number of events gotten by a user from this attachment
+ */
+ public long getEventsGet() {
+ return eventsGet;
+ }
+
+ /**
+ * Set the number of events gotten by a user from this attachment
+ * @param eventsGet number of events gotten by a user from this attachment
+ */
+ public void setEventsGet(long eventsGet) {
+ this.eventsGet = eventsGet;
+ }
+
+ /**
+ * Get the number of events dumped (recycled by returning to GRAND_CENTRAL station)
+ * by a user through this attachment.
+ * @return number of events dumped by a user through this attachment
+ */
+ public long getEventsDump() {
+ return eventsDump;
+ }
+
+ /**
+ * Set the number of events dumped (recycled by returning to GRAND_CENTRAL station)
+ * by a user through this attachment.
+ * @param eventsDump number of events dumped by a user through this attachment.
+ */
+ public void setEventsDump(long eventsDump) {
+ this.eventsDump = eventsDump;
+ }
+
+ /**
+ * Get the number of new events gotten by a user from this attachment.
+ * @return number of new events gotten by a user from this attachment
+ */
+ public long getEventsMake() {
+ return eventsMake;
+ }
+
+ /**
+ * Set the number of new events gotten by a user from this attachment.
+ * @param eventsMake number of new events gotten by a user from this attachment
+ */
+ public void setEventsMake(long eventsMake) {
+ this.eventsMake = eventsMake;
+ }
+
+
+}
+
+
+
hps-et-java/src/main/java/org/jlab/coda/et/system
diff -N EventList.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EventList.java 13 Feb 2012 22:50:54 -0000 1.3
@@ -0,0 +1,595 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12B3 *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-6248 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.system;
+
+import java.lang.*;
+import java.util.*;
+import org.jlab.coda.et.exception.*;
+import org.jlab.coda.et.EtEvent;
+import org.jlab.coda.et.EtConstants;
+import org.jlab.coda.et.EtEventImpl;
+import org.jlab.coda.et.enums.Priority;
+
+/**
+ * This class defines a linked list of events for use as either a station's
+ * input or output list in a station.
+ *
+ * @author Carl Timmer
+ */
+
+class EventList {
+
+ /** Linked list of events. */
+ private LinkedList<EtEventImpl> events;
+
+ /** Number of events put into this list. */
+ private long eventsIn;
+
+ /** Number of events taken out of this list. */
+ private long eventsOut;
+
+ // input list members only
+
+ /** Number of events tried to put into this list when used with prescaling. */
+ private long eventsTry;
+
+ /** Flag telling the list to wake up the user waiting to read events. */
+ private boolean wakeAll;
+
+ /** Count of the number of users sleeping on reading events. Last one to wake
+ * up needs to reset wakeAll. */
+ private int waitingCount;
+
+ // output list members only
+
+ /** Position of the last high priority event in the linked list. */
+ private int lastHigh;
+
+
+
+ /** Construct a new EventList object. */
+ EventList() {
+ events = new LinkedList<EtEventImpl>();
+ }
+
+
+
+ /**
+ * Get the linked list of events.
+ * @return linked list of events
+ */
+ LinkedList<EtEventImpl> getEvents() {
+ return events;
+ }
+
+ /**
+ * Get the number of events tried to put into this list when used with prescaling.
+ * @return number of events tried to put into this list when used with prescaling
+ */
+ long getEventsTry() {
+ return eventsTry;
+ }
+
+ /**
+ * set the number of events tried to put into this list when used with prescaling.
+ * @param eventsTry number of events tried to put into this list when used with prescaling
+ */
+ void setEventsTry(long eventsTry) {
+ this.eventsTry = eventsTry;
+ }
+
+ /**
+ * Get the number of events put into this list.
+ * @return number of events put into this list
+ */
+ long getEventsIn() {
+ return eventsIn;
+ }
+
+ /**
+ * Set the number of events put into this list.
+ * @param eventsIn number of events put into this list
+ */
+ void setEventsIn(long eventsIn) {
+ this.eventsIn = eventsIn;
+ }
+
+ /**
+ * Get the number of events taken out of this list.
+ * @return number of events taken out of this list
+ */
+ long getEventsOut() {
+ return eventsOut;
+ }
+
+ /**
+ * Set the number of events taken out of this list.
+ * @param eventsOut number of events taken out of this list
+ */
+ void setEventsOut(long eventsOut) {
+ this.eventsOut = eventsOut;
+ }
+
+
+ // methods for waking up reading attachments on input lists
+
+
+ /**
+ * Wake up an attachment waiting to read events from this list.
+ * @param att attachment to be woken up
+ */
+ synchronized void wakeUp(AttachmentLocal att) {
+ if (!att.isWaiting()) {
+ return;
+ }
+ att.setWakeUp(true);
+ notifyAll();
+ }
+
+
+ /** Wake up all attachments waiting to read events from this list. */
+ synchronized void wakeUpAll() {
+ if (waitingCount < 1) {
+ return;
+ }
+ wakeAll = true;
+ notifyAll();
+ }
+
+
+ /**
+ * Put all events into a station's input list as low priority. This is
+ * used inside synchronized blocks in conductor threads and in the initial
+ * filling of GRAND_CENTRAL station.
+ * @param newEvents list of events to put
+ */
+ void putInLow(List<EtEventImpl> newEvents) {
+ // add all events to list's end
+ events.addAll(newEvents);
+ // keep stats
+ eventsIn += newEvents.size();
+ }
+
+
+ /**
+ * Synchronized version of putInLow for user to dump events into
+ * GRAND_CENTRAL station.
+ * @param newEvents array of events to put
+ */
+ synchronized void putInGC(EtEventImpl[] newEvents) {
+ // convert array to list and put as low priority events
+ putInLow(Arrays.asList(newEvents));
+ }
+
+
+ /**
+ * Synchronized version of putInLow for user to dump events into
+ * GRAND_CENTRAL station.
+ * @param newEvents list of events to put
+ */
+ synchronized void putInGC(List<EtEventImpl> newEvents) {
+ putInLow(newEvents);
+ }
+
+
+ /**
+ * Put all events into the list regardless of how many are already in it.
+ * Synchronized and used only in conductor threads to put events into a
+ * station's input list. All high priority events are listed first in
+ * newEvents.
+ * @param newEvents list of events to put
+ */
+ void putAll(List<EtEventImpl> newEvents) {
+ // number of incoming events
+ int num = newEvents.size();
+
+ // all incoming events' priorities are low or no events in this EventList
+ if ((events.size() == 0) || ((newEvents.get(0)).getPriority() == Priority.LOW)) {
+ // adds new events to the end
+ events.addAll(newEvents);
+ /*
+ if ((newEvents.get(0)).priority == Constants.low) {
+ System.out.println(" putAll in as is as incoming are all low pri, " + newEvents.size());
+ }
+ if (events.size() == 0) {
+ System.out.println(" putAll in as is as list EventList empty, " + newEvents.size());
+ }
+ */
+ }
+
+ // if any high pri events (count != 0) ...
+ else {
+ // find last high priority event already in list
+ int highCount = 0;
+ for (EtEvent ev : events) {
+ if (ev.getPriority() != Priority.HIGH) {
+ break;
+ }
+ highCount++;
+ }
+//System.out.println(" putAll last high of input list = " + highCount);
+
+ // add new high pri items
+ int newHighCount = 0;
+ for (EtEventImpl ev : newEvents) {
+ if (ev.getPriority() != Priority.HIGH) {
+ break;
+ }
+//System.out.println(" putAll add high " + ev.id + " at " + (highCount + newHighCount));
+ events.add(highCount + newHighCount++, ev);
+ }
+
+ // rest are low pri, add to end
+ if (newHighCount < num) {
+//System.out.println(" putAll add " + (num - newHighCount) + " lows at end");
+ events.addAll(newEvents.subList(newHighCount, num));
+ }
+ }
+ // keep stats
+ eventsIn += num;
+ return;
+ }
+
+ /**
+ * For user to put all events into station's output list. High & low
+ * priorities may be mixed up in the newEvents list. May also be used to
+ * restore events to the input list when user connection is broken.
+ * @param newEvents array of events to put
+ */
+ synchronized void put(EtEventImpl[] newEvents) {
+ // if no events in list, initialize lastHigh
+ if (events.size() == 0) {
+ lastHigh = 0;
+ }
+
+ // put events in one-by-one - with place depending on priority
+ for (EtEventImpl ev : newEvents) {
+ // if low priority event, add to the list end
+ if (ev.getPriority() == Priority.LOW) {
+//System.out.println(" put in low - " + ev.id);
+ events.addLast(ev);
+ }
+ // else if high pri event, add after other high priority events
+ else {
+//System.out.println(" put in high - " + ev.id);
+ events.add(lastHigh++, ev);
+ }
+ }
+ notify();
+ return;
+ }
+
+ /**
+ * For user to put all events into station's output list. High & low
+ * priorities may be mixed up in the newEvents list. May also be used to
+ * restore events to the input list when user connection is broken.
+ * @param newEvents list of events to put
+ */
+ synchronized void put(List<EtEventImpl> newEvents) {
+ // if no events in list, initialize lastHigh
+ if (events.size() == 0) {
+ lastHigh = 0;
+ }
+
+ // put events in one-by-one - with place depending on priority
+ for (EtEventImpl ev : newEvents) {
+ // if low priority event, add to the list end
+ if (ev.getPriority() == Priority.LOW) {
+//System.out.println(" put in low - " + ev.id);
+ events.addLast(ev);
+ }
+ // else if high pri event, add after other high priority events
+ else {
+//System.out.println(" put in high - " + ev.id);
+ events.add(lastHigh++, ev);
+ }
+ }
+ notify();
+ return;
+ }
+
+
+ /**
+ * For user to put all events into a station's input or output list. High & low
+ * priorities may be mixed up in the newEvents list. Unlike {@link #put},
+ * this method puts the new events BEFORE those already in the list.
+ * Used to restore events to input/output lists when user connection is broken.
+ * @param newEvents list of events to put
+ */
+ synchronized void putReverse(List<EtEventImpl> newEvents) {
+ // if no events in list, initialize lastHigh
+ if (events.size() == 0) {
+ lastHigh = 0;
+ }
+ else {
+ // The lastHigh is NOT tracked for input lists, so let's do
+ // it here since this method can be used for input lists.
+ int highCount = 0;
+ for (EtEvent ev : events) {
+ if (ev.getPriority() != Priority.HIGH) {
+ break;
+ }
+ highCount++;
+ }
+ lastHigh = highCount;
+ }
+
+ // put events in one-by-one - with place depending on priority
+ for (EtEventImpl ev : newEvents) {
+ // if low priority event, add below last high priority but above low priority events
+ if (ev.getPriority() == Priority.LOW) {
+//System.out.println(" put in low - " + ev.id);
+ events.add(lastHigh, ev);
+ }
+ // else if high pri event, add to the top
+ else {
+//System.out.println(" put in high - " + ev.id);
+ events.add(0, ev);
+ lastHigh++;
+ }
+ }
+ notify();
+ return;
+ }
+
+
+ /**
+ * Used only by conductor to get all events from a station's output list.
+ * @param eventsToGo list of event to get
+ */
+ synchronized void get(List<EtEventImpl> eventsToGo) {
+ eventsToGo.addAll(events);
+ eventsOut += events.size();
+ events.clear();
+ return;
+ }
+
+
+ /**
+ * Method for an attachment (in TcpServer thread) to get an array of events.
+ *
+ * @param att attachment
+ * @param mode wait mode
+ * @param microSec time in microseconds to wait if timed wait mode
+ * @param quantity number of events desired
+ *
+ * @throws EtEmptyException
+ * if the mode is asynchronous and the station's input list is empty
+ * @throws EtTimeoutException
+ * if the mode is timed wait and the time has expired
+ * @throws EtWakeUpException
+ * if the attachment has been commanded to wakeup,
+ */
+ synchronized EtEventImpl[] get(AttachmentLocal att, int mode, int microSec, int quantity)
+ throws EtEmptyException, EtWakeUpException, EtTimeoutException {
+
+ int nanos, count = events.size();
+ long begin, microDelay, milliSec, elapsedTime = 0;
+
+ // Sleep mode is never used since it is implemented in the TcpServer
+ // thread by repeated calls in timed mode.
+ if (count == 0) {
+ if (mode == EtConstants.sleep) {
+ while (count < 1) {
+ waitingCount++;
+ att.setWaiting(true);
+//System.out.println(" get" + att.id + ": sleep");
+ try {
+ wait();
+ }
+ catch (InterruptedException ex) {
+ }
+
+ // if we've been told to wakeup & exit ...
+ if (att.isWakeUp() || wakeAll) {
+ att.setWakeUp(false);
+ att.setWaiting(false);
+ // last man to wake resets variable
+ if (--waitingCount < 1) {
+ wakeAll = false;
+ }
+ throw new EtWakeUpException("attachment " + att.getId() + " woken up");
+ }
+
+ att.setWaiting(false);
+ waitingCount--;
+ count = events.size();
+ }
+ }
+ else if (mode == EtConstants.timed) {
+ while (count < 1) {
+ microDelay = microSec - 1000*elapsedTime;
+ milliSec = microDelay/1000L;
+ if (milliSec < 0) {
+ throw new EtTimeoutException("timed out");
+ }
+ nanos = 1000 * (int)(microDelay - 1000*milliSec);
+
+ waitingCount++;
+ att.setWaiting(true);
+//System.out.println(" get" + att.getId() + ": wait " + milliSec + " ms and " +
+// nanos + " nsec, elapsed time = " + elapsedTime);
+ begin = System.currentTimeMillis();
+ try {
+ wait(milliSec, nanos);
+ }
+ catch (InterruptedException ex) {
+ }
+ elapsedTime += System.currentTimeMillis() - begin;
+
+ // if we've been told to wakeup & exit ...
+ if (att.isWakeUp() || wakeAll) {
+ att.setWakeUp(false);
+ att.setWaiting(false);
+ // last man to wake resets variable
+ if (--waitingCount < 1) {
+ wakeAll = false;
+ }
+ throw new EtWakeUpException("attachment " + att.getId() + " woken up");
+ }
+
+ att.setWaiting(false);
+ waitingCount--;
+ count = events.size();
+//System.out.println(" get" + att.id + ": woke up and counts = " + count);
+ }
+ }
+ else if (mode == EtConstants.async) {
+ throw new EtEmptyException("no events in list");
+ }
+ }
+
+ if (quantity > count) {
+ quantity = count;
+ }
+//System.out.println(" get"+ att.id + ": quantity = " + quantity);
+
+ List<EtEventImpl> deleteList = events.subList(0, quantity);
+ EtEventImpl[] eventsToGo = new EtEventImpl[quantity];
+ deleteList.toArray(eventsToGo);
+ deleteList.clear();
+
+ eventsOut += quantity;
+ return eventsToGo;
+ }
+
+
+ /**
+ * Method for an attachment (in TcpServer thread) to get a list of events.
+ *
+ * @param att attachment
+ * @param mode wait mode
+ * @param microSec time in microseconds to wait if timed wait mode
+ * @param quantity number of events desired
+ * @param group group number of events desired
+ *
+ * @throws EtEmptyException
+ * if the mode is asynchronous and the station's input list is empty
+ * @throws EtTimeoutException
+ * if the mode is timed wait and the time has expired
+ * @throws EtWakeUpException
+ * if the attachment has been commanded to wakeup,
+ */
+ synchronized List<EtEventImpl> get(AttachmentLocal att, int mode, int microSec, int quantity, int group)
+ throws EtEmptyException, EtWakeUpException, EtTimeoutException {
+
+ int nanos, count = events.size(), groupCount = 0;
+ EtEventImpl ev;
+ boolean scanList = true;
+ long begin, microDelay, milliSec, elapsedTime = 0;
+ LinkedList<EtEventImpl> groupList = new LinkedList<EtEventImpl>();
+
+ // Sleep mode is never used since it is implemented in the TcpServer
+ // thread by repeated calls in timed mode.
+ do {
+ if (mode == EtConstants.sleep) {
+ while (count < 1 || !scanList) {
+ waitingCount++;
+ att.setWaiting(true);
+//System.out.println(" get" + att.id + ": sleep");
+ try {
+ wait();
+ }
+ catch (InterruptedException ex) {
+ }
+
+ // if we've been told to wakeup & exit ...
+ if (att.isWakeUp() || wakeAll) {
+ att.setWakeUp(false);
+ att.setWaiting(false);
+ // last man to wake resets variable
+ if (--waitingCount < 1) {
+ wakeAll = false;
+ }
+ throw new EtWakeUpException("attachment " + att.getId() + " woken up");
+ }
+
+ att.setWaiting(false);
+ waitingCount--;
+ count = events.size();
+ scanList = true;
+ }
+ }
+ else if (mode == EtConstants.timed) {
+ while (count < 1 || !scanList) {
+ microDelay = microSec - 1000*elapsedTime;
+ milliSec = microDelay/1000L;
+ if (milliSec < 0) {
+ throw new EtTimeoutException("timed out");
+ }
+ nanos = 1000 * (int)(microDelay - 1000*milliSec);
+// if (nanos > 999999) {
+// System.out.println("nanos = " + nanos + ", millisec = " +
+// milliSec + ", elapsed = " + elapsedTime + ", microSec = " + microSec + ", scanList = " + scanList);
+// }
+
+ waitingCount++;
+ att.setWaiting(true);
+//System.out.println(" get" + att.id + ": wait " + milliSec + " ms and " +
+// nanos + " nsec, elapsed time = " + elapsedTime);
+ begin = System.currentTimeMillis();
+ try {
+ wait(milliSec, nanos);
+ }
+ catch (InterruptedException ex) {
+ }
+ elapsedTime += System.currentTimeMillis() - begin;
+
+ // if we've been told to wakeup & exit ...
+ if (att.isWakeUp() || wakeAll) {
+ att.setWakeUp(false);
+ att.setWaiting(false);
+ // last man to wake resets variable
+ if (--waitingCount < 1) {
+ wakeAll = false;
+ }
+ throw new EtWakeUpException("attachment " + att.getId() + " woken up");
+ }
+
+ att.setWaiting(false);
+ waitingCount--;
+ count = events.size();
+//System.out.println(" get" + att.id + ": woke up and counts = " + count);
+ scanList = true;
+ }
+ }
+ else if (mode == EtConstants.async) {
+ throw new EtEmptyException("no events in list");
+ }
+
+ if (quantity > count) {
+ quantity = count;
+ }
+//System.out.println(" get"+ att.id + ": quantity = " + quantity);
+
+ for (ListIterator liter = events.listIterator(); liter.hasNext(); ) {
+ ev = (EtEventImpl)liter.next();
+ if (ev.getGroup() == group) {
+ groupList.add(ev);
+ if (++groupCount >= quantity) break;
+ }
+ }
+
+ scanList = false;
+
+ // If we got nothing and we're Constants.sleep or Constants.timed, then try again
+ } while (groupCount == 0 && mode != EtConstants.async);
+
+ // remove from this list
+ events.removeAll(groupList);
+ eventsOut += groupList.size();
+ return groupList;
+ }
+}
hps-et-java/src/main/java/org/jlab/coda/et/system
diff -N StationLocal.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ StationLocal.java 13 Feb 2012 22:50:54 -0000 1.3
@@ -0,0 +1,942 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.system;
+
+import java.lang.*;
+import java.util.*;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.jlab.coda.et.exception.*;
+import org.jlab.coda.et.*;
+
+/**
+ * This class defines a station for ET system use.
+ *
+ * @author Carl Timmer
+ */
+
+public class StationLocal extends Thread implements EtEventSelectable {
+
+ /** ET system object. */
+ private SystemCreate sys;
+
+ /** Unique id number. */
+ private int id;
+
+ /** Unique station name. */
+ private String name;
+
+ /** Station configuration object. */
+ private EtStationConfig config;
+
+ /** Station status. It may have the values {@link org.jlab.coda.et.EtConstants#stationUnused},
+ * {@link org.jlab.coda.et.EtConstants#stationCreating}, {@link org.jlab.coda.et.EtConstants#stationIdle}, and
+ * {@link org.jlab.coda.et.EtConstants#stationActive}. */
+ private volatile int status;
+
+ /** Flag telling this station to kill the conductor thread */
+ private volatile boolean killConductor;
+
+ /** Flag telling if this station was the last to receive an event
+ * when using the round-robin selection method for a parallel group
+ * of stations. */
+ private volatile boolean wasLast;
+
+ /** Lock used to stop insertion/removal of stations when events
+ * are being transferred by the conductor thread and vice versa. */
+ private final ReentrantLock stopTransferLock;
+
+ /** If this station is the first in a linked list of parallel stations,
+ * this list contains all the parallel stations in that group.
+ * It's protected by stopTransferLock & {@link SystemCreate#systemLock}. */
+ private LinkedList<StationLocal> parallelStations;
+
+ /** Input list of events. */
+ private EventList inputList;
+
+ /** Output list of events. */
+ private EventList outputList;
+
+ /** Set of attachments to this station. */
+ private HashSet<AttachmentLocal> attachments;
+
+ /** Predefined event selection method used when the station's select mode
+ * is {@link org.jlab.coda.et.EtConstants#stationSelectMatch}. */
+ private EtEventSelectable selector;
+
+ /**
+ * Creates a new StationLocal object.
+ *
+ * @param sys ET system object
+ * @param name station name
+ * @param config station configuration
+ * @param id unique station id number
+ * @throws EtException
+ * if the station cannot load the selectClass
+ */
+ public StationLocal(SystemCreate sys, String name, EtStationConfig config, int id)
+ throws EtException {
+
+ this.id = id;
+ this.sys = sys;
+ this.name = name;
+ this.config = new EtStationConfig(config);
+ status = EtConstants.stationUnused;
+ parallelStations = new LinkedList<StationLocal>();
+ stopTransferLock = new ReentrantLock();
+
+ inputList = new EventList();
+ outputList = new EventList();
+
+ // attachments
+ attachments = new HashSet<AttachmentLocal>(EtConstants.attachmentsMax);
+
+ // user event selection routine
+ selector = this;
+ if (config.getSelectMode() == EtConstants.stationSelectUser) {
+ // instantiate object of proper class
+ try {
+ Object f = Class.forName(config.getSelectClass()).newInstance();
+ selector = (EtEventSelectable) f;
+ }
+ catch (ClassNotFoundException ex) {
+ throw new EtException("station cannot load select class " + config.getSelectClass());
+ }
+ catch (InstantiationException ex) {
+ throw new EtException("station cannot instantiate class " + config.getSelectClass());
+ }
+ catch (IllegalAccessException ex) {
+ throw new EtException("station cannot load class " + config.getSelectClass());
+ }
+
+ if (sys.getConfig().getDebug() >= EtConstants.debugInfo) {
+ System.out.println(name + " loaded select class " + config.getSelectClass());
+ }
+ }
+ }
+
+
+ /**
+ * Gets the station id number. Because this class extends Thread, calling this method
+ * getId() would override the method from the Thread class, which is something
+ * we do NOT want. So call this method getStationId() instead.
+ * @return station id number
+ */
+ public int getStationId() { return id; }
+
+ /**
+ * Gets the station name. Because this class extends Thread, calling this method
+ * getName() would override the method from the Thread class, which is something
+ * we do NOT want. So call this method getStationName() instead.
+ * @return station name
+ */
+ public String getStationName() { return name; }
+
+ /**
+ * Get object containing list of input events.
+ * @return object containing list of input events
+ */
+ public EventList getInputList() { return inputList; }
+
+ /**
+ * Get object containing list of utput events.
+ * @return object containing list of output events
+ */
+ public EventList getOutputList() { return outputList; }
+
+ /**
+ * Get lock object used to add and remove stations from the station linked list
+ * while blocking the moving of events.
+ * @return lock object
+ */
+ public ReentrantLock getStopTransferLock() { return stopTransferLock; }
+
+ /**
+ * Get the station configuration.
+ * @return tation configuration
+ */
+ public EtStationConfig getConfig() { return config; }
+
+ /**
+ * Get the linked list of parallel stations.
+ * @return linked list of parallel stations
+ */
+ public LinkedList<StationLocal> getParallelStations() { return parallelStations; }
+
+ /**
+ * Get the station status which may be one of the following values: {@link org.jlab.coda.et.EtConstants#stationUnused },
+ * {@link org.jlab.coda.et.EtConstants#stationCreating}, {@link org.jlab.coda.et.EtConstants#stationIdle}, or {@link org.jlab.coda.et.EtConstants#stationActive}.
+ * @return station status
+ */
+ public int getStatus() { return status; }
+
+ /**
+ * Set the station status which may be one of the following values: {@link org.jlab.coda.et.EtConstants#stationUnused },
+ * {@link org.jlab.coda.et.EtConstants#stationCreating}, {@link org.jlab.coda.et.EtConstants#stationIdle}, or {@link org.jlab.coda.et.EtConstants#stationActive}.
+ * Since the user does not ever call this method, forget any argument checks.
+ * @param status station status
+ */
+ public void setStatus(int status) { this.status = status; }
+
+ /**
+ * Get the set of attachments to this station.
+ * @return set of attachments to this station
+ */
+ public HashSet<AttachmentLocal> getAttachments() { return attachments; }
+
+ /**
+ * Is the conductor thread scheduled to be terminated?
+ * @return <code>true</code> if conductor thread scheduled to be terminated, else <code>false</code>
+ */
+ public boolean isKillConductor() { return killConductor; }
+
+ /** Schedule conductor thread to be terminated. */
+ public void killConductor() { killConductor = true; }
+
+
+ /**
+ * Method to dynamically set a station's blocking mode.
+ * @param mode blocking mode value
+ */
+ void setBlockMode(int mode) {
+ if (config.getBlockMode() == mode) return;
+ synchronized(sys.getStationLock()) {
+ synchronized(inputList) {
+ try {
+ config.setBlockMode(mode);
+ }
+ catch (EtException e) { /* should not happen. */ }
+ }
+ }
+ }
+
+
+ /**
+ * Method to dynamically set a station's cue.
+ * @param cue cue value
+ */
+ void setCue(int cue) {
+ if (config.getCue() == cue) return;
+ synchronized(sys.getStationLock()) {
+ synchronized(inputList) {
+ try {
+ config.setCue(cue);
+ }
+ catch (EtException e) { /* should not happen. */ }
+ }
+ }
+ }
+
+
+ /**
+ * Method to dynamically set a station's prescale.
+ * @param prescale prescale value
+ */
+ void setPrescale(int prescale) {
+ if (config.getPrescale() == prescale) return;
+ synchronized(sys.getStationLock()) {
+ synchronized(inputList) {
+ try {
+ config.setPrescale(prescale);
+ }
+ catch (EtException e) { /* should not happen. */ }
+ }
+ }
+ }
+
+
+ /**
+ * Method to dynamically set a station's select integers.
+ * @param select array of selection integers
+ */
+ void setSelectWords(int[] select) {
+ if (config.getSelect() == select) return;
+ synchronized(sys.getStationLock()) {
+ synchronized(inputList) {
+ try {
+ config.setSelect(select.clone());
+ }
+ catch (EtException e) { /* should not happen. */ }
+ }
+ }
+ }
+
+
+ /**
+ * Method to dynamically set a station's user mode.
+ * @param mode user mode value
+ */
+ void setUserMode(int mode) {
+ if (config.getUserMode() == mode) return;
+ synchronized(sys.getStationLock()) {
+ try {
+ config.setUserMode(mode);
+ }
+ catch (EtException e) { /* should not happen. */ }
+ }
+ }
+
+
+ /**
+ * Method to dynamically set a station's restore mode.
+ * @param mode restore mode value
+ */
+ void setRestoreMode(int mode) {
+ if (config.getRestoreMode() == mode) return;
+ synchronized(sys.getStationLock()) {
+ try {
+ config.setRestoreMode(mode);
+ }
+ catch (EtException e) { /* should not happen. */ }
+ }
+ }
+
+
+ /**
+ * When selectMode equals {@link org.jlab.coda.et.EtConstants#stationSelectMatch}, this
+ * becomes the station's selection method.
+ *
+ * @param sys ET system object
+ * @param stat station object
+ * @param ev event object being evaluated
+ * @see org.jlab.coda.et.EtEventSelectable
+ */
+ public boolean select(SystemCreate sys, StationLocal stat, EtEvent ev) {
+ boolean result = false;
+ int[] select = stat.config.getSelect();
+ int[] control = ev.getControl();
+
+ for (int i=0; i < EtConstants.stationSelectInts ; i++) {
+ if (i%2 == 0) {
+ result = result || ((select[i] != -1) &&
+ (select[i] == control[i]));
+ }
+ else {
+ result = result || ((select[i] != -1) &&
+ ((select[i] & control[i]) != 0));
+ }
+ }
+ return result;
+ }
+
+
+ /**
+ * Shell's method of sorting from "Numerical Recipes" slightly modified.
+ * It is assumed that a and b have indexes from 1 to n. Since the input
+ * arrays will start at 0 index, put nonsense in the first element.
+ *
+ * @param n number of array elements to be sorted
+ * @param a array to be sorted
+ * @param b array to be sorted in the same manner that array a is sorted
+ */
+ private void shellSort(int n, int[] a, int[] b) {
+ int i, j, inc, v, w;
+ inc = 1;
+ do {
+ inc *= 3;
+ inc++;
+ } while (inc <= n);
+
+ do {
+ inc /= 3;
+ for (i = inc + 1; i <= n; i++) {
+ v = a[i];
+ w = b[i];
+ j = i;
+ while (a[j - inc] > v) {
+ a[j] = a[j - inc];
+ b[j] = b[j - inc];
+ j -= inc;
+ if (j <= inc) break;
+ }
+ a[j] = v;
+ b[j] = w;
+ }
+ } while (inc > 1);
+ }
+
+
+ /**
+ * Method to implement thread conducting events between stations. This
+ * conductor places all events that go into a single station into one list
+ * then writes it. It looks downstream, one station at a time, and repeats
+ * the process.
+ * It optimizes for cases in which the next station is GRAND_CENTRAL or one
+ * which takes all events. In those cases, it dumps everything in that
+ * station's input list without bothering to sort or filter it.
+ */
+ public void run() {
+ int count, prescale, available, getListSize, position;
+ long listTry;
+ EtEventImpl ev;
+ boolean writeAll, parallelIsActive, rrobinOrEqualcue;
+ StationLocal currentStat, stat, firstActive, startStation;
+ List<EtEventImpl> subList;
+ ListIterator statIterator, pIterator = null;
+
+ // inputList of next station
+ EventList inList;
+ // events read from station's outputList
+ ArrayList<EtEventImpl> getList = new ArrayList<EtEventImpl>(sys.getConfig().getNumEvents());
+ // events to be put into the next station's inputList
+ ArrayList<EtEventImpl> putList = new ArrayList<EtEventImpl>(sys.getConfig().getNumEvents());
+
+ // store some constants in stack variables for greater speed
+ final int idle = EtConstants.stationIdle;
+ final int active = EtConstants.stationActive;
+ final int blocking = EtConstants.stationBlocking;
+ final int nonBlocking = EtConstants.stationNonBlocking;
+ final int selectAll = EtConstants.stationSelectAll;
+ final int parallel = EtConstants.stationParallel;
+
+ if (name.equals("GRAND_CENTRAL")) {
+ status = active;
+ }
+ else {
+ status = idle;
+ }
+
+ while (true) {
+ // wait for events
+ synchronized (outputList) {
+ while (outputList.getEvents().size() < 1) {
+ try {
+ outputList.wait();
+ }
+ catch (InterruptedException ex) {
+ }
+ if (killConductor) {
+ return;
+ }
+ }
+ }
+
+ // grab all events in station's outputList
+ outputList.get(getList);
+
+ // reinit items
+ writeAll = false;
+
+ // allow no change to linked list of created stations
+ stopTransferLock.lock();
+
+ // find next station in main linked list
+ position = sys.getStations().indexOf(this);
+ // If we're a parallel station which is NOT the head of its group,
+ // find our position in the main linked list
+ if (position < 0) {
+ position = 1;
+ for (ListIterator i = sys.getStations().listIterator(1); i.hasNext();) {
+ stat = (StationLocal) i.next();
+ if (stat.config.getFlowMode() == parallel) {
+ // we've found the group of parallel stations we belong to & our position
+ if (stat.parallelStations.indexOf(this) > -1) {
+ break;
+ }
+ }
+ position++;
+ }
+ }
+
+ statIterator = sys.getStations().listIterator(position + 1);
+ if (statIterator.hasNext()) {
+ currentStat = (StationLocal) statIterator.next();
+ }
+ else {
+ // the next station is GrandCentral, put everything in it
+ currentStat = sys.getStations().getFirst();
+ inList = currentStat.inputList;
+ synchronized (inList) {
+ inList.putInLow(getList);
+ getList.clear();
+ inList.notifyAll();
+ }
+ stopTransferLock.unlock();
+ continue;
+ }
+
+ inList = currentStat.inputList;
+
+ while (getList.size() > 0) {
+ parallelIsActive = false;
+ rrobinOrEqualcue = false;
+ startStation = null;
+ firstActive = null;
+
+ // if this is a parallel station ...
+ if (currentStat.config.getFlowMode() == EtConstants.stationParallel) {
+ // Are any of the parallel stations active or can we skip the bunch?
+ pIterator = currentStat.parallelStations.listIterator();
+ while (pIterator.hasNext()) {
+ stat = (StationLocal) pIterator.next();
+ if (stat.status == EtConstants.stationActive) {
+ parallelIsActive = true;
+ firstActive = stat;
+ break;
+ }
+ }
+ // At this point pIterator will give the station after firstActive
+ // with the following next().
+
+ // Which algorithm are we using?
+ if (parallelIsActive &&
+ ((currentStat.config.getSelectMode() == EtConstants.stationSelectRRobin) ||
+ (currentStat.config.getSelectMode() == EtConstants.stationSelectEqualCue))) {
+ rrobinOrEqualcue = true;
+ }
+ }
+
+ // if not rrobin/equalcue & station(s) is(are) active ...
+ if (!rrobinOrEqualcue &&
+ (parallelIsActive || (currentStat.status == EtConstants.stationActive))) {
+
+ if (currentStat.config.getFlowMode() == EtConstants.stationParallel) {
+ // Skip to first active parallel station
+ currentStat = firstActive;
+ inList = currentStat.inputList;
+ }
+
+ // Loop through all the active parallel stations if necessary.
+ parallelDo:
+ do {
+ // allow no exterior change to inputList
+ synchronized (inList) {
+ // if GrandCentral, put everything into it ...
+ if (currentStat.id == 0) {
+ writeAll = true;
+ }
+
+ // all events, blocking
+ else if ((currentStat.config.getSelectMode() == selectAll) &&
+ (currentStat.config.getBlockMode() == blocking)) {
+
+ // if prescale=1, dump everything into station
+ getListSize = getList.size();
+ if (currentStat.config.getPrescale() == 1) {
+ writeAll = true;
+ }
+ else {
+ prescale = currentStat.config.getPrescale();
+ listTry = inList.getEventsTry();
+ subList = getList.subList(0, (int) ((listTry + getListSize) / prescale - listTry / prescale));
+ putList.addAll(subList);
+ subList.clear();
+ }
+ inList.setEventsTry(inList.getEventsTry() + getListSize);
+ }
+
+ // all events, nonblocking
+ else if ((currentStat.config.getSelectMode() == selectAll) &&
+ (currentStat.config.getBlockMode() == nonBlocking)) {
+ if (inList.getEvents().size() < currentStat.config.getCue()) {
+ count = currentStat.config.getCue() - inList.getEvents().size();
+ available = getList.size();
+ subList = getList.subList(0, (count > available) ? available : count);
+ putList.addAll(subList);
+ subList.clear();
+ }
+ }
+
+ // condition (user or match), blocking
+ else if (currentStat.config.getBlockMode() == blocking) {
+ prescale = currentStat.config.getPrescale();
+ for (ListIterator i = getList.listIterator(); i.hasNext();) {
+ ev = (EtEventImpl) i.next();
+ // apply selection method
+ if (currentStat.selector.select(sys, currentStat, ev)) {
+ // apply prescale
+ listTry = inList.getEventsTry();
+ inList.setEventsTry(listTry + 1);
+ if ((listTry % prescale) == 0) {
+ putList.add(ev);
+ i.remove();
+ }
+ }
+ }
+ }
+
+ // condition (user or match) + nonblocking
+ else if (currentStat.config.getBlockMode() == nonBlocking) {
+ if (inList.getEvents().size() < currentStat.config.getCue()) {
+ count = currentStat.config.getCue() - inList.getEvents().size();
+ for (ListIterator i = getList.listIterator(); i.hasNext();) {
+ ev = (EtEventImpl) i.next();
+ // apply selection method
+ if (currentStat.selector.select(sys, currentStat, ev)) {
+ putList.add(ev);
+ i.remove();
+ if (--count < 1) {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // if items go in this station ...
+ if ((putList.size() > 0) || (writeAll)) {
+ // if grandcentral
+ if (currentStat.id == 0) {
+ inList.putInLow(getList);
+ getList.clear();
+ writeAll = false;
+ }
+
+ else {
+ if (writeAll) {
+ inList.putAll(getList);
+ getList.clear();
+ writeAll = false;
+ }
+ else {
+ inList.putAll(putList);
+ putList.clear();
+ }
+ }
+ // signal reader that new events are here
+ inList.notifyAll();
+ } // if items go in this station
+ } // end of inputList synchronization
+
+ // go to next active parallel station, if there is one
+ if (parallelIsActive) {
+ do {
+ if (pIterator.hasNext()) {
+ stat = (StationLocal) pIterator.next();
+ if (stat.status == EtConstants.stationActive) {
+ currentStat = stat;
+ inList = currentStat.inputList;
+ break;
+ }
+ }
+ else {
+ break parallelDo;
+ }
+ } while (stat.status != EtConstants.stationActive);
+ }
+
+ // loop through active parallel stations if necessary
+ } while (parallelIsActive && (getList.size() > 0));
+
+ } // if station active and not rrobin or equalcue
+
+ // Implement the round-robin & equal-cue algorithms for dispensing
+ // events to a single group of parallel stations.
+ else if (rrobinOrEqualcue && parallelIsActive) {
+
+ int num, extra, lastEventIndex = 0, eventsAlreadyPut, numActiveStations = 0;
+ int index, numOfEvents, min, eventsToPut, eventsLeft;
+ int eventsPerStation, nextHigherCue, eventsDoledOut, stationsWithSameCue;
+ int[] numEvents;
+
+ if (currentStat.config.getSelectMode() == EtConstants.stationSelectRRobin) {
+ // Flag to start looking for station that receives first round-robin event
+ boolean startLooking = false;
+ stat = currentStat;
+ pIterator = currentStat.parallelStations.listIterator(1);
+
+ while (true) {
+ // for each active station ...
+ if (stat.status == EtConstants.stationActive) {
+ if (startLooking) {
+ // This is the first active station after
+ // the last station to receive an event.
+ startStation = stat;
+ startLooking = false;
+ }
+ numActiveStations++;
+ }
+
+ // Find last station to receive a round-robin event and start looking
+ // for the next active station to receive the first one.
+ if (stat.wasLast) {
+ stat.wasLast = false;
+ startLooking = true;
+ }
+
+ // find next station in the parallel linked list
+ if (pIterator.hasNext()) {
+ stat = (StationLocal) pIterator.next();
+ }
+ // else if we're at the end of the list ...
+ else {
+ // If we still haven't found a place to start the round-robin
+ // event dealing, make it the first active station.
+ if (startStation == null) {
+ startStation = firstActive;
+ }
+ break;
+ }
+ }
+
+ // Find the number of events going into each station
+ num = getList.size() / numActiveStations;
+ // Find the number of events left over (not enough for another round). */
+ extra = getList.size() % numActiveStations;
+ eventsAlreadyPut = count = 0;
+ numEvents = new int[numActiveStations];
+
+ // Rearrange events so all those destined for a particular
+ // station are grouped together in the new array.
+ for (int i = 0; i < numActiveStations; i++) {
+ if (i < extra) {
+ numEvents[i] = num + 1;
+ if (i == (extra - 1)) {
+ lastEventIndex = i;
+ }
+ }
+ else {
+ numEvents[i] = num;
+ }
+
+ if (extra == 0) {
+ lastEventIndex = numActiveStations - 1;
+ }
+
+ numOfEvents = numEvents[i];
+
+ index = i;
+ for (int j = 0; j < numOfEvents; j++) {
+ putList.add(getList.get(index));
+ index += numActiveStations;
+ }
+ }
+
+ // Place the first event with the station after the one which
+ // received the last event in the previous round.
+ stat = startStation;
+ inList = stat.inputList;
+ count = 0;
+
+ // set iterator to start with the station following startStation
+ index = currentStat.parallelStations.indexOf(startStation) + 1;
+ pIterator = currentStat.parallelStations.listIterator(index);
+
+ while (true) {
+ // For each active parallel station ...
+ if (stat.status == EtConstants.stationActive) {
+ // Mark station that got the last event
+ if (count == lastEventIndex) {
+ stat.wasLast = true;
+ }
+
+ // Put "eventsToPut" number of events in the next active station
+ eventsToPut = numEvents[count++];
+
+ if (eventsToPut > 0) {
+ synchronized (inList) {
+ subList = putList.subList(eventsAlreadyPut, eventsAlreadyPut + eventsToPut);
+ inList.putAll(subList);
+ inList.setEventsTry(inList.getEventsTry() + eventsToPut);
+ // signal reader that new events are here
+ inList.notifyAll();
+ }
+
+ eventsAlreadyPut += eventsToPut;
+ }
+ }
+
+ // Find next active station
+ if (count >= numActiveStations) {
+ break;
+ }
+ else if (pIterator.hasNext()) {
+ stat = (StationLocal) pIterator.next();
+ inList = stat.inputList;
+ }
+ else {
+ // Go back to the first active parallel station
+ stat = firstActive;
+ inList = stat.inputList;
+ index = currentStat.parallelStations.indexOf(stat) + 1;
+ pIterator = currentStat.parallelStations.listIterator(index);
+ }
+ } // while (forever)
+
+ putList.clear();
+
+ } // if round-robin
+
+ // else if equal-cue algorithm ...
+ else {
+ eventsLeft = getList.size();
+ eventsDoledOut = 0;
+ eventsAlreadyPut = 0;
+ stationsWithSameCue = 0;
+
+ // Array that keeps track of original station order, and
+ // one that contains input list counts.
+ // Give 'em an extra element as the sorting routine
+ // assumes a starting index of 1.
+ int[] place = new int[sys.getConfig().getStationsMax() + 1];
+ int[] inListCount = new int[sys.getConfig().getStationsMax() + 1];
+ for (int i = 1; i <= sys.getConfig().getStationsMax(); i++) {
+ place[i] = i;
+ }
+
+ stat = firstActive;
+ while (true) {
+ // For each active station ...
+ if (stat.status == EtConstants.stationActive) {
+ // Find total # of events in stations' input lists.
+ // Store this information as it will change and we don't
+ // really want to grab all the input mutexes to make
+ // sure these values don't change.
+ inListCount[numActiveStations + 1] = stat.inputList.getEvents().size();
+
+ // Total number of active stations
+ numActiveStations++;
+ }
+
+ // find next station in the parallel linked list
+ if (pIterator.hasNext()) {
+ stat = (StationLocal) pIterator.next();
+ }
+ else {
+ break;
+ }
+ }
+
+ // Sort the input lists (cues) according to number of events. The "place"
+ // array remembers the place in the presorted array of input lists.
+ // Arrays to be sorted are assumed to have indexes from 1 to n,
+ // so the first element contains nonsense.
+ shellSort(numActiveStations, inListCount, place);
+
+ // To determine which stations get how many events:
+ // Take the lowest cues, add enough to make them equal
+ // to the next higher cue. Continue doing this until all
+ // are equal. Evenly divide any remaining events.
+ nextHigherCue = 0;
+ min = inListCount[1];
+ numEvents = new int[numActiveStations];
+
+ while (eventsDoledOut < eventsLeft) {
+ // Find how many cues have the lowest # of events in them
+ stationsWithSameCue = 0;
+ for (int i = 1; i <= numActiveStations; i++) {
+ // Does events in cue + events we've just given it = min?
+ if (min == inListCount[i] + numEvents[place[i] - 1]) {
+ stationsWithSameCue++;
+ }
+ else {
+ nextHigherCue = inListCount[i];
+ break;
+ }
+ }
+
+ // If all stations have same # of events, or if there are not enough
+ // events to fill each lowest cue to level of the next higher cue,
+ // we spread available events between them all ...
+ if ((stationsWithSameCue == numActiveStations) ||
+ ((eventsLeft - eventsDoledOut) < ((nextHigherCue - min) * stationsWithSameCue)))
+ {
+ eventsToPut = eventsLeft - eventsDoledOut;
+ eventsPerStation = eventsToPut / stationsWithSameCue;
+ extra = eventsToPut % stationsWithSameCue;
+ count = 0;
+ for (int i = 1; i <= stationsWithSameCue; i++) {
+ if (count++ < extra) {
+ numEvents[place[i] - 1] += eventsPerStation + 1;
+ }
+ else {
+ numEvents[place[i] - 1] += eventsPerStation;
+ }
+ }
+ break;
+ }
+ // Else, fill the lowest cues to the level of the next higher cue
+ // and repeat the cycle.
+ else {
+ eventsPerStation = nextHigherCue - min;
+ for (int i = 1; i <= stationsWithSameCue; i++) {
+ numEvents[place[i] - 1] += eventsPerStation;
+ }
+ min = nextHigherCue;
+ }
+ eventsDoledOut += eventsPerStation * stationsWithSameCue;
+ }
+
+ stat = firstActive;
+ count = 0;
+ index = currentStat.parallelStations.indexOf(stat) + 1;
+ pIterator = currentStat.parallelStations.listIterator(index);
+
+ while (true) {
+ // for each active parallel station ...
+ if (stat.status == EtConstants.stationActive) {
+
+ if ((eventsToPut = numEvents[count++]) < 1) {
+ // find next station in the parallel linked list
+ if (pIterator.hasNext()) {
+ stat = (StationLocal) pIterator.next();
+ continue;
+ }
+ else {
+ break;
+ }
+ }
+
+ // Put "eventsToPut" number of events in the next active station
+ inList = stat.inputList;
+ synchronized (inList) {
+ subList = getList.subList(eventsAlreadyPut, eventsAlreadyPut + eventsToPut);
+ inList.putAll(subList);
+ inList.setEventsTry(inList.getEventsTry() + eventsToPut);
+ // signal reader that new events are here
+ inList.notifyAll();
+ }
+
+ eventsAlreadyPut += eventsToPut;
+ }
+
+ // Find next station in the parallel linked list
+ if (pIterator.hasNext()) {
+ stat = (StationLocal) pIterator.next();
+ }
+ else {
+ break;
+ }
+ } // while(true)
+ } // else if equal-cue algorithm
+
+ getList.clear();
+
+ } // Implement the round-robin & equal-cue algorithms
+
+ if (currentStat.id == 0) {
+ break;
+ }
+
+ // find next station
+ if (statIterator.hasNext()) {
+ currentStat = (StationLocal) statIterator.next();
+ }
+ else {
+ currentStat = sys.getStations().getFirst();
+ }
+ inList = currentStat.inputList;
+
+ } // while(getList.size() > 0), events left to put
+
+ // stop transfer unlocked - now changes to stations linked list allowed
+ stopTransferLock.unlock();
+
+ } // while(true)
+
+ } // run method
+
+
+}
hps-et-java/src/main/java/org/jlab/coda/et/system
diff -N SystemConfig.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ SystemConfig.java 13 Feb 2012 22:50:54 -0000 1.3
@@ -0,0 +1,448 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.system;
+
+import java.lang.*;
+import java.util.*;
+import java.net.*;
+import org.jlab.coda.et.exception.*;
+import org.jlab.coda.et.EtConstants;
+
+/**
+ * This class defines a configuration for the creation of an ET system.
+ *
+ * @author Carl Timmer
+ */
+
+public class SystemConfig {
+
+ /** Total number of events. */
+ private int numEvents;
+
+ /** Size of the "normal" event in bytes. This is the memory allocated to each
+ * event upon starting up the ET system. */
+ private int eventSize;
+
+ /** Number of events in each group. Used with multiple producers who want to
+ * guarantee available events for each producer. */
+ private int[] groups;
+
+ /** Maximum number of station. */
+ private int stationsMax;
+
+ /** Maximum number of attachments. */
+ private int attachmentsMax;
+
+ /**
+ * Debug level. This may have values of {@link org.jlab.coda.et.EtConstants#debugNone} meaning
+ * print nothing, {@link org.jlab.coda.et.EtConstants#debugSevere} meaning print only the
+ * severest errors, {@link org.jlab.coda.et.EtConstants#debugError} meaning print all errors,
+ * {@link org.jlab.coda.et.EtConstants#debugWarn} meaning print all errors and warnings, and
+ * finally {@link org.jlab.coda.et.EtConstants#debugInfo} meaning print all errors, warnings,
+ * and informative messages.
+ */
+ private int debug;
+
+ /** ET server's TCP send buffer size in bytes. */
+ private int tcpSendBufSize;
+
+ /** ET server's TCP receive buffer size in bytes. */
+ private int tcpRecvBufSize;
+
+ /**
+ * ET server's socket's no-delay setting.
+ * <code>True</code> if no delay, else <code>false</code>.
+ */
+ private boolean noDelay;
+
+ /** UDP port number for thread responding to users' broadcasts looking for the
+ * ET system. */
+ private int udpPort;
+
+ /** TCP port number for the thread establishing connections with users,
+ * otherwise referred to as the ET server thread. */
+ private int serverPort;
+
+ /** UDP port number for thread responding to users' multicasts looking for the
+ * ET system. */
+ private int multicastPort;
+
+ /** Set of all multicast addresses to listen on (in String form). */
+ private HashSet<InetAddress> multicastAddrs;
+
+
+ /**
+ * Constructor that creates a new SystemConfig object using default parameters.
+ * The default parameters are:
+ * number of events = {@link org.jlab.coda.et.EtConstants#defaultNumEvents},
+ * event size = {@link org.jlab.coda.et.EtConstants#defaultEventSize},
+ * max number of stations = {@link org.jlab.coda.et.EtConstants#defaultStationsMax},
+ * max number of attachments = {@link org.jlab.coda.et.EtConstants#defaultAttsMax},
+ * debug level = {@link org.jlab.coda.et.EtConstants#debugError},
+ * udp port = {@link org.jlab.coda.et.EtConstants#broadcastPort},
+ * server (tcp) port = {@link org.jlab.coda.et.EtConstants#serverPort}, and
+ * multicasting port = {@link org.jlab.coda.et.EtConstants#multicastPort}.
+ */
+ public SystemConfig () {
+ numEvents = EtConstants.defaultNumEvents;
+ eventSize = EtConstants.defaultEventSize;
+ stationsMax = EtConstants.defaultStationsMax;
+ attachmentsMax = EtConstants.defaultAttsMax;
+ debug = EtConstants.debugError;
+ udpPort = EtConstants.broadcastPort;
+ serverPort = EtConstants.serverPort;
+ multicastPort = EtConstants.multicastPort;
+ multicastAddrs = new HashSet<InetAddress>(10);
+ // by default there is one group with all events in it
+ groups = new int[1];
+ groups[0] = numEvents;
+ }
+
+ /** Constructor that creates a new SystemConfig object from an existing one. */
+ public SystemConfig (SystemConfig config) {
+ numEvents = config.numEvents;
+ eventSize = config.eventSize;
+ stationsMax = config.stationsMax;
+ attachmentsMax = config.attachmentsMax;
+ debug = config.debug;
+ udpPort = config.udpPort;
+ tcpRecvBufSize = config.tcpRecvBufSize;
+ tcpSendBufSize = config.tcpSendBufSize;
+ noDelay = config.noDelay;
+ serverPort = config.serverPort;
+ multicastPort = config.multicastPort;
+ multicastAddrs = new HashSet<InetAddress>(config.multicastAddrs);
+ groups = config.groups.clone();
+ }
+
+
+ // public gets
+
+
+ /** Get the total number of events.
+ * @return total number of events */
+ public int getNumEvents() {return numEvents;}
+
+ /** Get the size of the normal events in bytes.
+ * @return size of normal events in bytes */
+ public int getEventSize() {return eventSize;}
+
+ /** Get the array of how many events in each group.
+ * @return array of how many events in each group */
+ public int[] getGroups() {return groups.clone();}
+
+ /** Get the maximum number of stations.
+ * @return maximum number of stations */
+ public int getStationsMax() {return stationsMax;}
+
+ /** Get the maximum number of attachments.
+ * @return maximum number of attachments */
+ public int getAttachmentsMax() {return attachmentsMax;}
+
+ /** Get the debug level.
+ * @return debug level */
+ public int getDebug() {return debug;}
+
+ /** Get the TCP receive buffer size in bytes.
+ * @return TCP receive buffer size in bytes */
+ public int getTcpSendBufSize() {
+ return tcpSendBufSize;
+ }
+
+ /** Get the TCP send buffer size in bytes.
+ * @return TCP send buffer size in bytes */
+ public int getTcpRecvBufSize() {
+ return tcpRecvBufSize;
+ }
+
+ /** Get the TCP no-delay setting.
+ * @return TCP no-delay setting */
+ public boolean isNoDelay() {
+ return noDelay;
+ }
+
+ /** Get the udp port number.
+ * @return udp port number */
+ public int getUdpPort() {return udpPort;}
+
+ /** Get the tcp server port number.
+ * @return tcp server port number */
+ public int getServerPort() {return serverPort;}
+
+ /** Get the multicast port number.
+ * @return multicast port number */
+ public int getMulticastPort() {return multicastPort;}
+
+ /** Get the set of multicast addresses.
+ * @return set of multicast addresses */
+ public Set<InetAddress> getMulticastAddrs() {return new HashSet<InetAddress>(multicastAddrs);}
+
+ /** Get the multicast addresses as a String array.
+ * @return multicast addresses as a String array */
+ public String[] getMulticastStrings() {
+ if (multicastAddrs == null) {
+ return null;
+ }
+ int index = 0;
+ String[] addrs = new String[multicastAddrs.size()];
+ for (InetAddress addr : multicastAddrs) {
+ addrs[index++] = addr.getHostAddress();
+ }
+ return addrs;
+ }
+
+
+ // public adds, removes
+
+
+ /**
+ * Adds a multicast address to the set.
+ * @param mCastAddr multicast address
+ * @throws EtException
+ * if the argument is not a multicast address
+ */
+ public void addMulticastAddr(String mCastAddr) throws EtException {
+ InetAddress addr;
+ try {addr = InetAddress.getByName(mCastAddr);}
+ catch (UnknownHostException ex) {
+ throw new EtException("not a multicast address");
+ }
+
+ if (!addr.isMulticastAddress()) {
+ throw new EtException("not a multicast address");
+ }
+ multicastAddrs.add(addr);
+ return;
+ }
+
+
+ /**
+ * Removes a multicast address from the set.
+ * @param addr multicast address
+ */
+ public void removeMulticastAddr(String addr) {
+ InetAddress ad;
+ try {ad = InetAddress.getByName(addr);}
+ catch (UnknownHostException ex) {
+ return;
+ }
+ multicastAddrs.remove(ad);
+ return;
+ }
+
+
+ // public sets
+
+
+ /**
+ * Set the total number of events.
+ * @param num total number of events
+ * @throws EtException
+ * if the argument is less than 1
+ */
+ public void setNumEvents(int num) throws EtException {
+ if (num < 1) {
+ throw new EtException("must have 1 or more events");
+ }
+ numEvents = num;
+ if (groups.length ==1) groups[0] = num;
+ }
+
+
+ /**
+ * Set the event size in bytes.
+ * @param size event size in bytes
+ * @throws EtException
+ * if the argument is less than 1 byte
+ */
+ public void setEventSize(int size) throws EtException {
+ if (size < 1) {
+ throw new EtException("events must have at least one byte");
+ }
+ eventSize = size;
+ }
+
+
+ /**
+ * Set the number of events in each group. Used with mulitple producers who want to
+ * guarantee available events for each producer.
+ *
+ * @param groups array defining number of events in each group
+ * @throws EtException
+ * if the groups array has length < 1 or values are not positive ints
+ */
+ public void setGroups(int[] groups) throws EtException {
+ if (groups.length < 1) {
+ throw new EtException("events must have at least one group");
+ }
+ for (int num : groups) {
+ if (num < 1) {
+ throw new EtException("each event group must contain at least one event");
+ }
+ }
+
+ this.groups = groups.clone();
+ }
+
+ /**
+ * Set the maximum number of stations.
+ * @param num maximum number of stations
+ * @throws EtException
+ * if the argument is less than 2
+ */
+ public void setStationsMax(int num) throws EtException {
+ if (num < 2) {
+ throw new EtException("must have at least 2 stations");
+ }
+ stationsMax = num;
+ }
+
+
+ /**
+ * Set the maximum number of attachments.
+ * @param num maximum number of attachments
+ * @throws EtException
+ * if the argument is less than 1
+ */
+ public void setAttachmentsMax(int num) throws EtException {
+ if (num < 1) {
+ throw new EtException("must be able to have at least one attachment");
+ }
+ attachmentsMax = num;
+ }
+
+
+ /**
+ * Set the debug level.
+ * @param level debug level
+ * @throws EtException
+ * if the argument has a bad value
+ */
+ public void setDebug(int level) throws EtException {
+ if ((level != EtConstants.debugNone) &&
+ (level != EtConstants.debugInfo) &&
+ (level != EtConstants.debugWarn) &&
+ (level != EtConstants.debugError) &&
+ (level != EtConstants.debugSevere)) {
+ throw new EtException("bad debug value");
+ }
+ debug = level;
+ }
+
+
+ /**
+ * Set the TCP send buffer size in bytes. A value of 0
+ * means use the operating system default.
+ *
+ * @param tcpSendBufSize TCP send buffer size in bytes
+ * @throws EtException
+ * if the argument is less than 0
+ */
+ public void setTcpSendBufSize(int tcpSendBufSize) throws EtException {
+ if (tcpSendBufSize < 0) {
+ throw new EtException("buffer size must be >= than 0");
+ }
+ this.tcpSendBufSize = tcpSendBufSize;
+ }
+
+
+ /**
+ * Set the TCP receive buffer size in bytes. A value of 0
+ * means use the operating system default.
+ *
+ * @param tcpRecvBufSize TCP receive buffer size in bytes
+ * @throws EtException
+ * if the argument is less than 0
+ */
+ public void setTcpRecvBufSize(int tcpRecvBufSize) throws EtException {
+ if (tcpRecvBufSize < 0) {
+ throw new EtException("buffer size must be >= than 0");
+ }
+ this.tcpRecvBufSize = tcpRecvBufSize;
+ }
+
+
+ /**
+ * Set the TCP no-delay setting. It is off by default.
+ * @param noDelay TCP no-delay setting
+ */
+ public void setNoDelay(boolean noDelay) {
+ this.noDelay = noDelay;
+ }
+
+
+ /**
+ * Sets the udp port number.
+ * @param port udp port number
+ * @throws EtException
+ * if the argument is less than 1024
+ */
+ public void setUdpPort(int port) throws EtException {
+ if (port < 1024) {
+ throw new EtException("port number must be greater than 1023");
+ }
+ udpPort = port;
+ }
+
+
+ /**
+ * Sets the tcp server port number.
+ * @param port tcp server port number
+ * @throws EtException
+ * if the argument is less than 1024
+ */
+ public void setServerPort(int port) throws EtException {
+ if (port < 1024) {
+ throw new EtException("port number must be greater than 1023");
+ }
+ serverPort = port;
+ }
+
+
+ /**
+ * Sets the multicast port number.
+ * @param port multicast port number
+ * @throws EtException
+ * if the argument is less than 1024
+ */
+ public void setMulticastPort(int port) throws EtException {
+ if (port < 1024) {
+ throw new EtException("port number must be greater than 1023");
+ }
+// else if (port == udpPort) {
+// throw new EtException("multicast port must be different than udp port");
+// }
+ multicastPort = port;
+ }
+
+
+ /**
+ * Checks configuration settings for consistency.
+ * @return true if consistent, else false
+ */
+ public boolean selfConsistent() {
+ // Check to see if the number of events in groups equal the total number of events
+ int count = 0;
+ for (int i : groups) {
+ count += i;
+ }
+ if (count != numEvents) {
+ System.out.println("events in groups != total event number");
+ return false;
+ }
+ return true;
+ }
+}
+
hps-et-java/src/main/java/org/jlab/coda/et/system
diff -N SystemCreate.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ SystemCreate.java 13 Feb 2012 22:50:54 -0000 1.3
@@ -0,0 +1,1962 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.system;
+
+import java.lang.*;
+import java.util.*;
+import java.io.*;
+import java.net.*;
+
+import org.jlab.coda.et.exception.*;
+import org.jlab.coda.et.*;
+import org.jlab.coda.et.enums.Priority;
+import org.jlab.coda.et.enums.Age;
+
+/**
+ * This class creates an ET system.
+ *
+ * @author Carl Timmer
+ */
+
+public class SystemCreate {
+
+ /** A copy of the ET system configuration. */
+ private SystemConfig config;
+
+ /** The ET system file name. */
+ private String name;
+
+ /** A list of stations defining the flow of events. Only the first
+ * station of a single group of parallel stations is included in
+ * this list. The other parallel stations are available in a list
+ * kept by the first parallel station. */
+ private LinkedList<StationLocal> stations; // protected by stopTransfer & systemLock
+
+ /** The total number of idle and active stations. This consists
+ * of the number of main stations given by the size of the "stations"
+ * linked list (stations.size()) and the number of additional parallel
+ * stations added together. */
+ private int stationCount;
+
+ /** GRAND_CENTRAL station object */
+ private StationLocal gcStation;
+
+ /** Map of all ET system attachments. */
+ private HashMap<Integer,AttachmentLocal> attachments; // protected by systemLock
+
+ /** Map of all ET system events. */
+ private HashMap<Integer, EtEventImpl> events;
+
+ /** All local IP addresses */
+ private InetAddress[]netAddresses;
+
+ /** Flag telling if the ET system is running. */
+ private boolean running;
+
+ /** Object on which to synchronize for system stuff - attachments. */
+ private byte[] systemLock;
+
+ /** Object on which to synchronize for station stuff. */
+ private byte[] stationLock;
+
+ /** Flag for killing all threads started by ET system. */
+ private volatile boolean killAllThreads;
+
+ // Variables for gathering system information for distribution.
+ // Do it no more than once per second.
+
+ /** Flag for specifying it's time to regather system information. */
+ private boolean gather = true;
+
+ /** Monitor time when gathering system information. */
+ private long time1 = 0L;
+
+ /** Length of valid data in array storing system information. */
+ private int dataLength = 0;
+
+ /** Array for storing system information for distribution. */
+ private byte[] infoArray = new byte[6000];
+
+
+ /**
+ * Constructor that creates a new ET system using default parameters and starts it running.
+ * The default parameters are:
+ * number of events = {@link org.jlab.coda.et.EtConstants#defaultNumEvents},
+ * event size = {@link org.jlab.coda.et.EtConstants#defaultEventSize},
+ * max number of stations = {@link org.jlab.coda.et.EtConstants#defaultStationsMax},
+ * max number of attachments = {@link org.jlab.coda.et.EtConstants#defaultAttsMax},
+ * debug level = {@link org.jlab.coda.et.EtConstants#debugError},
+ * udp port = {@link org.jlab.coda.et.EtConstants#broadcastPort},
+ * server (tcp) port = {@link org.jlab.coda.et.EtConstants#serverPort}, and
+ * multicasting port = {@link org.jlab.coda.et.EtConstants#multicastPort}
+ *
+ * @param name ET system file name
+ * @throws EtException
+ * if the file already exists or cannot be created
+ */
+ public SystemCreate(String name) throws EtException {
+ this(name, new SystemConfig());
+ }
+
+
+ /**
+ * COnstructor that creates a new ET system with specified parameters and starts it running.
+ *
+ * @param name file name
+ * @param config ET system configuration
+ * @throws EtException
+ * if the file already exists or cannot be created
+ */
+ public SystemCreate (String name, SystemConfig config) throws EtException {
+
+ // check config for consistency
+ if (!config.selfConsistent()) {
+ if (config.getDebug() >= EtConstants.debugInfo) {
+ System.out.println("Number of events in groups does not equal total number of events");
+ }
+ throw new EtException("Number of events in groups does not equal total number of events");
+ }
+
+ this.name = name;
+ this.config = new SystemConfig(config);
+ attachments = new HashMap<Integer, AttachmentLocal>(EtConstants.attachmentsMax + 1);
+ events = new HashMap<Integer, EtEventImpl>(config.getNumEvents() + 1);
+ stations = new LinkedList<StationLocal>();
+ // netAddresses will be set in SystemUdpServer
+ systemLock = new byte[0];
+ stationLock = new byte[0];
+
+ // The ET name is a file (which is really irrelevant in Java)
+ // but is a convenient way to make all system names unique.
+ File etFile = new File(name);
+ try {
+ // if file already exists ...
+ if (!etFile.createNewFile()) {
+ if (config.getDebug() >= EtConstants.debugInfo) {
+ System.out.println("ET file already exists");
+ }
+ throw new EtException("ET file already exists");
+ }
+ }
+ catch (IOException ex) {
+ if (config.getDebug() >= EtConstants.debugInfo) {
+ System.out.println("cannot create ET file");
+ }
+ throw new EtException("Cannot create ET file");
+ }
+ etFile.deleteOnExit();
+
+ // Write into the file indicating a JAVA ET system
+ // is creating and using it. This is for the benefit of
+ // C-based ET systems which may try to open and read local
+ // ET system files thinking they contain shared memory.
+ try {
+ FileOutputStream fos = new FileOutputStream(etFile);
+ DataOutputStream dos = new DataOutputStream(fos);
+ dos.writeInt(0x04030201); // for determining byte order
+ dos.writeInt(EtConstants.systemTypeJava);
+ dos.writeInt(EtConstants.version);
+ dos.writeInt(EtConstants.minorVersion);
+ dos.writeInt(EtConstants.stationSelectInts);
+ // this & following not used in Java
+ dos.writeInt(0);
+ dos.writeLong(0L);
+ dos.writeLong(0L);
+ dos.writeLong(0L);
+ dos.writeLong(0L);
+ dos.writeLong(0L);
+ dos.flush();
+ }
+ catch (FileNotFoundException ex) {
+ }
+ catch (UnsupportedEncodingException ex) {
+ }
+ catch (IOException ex) {
+ }
+
+ // store local IP addresses
+ try {
+ netAddresses = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName());
+ }
+ catch (UnknownHostException ex) {
+ if (config.getDebug() >= EtConstants.debugError) {
+ System.out.println("cannot find local IP addresses");
+ ex.printStackTrace();
+ }
+ throw new EtException("Cannot find local IP addresses");
+ }
+
+ // start things running
+ startUp();
+ }
+
+
+ /** Gets the ET system file name.
+ * @return ET system file name */
+ public String getName() {return name;}
+
+ /** Gets the ET system configuration.
+ * @return ET system configuration */
+ public SystemConfig getConfig() {return new SystemConfig(config);}
+
+ /** Tells if the ET system is running or not.
+ * @return <code>true</code> if the system is running, else <code>false</code> */
+ synchronized public boolean running() {return running;}
+
+ /** Get the linked list of stations.
+ * @return linked list of stations */
+ public LinkedList<StationLocal> getStations() { return stations; }
+
+ /** Get the station synchronization object.
+ * @return station synchronization object */
+ public byte[] getStationLock() { return stationLock; }
+
+ /** Get the system synchronization object.
+ * @return system synchronization object */
+ public byte[] getSystemLock() { return systemLock; }
+
+ /** Get map holding all ET system's events.
+ * @return map holding all ET system's events */
+ public HashMap<Integer, EtEventImpl> getEvents() { return events; }
+
+ /** Gets the list of all network addresses.
+ * @return list of all network addresses */
+ public InetAddress[] getNetAddresses() { return netAddresses; }
+
+ /** Get the map of all attachments.
+ * @return map of all attachments */
+ public HashMap<Integer, AttachmentLocal> getAttachments() { return attachments; }
+
+ /** Has this object been told to kill all spawned threads?
+ * @return <code>true</code> if this object has been told to kill all spawned threads */
+ public boolean killAllThreads() { return killAllThreads; }
+
+ /** Get array for storing system information for distribution.
+ * @return rray for storing system information for distribution */
+ public byte[] getInfoArray() { return infoArray; }
+
+ /** Get length (number of bytes) of valid data in array storing system information.
+ * @return length (number of bytes) of valid data in array storing system information */
+ public int getDataLength() { return dataLength; }
+
+
+
+ /** Starts the ET system running. If the system is already running, nothing
+ * is done. */
+ synchronized public void startUp() {
+ if (running) return;
+
+ // make grandcentral
+ gcStation = createGrandCentral();
+
+ // fill GC with standard sized events
+ EtEventImpl ev;
+ int index = 0, count = 0;
+ ArrayList<EtEventImpl> eventList = new ArrayList<EtEventImpl>(config.getNumEvents());
+
+ for (int i=0; i < config.getNumEvents(); i++) {
+ ev = new EtEventImpl(config.getEventSize());
+ ev.setId(i);
+
+ // assign group numbers
+ if (count < 1)
+ count = (config.getGroups())[index++];
+ ev.setGroup(index);
+ count--;
+
+ eventList.add(ev);
+ // add to hashTable for future easy access
+ events.put(i, ev);
+ }
+
+ // synchronization not necessary here as we're just starting up
+ gcStation.getInputList().putInLow(eventList);
+ // undo statistics keeping for inital event loading
+ gcStation.getInputList().setEventsIn(0);
+
+ // run tcp server thread
+ SystemTcpServer tcpServer = new SystemTcpServer(this);
+ tcpServer.start();
+
+ // run udp listening thread
+ SystemUdpServer udpServer = new SystemUdpServer(this);
+ udpServer.start();
+
+ running = true;
+ }
+
+
+ /** Stops the ET system if it is running. All threads are stopped.
+ * If the system is not running, nothing is done. */
+ synchronized public void shutdown() {
+ if (!running) return;
+ // tell threads to kill themselves
+ killAllThreads = true;
+ // sockets on 2 second timeout so wait
+ try {Thread.sleep(2500);}
+ catch (InterruptedException ex) {}
+ // delete file
+ File etFile = new File(name);
+ etFile.delete();
+
+ // clear everything
+ stations = null;
+ attachments = null;
+ events = null;
+ netAddresses = null;
+ stationLock = null;
+ killAllThreads = false;
+ running = false;
+ }
+
+ //---------------------------------------------------------------------------
+ // Station related methods, mainly to manipulate the linked lists of stations
+ //---------------------------------------------------------------------------
+
+ /**
+ * This method locks the stopTransfer locks of all existing stations which ensures no events
+ * are currently being moved.
+ */
+ private void lockAllStationTransferLocks() {
+ for (StationLocal mainListStation : stations) {
+ // lock station in main linked list
+ mainListStation.getStopTransferLock().lock();
+ // if this station is the head of a parallel linked list, grab all their locks too
+ if (mainListStation.getConfig().getFlowMode() == EtConstants.stationParallel) {
+ // skip first element in parallel list as it is identical to mainListStation
+ StationLocal parallelListStation;
+ for (ListIterator iter = mainListStation.getParallelStations().listIterator(1); iter.hasNext();) {
+ parallelListStation = (StationLocal) iter.next();
+ parallelListStation.getStopTransferLock().lock();
+ }
+ }
+ }
+ }
+
+
+ /**
+ * This method unlocks the stopTransfer locks of all existing stations which means events
+ * are now allowed to be moved.
+ */
+ private void unlockAllStationTransferLocks() {
+ for (StationLocal mainListStation : stations) {
+ // unlock station in main linked list
+ mainListStation.getStopTransferLock().unlock();
+ // if this station is the head of a parallel linked list, release all their locks too
+ if (mainListStation.getConfig().getFlowMode() == EtConstants.stationParallel) {
+ // skip first element in parallel list as it is identical to mainListStation
+ StationLocal parallelListStation;
+ for (ListIterator iter = mainListStation.getParallelStations().listIterator(1); iter.hasNext();) {
+ parallelListStation = (StationLocal) iter.next();
+ parallelListStation.getStopTransferLock().unlock();
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Method used to add a new station to all the relevant linked lists of stations.
+ *
+ * @param newStation station object
+ * @param position the desired position in the main linked list of stations
+ * @param parallelPosition the desired position of a parallel station in the
+ * group of parallel stations it's being added to
+ * @throws EtException
+ * if trying to add an incompatible parallel station to an existing group
+ * of parallel stations or to the head of an existing group of parallel
+ * stations.
+ */
+ private void insertStation(StationLocal newStation, int position, int parallelPosition) throws EtException {
+
+ // If GRAND_CENTRAL is only existing station, or if we're at
+ // or past the end of the linked list, put station on the end
+ if ((stations.size() < 2) ||
+ (position >= stations.size()) ||
+ (position == EtConstants.end)) {
+
+ stations.add(newStation);
+ if (newStation.getConfig().getFlowMode() == EtConstants.stationParallel) {
+ newStation.getParallelStations().clear();
+ newStation.getParallelStations().add(newStation);
+ }
+ }
+ // else, put the station in the desired position in the middle somewhere
+ else {
+ StationLocal stat = stations.get(position);
+
+ // if the station in "position" and this station are both parallel ...
+ if ((newStation.getConfig().getFlowMode() == EtConstants.stationParallel) &&
+ (stat.getConfig().getFlowMode() == EtConstants.stationParallel) &&
+ (parallelPosition != EtConstants.newHead)) {
+
+ // If these 2 stations have incompatible definitions or we're trying to place
+ // a parallel station in the first (already taken) spot of its group ...
+ if (!EtStationConfig.compatibleParallelConfigs(stat.getConfig(), newStation.getConfig())) {
+ throw new EtException("trying to add incompatible parallel station\n");
+ }
+ else if (parallelPosition == 0) {
+ throw new EtException("trying to add parallel station to head of existing parallel group\n");
+ }
+
+ // Add this parallel station in the "parallelPosition" slot in the
+ // parallel linked list or to the end if parallelPosition = Constants.end.
+ if ((parallelPosition == EtConstants.end) ||
+ (parallelPosition >= stat.getParallelStations().size())) {
+ stat.getParallelStations().add(newStation);
+ }
+ else {
+ stat.getParallelStations().add(parallelPosition, newStation);
+ }
+ }
+ else {
+ stations.add(position, newStation);
+ if (newStation.getConfig().getFlowMode() == EtConstants.stationParallel) {
+ newStation.getParallelStations().clear();
+ newStation.getParallelStations().add(newStation);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Method used to remove a station from all relevant linked lists of stations.
+ * @param station station object
+ */
+ private void deleteStation(StationLocal station) {
+ // The only tricky part in removing a station is to remember that it may not
+ // be in the main linked list if it is a parallel station.
+
+ // if the station is in the main linked list ...
+ if (stations.contains(station)) {
+
+ // remember where the station was located
+ int index = stations.indexOf(station);
+
+ // remove it from main list
+ stations.remove(station);
+
+ // if it's not a parallel station, we're done
+ if (station.getConfig().getFlowMode() == EtConstants.stationSerial) {
+ return;
+ }
+
+ // if the station is parallel, it's the head of another linked list.
+ station.getParallelStations().removeFirst();
+
+ // if no other stations in the group, we're done
+ if (station.getParallelStations().size() < 1) {
+ return;
+ }
+
+ // If there are other stations in the group, make sure that the linked
+ // list of parallel stations is passed on to the next member. And put
+ // the new head of the parallel list into the main list.
+ StationLocal nextStation = station.getParallelStations().getFirst();
+ nextStation.getParallelStations().clear();
+ nextStation.getParallelStations().addAll(station.getParallelStations());
+ station.getParallelStations().clear();
+ stations.add(index, nextStation);
+ }
+
+ // else if it's not in the main linked list, we'll have to hunt it down
+ else {
+ // loop thru all stations in main list
+ for (StationLocal nextStation : stations) {
+ // If it's a parallel station, try to remove "station" from the
+ // list of parallel stations registered with it.
+ if (nextStation.getConfig().getFlowMode() == EtConstants.stationParallel) {
+ if (nextStation.getParallelStations().remove(station)) {
+ // we got it
+ return;
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Method for use by {@link #createStation(org.jlab.coda.et.EtStationConfig, String)}
+ * to grab all stations'
+ * transfer locks and stop all event transfer before adding a new station to
+ * the ET system's linked lists of stations.
+ *
+ * @param newStation station to add
+ * @param position the desired position in the main linked list of stations
+ * @param parallelPosition the desired position of a parallel station in the
+ * group of parallel stations it's being added to
+ * @throws EtException
+ * if trying to add an incompatible parallel station to an existing group
+ * of parallel stations or to the head of an existing group of parallel
+ * stations.
+ */
+ private void addStationToList(StationLocal newStation, int position, int parallelPosition) throws EtException {
+ lockAllStationTransferLocks();
+ try {
+ insertStation(newStation, position, parallelPosition);
+ // since we locked all stations' transfer locks, do so with the new one too
+ newStation.getStopTransferLock().lock();
+ }
+ finally {
+ unlockAllStationTransferLocks();
+ }
+ }
+
+
+ /**
+ * Method for use by {@link #removeStation(int)} to grab all stations'
+ * transfer locks and stop all event transfer before removing a station from
+ * the ET system's linked lists of stations.
+ *
+ * @param station station to remove
+ */
+ private void removeStationFromList(StationLocal station) {
+ lockAllStationTransferLocks();
+ try {
+ deleteStation(station);
+ // since we will unlock all stations' transfer locks, do so with the new one too
+ station.getStopTransferLock().unlock();
+ }
+ finally {
+ unlockAllStationTransferLocks();
+ }
+ }
+
+
+ /**
+ * Method for use by {@link #removeStationFromList(StationLocal)} to grab all stations'
+ * transfer locks and stop all event transfer before moving a station in
+ * the ET system's linked lists of stations.
+ *
+ * @param station station to move
+ * @param position the desired position in the main linked list of stations
+ * @param parallelPosition the desired position of a parallel station in the
+ * group of parallel stations it's being added to
+ * @throws EtException
+ * if trying to move an incompatible parallel station to an existing group
+ * of parallel stations or to the head of an existing group of parallel
+ * stations.
+ */
+ private void moveStationInList(StationLocal station, int position, int parallelPosition) throws EtException {
+ lockAllStationTransferLocks();
+ try {
+ deleteStation(station);
+ insertStation(station, position, parallelPosition);
+ }
+ finally {
+ unlockAllStationTransferLocks();
+ }
+ }
+
+
+ /**
+ * Method for use by {@link #deleteStation(StationLocal)} and {@link #detach(AttachmentLocal)}
+ * to grab all stations' transfer locks and stop all event transfer before changing a station's status.
+ *
+ * @param station station to set status on
+ * @param status the desired status of the station
+ */
+ private void changeStationStatus(StationLocal station, int status) {
+ lockAllStationTransferLocks();
+ try {
+ station.setStatus(status);
+ }
+ finally {
+ unlockAllStationTransferLocks();
+ }
+ }
+
+
+ //
+ // Done with station manipulation methods
+ //
+
+
+ /**
+ * Creates a new station placed at the end of the linked list of stations.
+ *
+ * @param stationConfig station configuration
+ * @param name station name
+ *
+ * @return the new station object
+ *
+ * @throws EtException
+ * if the select method's class cannot be loaded
+ * @throws EtExistsException
+ * if the station already exists but with a different configuration
+ * @throws EtTooManyException
+ * if the maximum number of stations has been created already
+ */
+ StationLocal createStation(EtStationConfig stationConfig, String name)
+ throws EtException, EtExistsException, EtTooManyException {
+ synchronized(stationLock) {
+ return createStation(stationConfig, name, stations.size(), EtConstants.end);
+ }
+ }
+
+
+ /**
+ * Creates a new station at a specified position in the linked list of
+ * stations. Cannot exceed the maximum number of stations allowed in a system.
+ *
+ * @param stationConfig station configuration
+ * @param name station name
+ * @param position position in the linked list to put the station.
+ *
+ * @return the new station object
+ *
+ * @throws EtException
+ * if the select method's class cannot be loaded
+ * @throws EtExistsException
+ * if the station already exists but with a different configuration
+ * @throws EtTooManyException
+ * if the maximum number of stations has been created already
+ */
+ StationLocal createStation(EtStationConfig stationConfig, String name,
+ int position, int parallelPosition)
+ throws EtException, EtExistsException, EtTooManyException {
+
+
+ int id = 0;
+ StationLocal station;
+
+ // grab station mutex
+ synchronized (stationLock) {
+ // check to see if hit maximum allowed # of stations
+ if (stations.size() >= config.getStationsMax()) {
+ throw new EtTooManyException("Maximum number of stations already created");
+ }
+ else if (position > stations.size()) {
+ position = stations.size();
+ }
+
+ // check to see if it already exists
+ StationLocal listStation;
+ try {
+ listStation = stationNameToObject(name);
+ EtStationConfig listStationConfig = listStation.getConfig();
+ // it's got the same name, let's see if it's defined the same
+ if ((listStationConfig.getFlowMode() == stationConfig.getFlowMode()) &&
+ (listStationConfig.getUserMode() == stationConfig.getUserMode()) &&
+ (listStationConfig.getBlockMode() == stationConfig.getBlockMode()) &&
+ (listStationConfig.getSelectMode() == stationConfig.getSelectMode()) &&
+ (listStationConfig.getRestoreMode() == stationConfig.getRestoreMode()) &&
+ (listStationConfig.getPrescale() == stationConfig.getPrescale()) &&
+ (listStationConfig.getCue() == stationConfig.getCue()) &&
+ (Arrays.equals(listStationConfig.getSelect(), stationConfig.getSelect()))) {
+
+ if ((listStationConfig.getSelectClass() != null) &&
+ (!listStationConfig.getSelectClass().equals(stationConfig.getSelectClass()))) {
+ throw new EtExistsException("Station already exists with different configuration");
+ }
+ // station definitions are the same, use listStation
+ return listStation;
+ }
+ throw new EtExistsException("Station already exists with different configuration");
+ }
+ catch (EtException ex) {
+ // station does NOT exist, continue on
+ }
+
+ // find smallest possible unique id number
+ search:
+ for (int i = 0; i < stationCount + 1; i++) {
+ for (ListIterator j = stations.listIterator(); j.hasNext();) {
+ listStation = (StationLocal) j.next();
+ if (listStation.getStationId() == i) {
+ continue search;
+ }
+ if (listStation.getConfig().getFlowMode() == EtConstants.stationParallel) {
+ for (ListIterator k = listStation.getParallelStations().listIterator(1); k.hasNext();) {
+ listStation = (StationLocal) k.next();
+ if (listStation.getStationId() == i) {
+ continue search;
+ }
+ }
+ }
+ }
+ // only get down here if "i" is not a used id number
+ id = i;
+ break;
+ }
+
+ // create station
+ station = new StationLocal(this, name, stationConfig, id);
+
+ // start its conductor thread
+ station.start();
+ // give up processor so thread can start
+ Thread.yield();
+
+ // make sure the conductor is started or we'll get race conditions
+ while (station.getStatus() != EtConstants.stationIdle) {
+ if (config.getDebug() >= EtConstants.debugInfo) {
+ System.out.println("Waiting for " + name + "'s conductor thread to start");
+ }
+ // sleep for minimum amount of time (1 nsec haha)
+ try {
+ Thread.sleep(0, 1);
+ }
+ catch (InterruptedException ex) {
+ }
+ }
+
+ // put in linked list(s) - first grabbing stopTransfer mutexes
+ addStationToList(station, position, parallelPosition);
+ // keep track of the total number of stations
+ stationCount++;
+ } // release station mutex
+
+ return station;
+ }
+
+
+ /**
+ * Creates the first station by the name of GRAND_CENTRAL and starts its
+ * conductor thread.
+ *
+ * @return GRAND_CENTRAL station's object
+ */
+ private StationLocal createGrandCentral() {
+ // use the default configuration
+ EtStationConfig gcConfig = new EtStationConfig();
+ StationLocal station = null;
+ // create station
+ try {
+ station = new StationLocal(this, "GRAND_CENTRAL", gcConfig, 0);
+ }
+ catch (EtException ex) {}
+
+ // put in linked list
+ stations.clear();
+ stations.addFirst(station);
+
+ // start its conductor thread
+ station.start();
+
+ // keep track of the total number of stations
+ stationCount++;
+ return station;
+ }
+
+
+ /**
+ * Removes an existing station.
+ *
+ * @param statId station id
+ * @throws EtException
+ * if attachments to the station still exist or the station does not exist
+ */
+ void removeStation(int statId) throws EtException {
+ StationLocal stat;
+ // grab station mutex
+ synchronized(stationLock) {
+ stat = stationIdToObject(statId);
+ // only remove if no attached processes
+ if (stat.getAttachments().size() != 0) {
+ throw new EtException("Remove all attachments before removing station");
+ }
+
+ // remove from linked list - first grabbing stopTransfer mutexes
+ removeStationFromList(stat);
+
+ // kill conductor thread
+ stat.killConductor();
+ stat.interrupt();
+
+ // set status
+ stat.setStatus(EtConstants.stationUnused);
+
+ // keep track of the total number of stations
+ stationCount--;
+ return;
+ }
+ }
+
+
+ /**
+ * Changes the position of a station in the linked lists of stations.
+ *
+ * @param statId station id
+ * @param position position in the main linked list of stations (starting at 0)
+ * @param parallelPosition position of a parallel station in a group of
+ * parallel stations (starting at 0)
+ * @throws EtException
+ * if the station does not exist, or
+ * if trying to move an incompatible parallel station to an existing group
+ * of parallel stations or to the head of an existing group of parallel
+ * stations.
+ */
+ void setStationPosition(int statId, int position, int parallelPosition) throws EtException {
+ StationLocal stat;
+ // grab station mutex
+ synchronized(stationLock) {
+ stat = stationIdToObject(statId);
+ // change linked list - first grabbing stopTransfer mutexes
+ moveStationInList(stat, position, parallelPosition);
+ }
+ }
+
+ /**
+ * Gets the position of a station in the main linked list of stations.
+ *
+ * @param statId station id
+ * @return the position of a station in the linked list of stations
+ * @throws EtException
+ * if the station does not exist
+ */
+ int getStationPosition(int statId) throws EtException {
+ // GrandCentral is always first
+ if (statId == 0) return 0;
+ int position = 0;
+
+ synchronized (stationLock) {
+ for (StationLocal stat : stations) {
+ if (stat.getStationId() == statId) {
+ return position;
+ }
+ if (stat.getConfig().getFlowMode() == EtConstants.stationParallel) {
+ for (StationLocal stat2 : stat.getParallelStations()) {
+ if (stat2.getStationId() == statId) {
+ return position;
+ }
+ }
+ }
+ position++;
+ }
+ }
+ throw new EtException("cannot find station");
+ }
+
+
+ /**
+ * Gets the position of a parallel station in its linked list of
+ * parallel stations.
+ *
+ * @param statId station id
+ * @return the position of a parallel station in its linked list
+ * of parallel stations, or zero if station is serial
+ * @throws EtException
+ * if the station does not exist
+ */
+ int getStationParallelPosition(int statId) throws EtException {
+ // parallel position is 0 for serial stations
+ if (statId == 0) return 0;
+ int pposition;
+
+ synchronized (stationLock) {
+ for (StationLocal stat : stations) {
+ if (stat.getStationId() == statId) {
+ return 0;
+ }
+ if (stat.getConfig().getFlowMode() == EtConstants.stationParallel) {
+ pposition = 1;
+ for (StationLocal stat2 : stat.getParallelStations()) {
+ if (stat2.getStationId() == statId) {
+ return pposition;
+ }
+ pposition++;
+ }
+ }
+ }
+ }
+ throw new EtException("cannot find station");
+ }
+
+
+ /**
+ * Tells if an attachment is attached to a station.
+ *
+ * @param statId station id
+ * @param attId attachment id
+ * @return <code>true</code> if an attachment is attached to a station
+ * and <code>false</code> otherwise
+ * @throws EtException
+ * if the station does not exist
+ */
+ boolean stationAttached(int statId, int attId) throws EtException {
+ StationLocal stat;
+ synchronized (stationLock) {
+ stat = stationIdToObject(statId);
+ for (AttachmentLocal att : stat.getAttachments()) {
+ if (att.getId() == attId) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+
+ /**
+ * Tells if a station exists.
+ *
+ * @param station station object
+ * @return <code>true</code> if a station exists and
+ * <code>false</code> otherwise
+ */
+ boolean stationExists(StationLocal station) {
+ synchronized (stationLock) {
+ if (stations.contains(station)) {
+ return true;
+ }
+ for (StationLocal listStation : stations) {
+ if (listStation.getConfig().getFlowMode() == EtConstants.stationParallel) {
+ if (listStation.getParallelStations().contains(station)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * Tells if a station exists.
+ *
+ * @param name station name
+ * @return <code>true</code> if a station exists and
+ * <code>false</code> otherwise
+ */
+ boolean stationExists(String name) {
+ try {
+ stationNameToObject(name);
+ }
+ catch (EtException ex) {
+ return false;
+ }
+ return true;
+ }
+
+
+ /**
+ * Gets a station's object representation.
+ *
+ * @param name station name
+ * @return a station's object
+ * @throws EtException
+ * if the station does not exist
+ */
+ StationLocal stationNameToObject(String name) throws EtException {
+ synchronized (stationLock) {
+ for (StationLocal listStation : stations) {
+ if (listStation.getStationName().equals(name)) {
+ return listStation;
+ }
+ if (listStation.getConfig().getFlowMode() == EtConstants.stationParallel) {
+ for (StationLocal listStation2 : listStation.getParallelStations()) {
+ if (listStation2.getStationName().equals(name)) {
+ return listStation2;
+ }
+ }
+ }
+ }
+ }
+ throw new EtException("station " + name + " does not exist");
+ }
+
+
+ /**
+ * Given a station id number, this method gets the corresponding
+ * StationLocal object.
+ *
+ * @param statId station id
+ * @return the station's object
+ * @throws EtException
+ * if the station does not exist
+ */
+ StationLocal stationIdToObject(int statId) throws EtException {
+ synchronized (stationLock) {
+ for (StationLocal stat : stations) {
+ if (stat.getStationId() == statId) {
+ return stat;
+ }
+ if (stat.getConfig().getFlowMode() == EtConstants.stationParallel) {
+ for (StationLocal stat2 : stat.getParallelStations()) {
+ if (stat2.getStationId() == statId) {
+ return stat2;
+ }
+ }
+ }
+ }
[truncated at 1000 lines; 966 more skipped]
hps-et-java/src/main/java/org/jlab/coda/et/system
diff -N SystemTcpServer.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ SystemTcpServer.java 13 Feb 2012 22:50:54 -0000 1.3
@@ -0,0 +1,1801 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.system;
+
+import java.lang.*;
+import java.util.*;
+import java.util.Map.*;
+import java.io.*;
+import java.net.*;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.ByteBuffer;
+
+import org.jlab.coda.et.exception.*;
+import org.jlab.coda.et.*;
+import org.jlab.coda.et.enums.Modify;
+import org.jlab.coda.et.enums.Priority;
+import org.jlab.coda.et.enums.DataStatus;
+
+/**
+ * This class implements a thread which listens for users trying to connect to
+ * the ET system. It starts another thread for each tcp socket connection
+ * established to a user of the system.
+ *
+ * @author Carl Timmer
+ */
+
+class SystemTcpServer extends Thread {
+
+ /** Port number to listen on. */
+ private int port;
+
+ /** Et system object. */
+ private SystemCreate sys;
+
+ /** Et system config object. */
+ private SystemConfig config;
+
+
+ /** Createes a new SystemTcpServer object.
+ * @param sys ET system object */
+ SystemTcpServer(SystemCreate sys) {
+ this.sys = sys;
+ config = sys.getConfig();
+ port = config.getServerPort();
+ }
+
+
+ /** Start thread to listen for connections and spawn off communication
+ * handling threads. */
+ public void run() {
+ if (config.getDebug() >= EtConstants.debugInfo) {
+ System.out.println("Running TCP Server Thread");
+ }
+
+ // use the default port number since one wasn't specified
+ if (port < 1) {
+ port = EtConstants.serverPort;
+ }
+
+ // let exceptions propagate up a level
+
+ // open a listening socket
+ try {
+
+ // Direct buffer for reading 3 magic ints with nonblocking IO
+ int BYTES_TO_READ = 12;
+ ByteBuffer buffer = ByteBuffer.allocateDirect(BYTES_TO_READ);
+
+ // Create channel and bind to port. If that isn't possible, exit.
+ ServerSocketChannel serverChannel = ServerSocketChannel.open();
+ serverChannel.socket().setReuseAddress(true);
+ serverChannel.socket().setSoTimeout(2000);
+ if (config.getTcpRecvBufSize() > 0) {
+ serverChannel.socket().setReceiveBufferSize(config.getTcpRecvBufSize());
+ }
+ serverChannel.socket().bind(new InetSocketAddress(port));
+
+ while (true) {
+ // socket to client created
+ SocketChannel channel;
+ Socket sock;
+ while (true) {
+ try {
+ // accept the connection from the client
+ channel = serverChannel.accept();
+ sock = channel.socket();
+ break;
+ }
+ // server socket accept timeout
+ catch (InterruptedIOException ex) {
+ // check to see if we've been commanded to die
+ if (sys.killAllThreads()) {
+ return;
+ }
+ }
+ }
+ // Set reading timeout to 1/2 second so dead clients
+ // can be found by reading on a socket.
+ sock.setSoTimeout(500);
+ // set send buffer size, receive buffer size is set above in server socket
+ if (config.getTcpSendBufSize() > 0) {
+ sock.setSendBufferSize(sys.getConfig().getTcpSendBufSize());
+ }
+ // Set tcpNoDelay so no packets are delayed
+ if (config.isNoDelay()) {
+ sock.setTcpNoDelay(config.isNoDelay());
+ }
+
+ // Check to see if this is a legitimate client or some imposter.
+ // Don't want to block on read here since it may not be a real client
+ // and may block forever - tying up the server.
+ int bytes, bytesRead=0, loops=0;
+ buffer.clear();
+ buffer.limit(BYTES_TO_READ);
+ channel.configureBlocking(false);
+
+ // read magic numbers
+ while (bytesRead < BYTES_TO_READ) {
+//System.out.println(" try reading rest of Buffer");
+//System.out.println(" Buffer capacity = " + buffer.capacity() + ", limit = " + buffer.limit()
+// + ", position = " + buffer.position() );
+ bytes = channel.read(buffer);
+ // for End-of-stream ...
+ if (bytes == -1) {
+ channel.close();
+ continue;
+ }
+ bytesRead += bytes;
+//System.out.println(" bytes read = " + bytesRead);
+
+ // if we've read everything, look to see if it's sent the magic #s
+ if (bytesRead >= BYTES_TO_READ) {
+ buffer.flip();
+ int magic1 = buffer.getInt();
+ int magic2 = buffer.getInt();
+ int magic3 = buffer.getInt();
+ if (magic1 != EtConstants.magicNumbers[0] ||
+ magic2 != EtConstants.magicNumbers[1] ||
+ magic3 != EtConstants.magicNumbers[2]) {
+//System.out.println("SystemTcpServer: Magic numbers did NOT match");
+ channel.close();
+ }
+ }
+ else {
+ // give client 10 loops (.1 sec) to send its stuff, else no deal
+ if (++loops > 10) {
+//System.out.println("SystemTcpServer: Client taking too long to send 3 ints, terminate connection");
+ channel.close();
+ continue;
+ }
+ try { Thread.sleep(10); }
+ catch (InterruptedException e) { }
+ }
+ }
+
+ // change back to blocking socket
+ channel.configureBlocking(true);
+
+ // create thread to deal with client
+ ClientThread connection = new ClientThread(sys, channel.socket());
+ connection.start();
+ }
+
+ }
+ catch (SocketException ex) {
+ }
+ catch (IOException ex) {
+ }
+ return;
+ }
+
+}
+
+
+/**
+ * This class handles all communication between an ET system and a user who has
+ * opened that ET system.
+ *
+ * @author Carl Timmer
+ */
+
+class ClientThread extends Thread {
+
+ /** Tcp socket. */
+ private Socket sock;
+
+ /** ET system object. */
+ private SystemCreate sys;
+
+ /** ET system configuration object. */
+ private SystemConfig config;
+
+ /** Data input stream built on top of the socket's input stream (with an
+ * intervening buffered input stream). */
+ private DataInputStream in;
+
+ /** Data output stream built on top of the socket's output stream (with an
+ * intervening buffered output stream). */
+ private DataOutputStream out;
+
+ /** Client is 64 bits? */
+ boolean bit64;
+
+
+ /**
+ * Create a new ClientThread object.
+ * @param sys ET system object.
+ * @param sock TCP socket.
+ */
+ ClientThread(SystemCreate sys, Socket sock) {
+ this.sys = sys;
+ this.sock = sock;
+ config = sys.getConfig();
+ }
+
+
+ /** Start thread to handle communications with user. */
+ public void run() {
+
+ try {
+ // buffered communication streams for efficiency
+ if (config.getTcpRecvBufSize() > 0) {
+ in = new DataInputStream(new BufferedInputStream(sock.getInputStream(),
+ config.getTcpRecvBufSize())
+ );
+ }
+ else {
+ in = new DataInputStream(new BufferedInputStream(sock.getInputStream(), sock.getReceiveBufferSize()));
+ }
+
+ if (config.getTcpRecvBufSize() > 0) {
+ out = new DataOutputStream(new BufferedOutputStream(sock.getOutputStream(),
+ config.getTcpSendBufSize())
+ );
+ }
+ else {
+ out = new DataOutputStream(new BufferedOutputStream(sock.getOutputStream(), sock.getSendBufferSize()));
+ }
+
+ int endian = in.readInt();
+ int length = in.readInt();
+ int b64 = in.readInt();
+ bit64 = b64 == 1;
+ in.readLong();
+
+ byte[] buf = new byte[length];
+ in.readFully(buf, 0, length);
+ String etName = new String(buf, 0, length - 1, "ASCII");
+
+ // see if the ET system that the client is
+ // trying to connect to is this one.
+ if (!etName.equals(sys.getName())) {
+ if (config.getDebug() >= EtConstants.debugError) {
+ System.out.println("Tcp Server: client trying to connect to " + etName);
+ }
+ // send error to client
+ out.writeInt(EtConstants.error);
+ out.flush();
+ return;
+ }
+
+ // send ET system info back to client
+ out.writeInt(EtConstants.ok);
+ out.writeInt(EtConstants.endianBig);
+ out.writeInt(config.getNumEvents());
+ out.writeLong(config.getEventSize());
+ out.writeInt(EtConstants.version);
+ out.writeInt(EtConstants.stationSelectInts);
+ out.writeInt(EtConstants.langJava);
+ out.writeInt(EtConstants.bit64);
+ out.writeInt(0);
+ out.flush();
+
+ /* wait for and process client requests */
+ commandLoop();
+
+ return;
+ }
+ catch (IOException ex) {
+ if (config.getDebug() >= EtConstants.debugError) {
+ System.out.println("Tcp Server: IO error in client etOpen");
+ }
+ }
+ finally {
+ // we are done with the socket
+ try {
+ sock.close();
+ }
+ catch (IOException ex) {
+ }
+ }
+ }
+
+
+ /** Wait for and implement commands from the user. */
+ private void commandLoop() {
+
+ // Keep track of all the attachments this client makes
+ // as they may need to be detached if the client dies
+ // without cleanly disconnecting itself. Detaching
+ // takes care of all events that were sent to clients
+ // as events to be modified, but were never put back.
+
+ // for efficiency, keep local copy of constants
+ final int selectInts = EtConstants.stationSelectInts;
+ final int dataShift = EtConstants.dataShift;
+ final int priorityMask = EtConstants.priorityMask;
+ final int dataMask = EtConstants.dataMask;
+ final int modify = EtConstants.modify;
+ final int ok = EtConstants.ok;
+
+ int command;
+ EtEventImpl[] evs = null;
+ HashMap<Integer, AttachmentLocal> attachments =
+ new HashMap<Integer, AttachmentLocal>(sys.getConfig().getAttachmentsMax() + 1);
+ // buffer for sending events to users
+ byte[] buffer = new byte[65535];
+ // buffer for reading command parameters (6 ints worth)
+ byte[] params = new byte[32 + 4 * selectInts];
+
+ // The Command Loop ...
+ try {
+ while (true) {
+ // First, read the remote command. Remember, the
+ // socket has a read timeout of 1/2 second.
+ while (true) {
+ try {
+ command = in.readInt();
+ break;
+ }
+ // socket read timeout
+ catch (InterruptedIOException ex) {
+ // check to see if we've been commanded to die
+ if (sys.killAllThreads()) {
+ return;
+ }
+ }
+ }
+
+ // Since there are so many commands, break up things up a bit,
+ // start off with commands for local clients for use in Linux
+ // or other non-mutex sharing operating systems.
+
+ if (command < EtConstants.netEvGet) {
+ // No local Linux stuff in Java implementation
+ if (config.getDebug() >= EtConstants.debugError) {
+ System.out.println("No Java support for local Linux");
+ }
+ throw new EtReadException("No Java support for local Linux");
+ }
+
+ else if (command < EtConstants.netAlive) {
+
+ switch (command) {
+
+ case EtConstants.netEvGet: {
+ in.readFully(params, 0, 20);
+ int err = ok;
+ int attId = EtUtils.bytesToInt(params, 0);
+ int mode = EtUtils.bytesToInt(params, 4);
+ int mod = EtUtils.bytesToInt(params, 8);
+ int sec = EtUtils.bytesToInt(params, 12);
+ int nsec = EtUtils.bytesToInt(params, 16);
+ AttachmentLocal att = attachments.get(new Integer(attId));
+
+ try {
+ if (mode == EtConstants.timed) {
+ int uSec = sec * 1000000 + nsec / 1000;
+ evs = sys.getEvents(att, mode, uSec, 1);
+ }
+ else if (mode == EtConstants.sleep) {
+ // There's a problem if we have a remote client that is waiting
+ // for another event by sleeping and the events stop flowing. In
+ // that case, the client can be killed and the ET system does NOT
+ // know about it. Since this thread will be stuck in "getEvents",
+ // it will not immediately detect the break in the socket - at least
+ // not until events start flowing again. To circumvent this, implement
+ // "sleep" by repeats of "timed" every few seconds to allow
+ // detection of broken socket between calls to "getEvents".
+
+ // Store the fact we're trying to sleep - necessary when
+ // told to wake up.
+ att.setSleepMode(true);
+
+ tryToGetEvents:
+ while (true) {
+ // try a 4 second wait for an event
+ try {
+ if (att.isWakeUp()) {
+ att.setWakeUp(false);
+ throw new EtWakeUpException("attachment " + att.getId() + " woken up");
+ }
+ evs = sys.getEvents(att, EtConstants.timed, 4000000, 1);
+ // no longer in sleep mode
+ att.setSleepMode(false);
+ // may have been told to wake up between last 2 statements.
+ att.setWakeUp(false);
+ break;
+ }
+ // if timeout, check socket to see if still open
+ catch (EtTimeoutException tx) {
+ try {
+ // 1/2 second max delay on read
+ in.readInt();
+ // should never be able to get here
+ att.setSleepMode(false);
+ throw new EtException("communication protocol error");
+ }
+ // if there's an interrupted ex, socket is OK
+ catch (InterruptedIOException ex) { }
+ }
+ }
+
+ }
+ else {
+ evs = sys.getEvents(att, mode, 0, 1);
+ }
+
+ }
+ catch (EtException ex) {
+ err = EtConstants.error;
+ }
+ catch (EtBusyException ex) {
+ err = EtConstants.errorBusy;
+ }
+ catch (EtEmptyException ex) {
+ err = EtConstants.errorEmpty;
+ }
+ catch (EtWakeUpException ex) {
+ err = EtConstants.errorWakeUp;
+ att.setSleepMode(false);
+ }
+ catch (EtTimeoutException ex) {
+ err = EtConstants.errorTimeout;
+ }
+
+ if (err != ok) {
+ out.writeInt(err);
+ out.flush();
+ break;
+ }
+
+ EtEventImpl ev = evs[0];
+
+ // handle buffering by hand
+ byte[] buf = new byte[4 * (10 + selectInts) + ev.getLength()];
+
+ // first send error
+ EtUtils.intToBytes(err, buf, 0);
+ EtUtils.longToBytes((long)ev.getLength(), buf, 4);
+ EtUtils.longToBytes((long)ev.getMemSize(), buf, 12);
+ EtUtils.intToBytes(ev.getPriority().getValue() |
+ ev.getDataStatus().getValue() << dataShift, buf, 20);
+ EtUtils.intToBytes(ev.getId(), buf, 24); // skip 4 bytes here
+ EtUtils.intToBytes(ev.getRawByteOrder(), buf, 32);
+ // arrays are initialized to zero so skip 0 values elements
+ int index = 36;
+ int[] control = ev.getControl();
+ for (int i = 0; i < selectInts; i++) {
+ EtUtils.intToBytes(control[i], buf, index += 4);
+ }
+ System.arraycopy(ev.getData(), 0, buf, index += 4, ev.getLength());
+
+ out.write(buf);
+ out.flush();
+
+ ev.setModify(Modify.getModify(mod));
+ if (mod == 0) {
+ sys.putEvents(att, evs);
+ }
+ evs = null;
+ }
+ break;
+
+
+ case EtConstants.netEvsGet: {
+ in.readFully(params, 0, 24);
+ int err = ok;
+ int attId = EtUtils.bytesToInt(params, 0);
+ int mode = EtUtils.bytesToInt(params, 4);
+ int mod = EtUtils.bytesToInt(params, 8);
+ int count = EtUtils.bytesToInt(params, 12);
+ int sec = EtUtils.bytesToInt(params, 16);
+ int nsec = EtUtils.bytesToInt(params, 20);
+ AttachmentLocal att = attachments.get(new Integer(attId));
+
+ try {
+ if (mode == EtConstants.timed) {
+ int uSec = sec * 1000000 + nsec / 1000;
+ evs = sys.getEvents(att, mode, uSec, count);
+ }
+ else if (mode == EtConstants.sleep) {
+ // There's a problem if we have a remote client that is waiting
+ // for another event by sleeping and the events stop flowing. In
+ // that case, the client can be killed and the ET system does NOT
+ // know about it. Since this thread will be stuck in "getEvents",
+ // it will not immediately detect the break in the socket - at least
+ // not until events start flowing again. To circumvent this, implement
+ // "sleep" by repeats of "timed" every few seconds to allow
+ // detection of broken socket between calls to "getEvents".
+
+ // Store the fact we're trying to sleep - necessary when
+ // told to wake up.
+ att.setSleepMode(true);
+
+ tryToGetEvents:
+ while (true) {
+ // try a 4 second wait for events
+ try {
+ if (att.isWakeUp()) {
+ att.setWakeUp(false);
+ throw new EtWakeUpException("attachment " + att.getId() + " woken up");
+ }
+ evs = sys.getEvents(att, EtConstants.timed, 4000000, count);
+ // no longer in sleep mode
+ att.setSleepMode(false);
+ // may have been told to wake up between last 2 statements.
+ att.setWakeUp(false);
+ break;
+ }
+ // if timeout, check socket to see if still open
+ catch (EtTimeoutException tx) {
+ try {
+ // 1/2 second max delay on read
+ in.readInt();
+ // should never be able to get here
+ att.setSleepMode(false);
+ throw new EtException("communication protocol error");
+ }
+ // if there's an interrupted ex, socket is OK
+ catch (InterruptedIOException ex) { }
+ }
+ }
+
+ }
+ else {
+ evs = sys.getEvents(att, mode, 0, count);
+ }
+
+ }
+ catch (EtException ex) {
+ err = EtConstants.error;
+ }
+ catch (EtBusyException ex) {
+ err = EtConstants.errorBusy;
+ }
+ catch (EtEmptyException ex) {
+ err = EtConstants.errorEmpty;
+ }
+ catch (EtWakeUpException ex) {
+ err = EtConstants.errorWakeUp;
+ att.setSleepMode(false);
+ }
+ catch (EtTimeoutException ex) {
+ err = EtConstants.errorTimeout;
+ }
+
+ if (err != ok) {
+ out.writeInt(err);
+ out.flush();
+ break;
+ }
+/*
+ // use buffered output
+ // first send number of events
+ out.writeInt(evs.length);
+ int size = evs.length * 4 * (6 + selectInts);
+ for (int j = 0; j < evs.length; j++) {
+ size += evs[j].length;
+ }
+ out.writeInt(size);
+ for (int j = 0; j < evs.length; j++) {
+ evs[j].modify = mod;
+ out.writeInt(evs[j].length);
+ out.writeInt(evs[j].memSize);
+ out.writeInt(evs[j].priority | evs[j].dataStatus << dataShift);
+ out.writeInt(evs[j].id);
+ out.writeInt(evs[j].byteOrder);
+ out.writeInt(0);
+ for (int i = 0; i < selectInts; i++) {
+ out.writeInt(evs[j].control[i]);
+ }
+ out.write(evs[j].data, 0, evs[j].length);
+ }
+ out.flush();
+*/
+ // handle buffering by hand
+ int length, index = 12;
+ int headerSize = 4 * (6 + selectInts);
+ int size = evs.length * headerSize;
+ for (EtEventImpl ev1 : evs) {
+ size += ev1.getLength();
+ }
+
+ EtUtils.intToBytes(evs.length, buffer, 0);
+ EtUtils.longToBytes((long)size, buffer, 4);
+
+ Modify mfy = Modify.getModify(mod);
+ for (EtEventImpl ev : evs) {
+ ev.setModify(mfy);
+ length = ev.getLength();
+ EtUtils.longToBytes((long)length, buffer, index);
+ EtUtils.longToBytes((long)ev.getMemSize(), buffer, index += 8);
+ EtUtils.intToBytes(ev.getPriority().getValue() |
+ ev.getDataStatus().getValue() << dataShift, buffer, index += 8);
+ EtUtils.intToBytes(ev.getId(), buffer, index += 4); // skip 4 bytes here
+ EtUtils.intToBytes(ev.getRawByteOrder(), buffer, index += 8);
+ EtUtils.intToBytes(0, buffer, index += 4);
+ int[] control = ev.getControl();
+ for (int i = 0; i < selectInts; i++) {
+ EtUtils.intToBytes(control[i], buffer, index += 4);
+ }
+ index += 4;
+ if (index + headerSize + length > buffer.length) {
+ out.write(buffer, 0, index);
+ index = 0;
+ if (headerSize + length > buffer.length / 2) {
+ out.write(ev.getData(), 0, length);
+ out.flush();
+ continue;
+ }
+ out.flush();
+ }
+ System.arraycopy(ev.getData(), 0, buffer, index, length);
+ index += length;
+ }
+
+ if (index > 0) {
+ out.write(buffer, 0, index);
+ out.flush();
+ }
+
+ if (mod == 0) {
+ sys.putEvents(att, evs);
+ }
+ evs = null;
+ }
+ break;
+
+
+ case EtConstants.netEvPut: {
+ in.readFully(params, 0, 32 + 4 * selectInts);
+
+ int attId = EtUtils.bytesToInt(params, 0);
+ AttachmentLocal att = attachments.get(new Integer(attId));
+
+ int id = EtUtils.bytesToInt(params, 4);
+ EtEventImpl ev = sys.getEvents().get(id);
+ // skip 4 bytes here
+
+ long len = EtUtils.bytesToLong(params, 12);
+ if (len > Integer.MAX_VALUE) {
+ throw new EtException("Event is too long for this (java) ET system");
+ }
+ ev.setLengthFromServer((int) len);
+
+ int priAndStat = EtUtils.bytesToInt(params, 20);
+ ev.setPriority(Priority.getPriority(priAndStat & priorityMask));
+ ev.setDataStatus(DataStatus.getStatus((priAndStat & dataMask) >> dataShift));
+ ev.setRawByteOrder(EtUtils.bytesToInt(params, 24));
+ // last parameter is ignored
+
+ int index = 24;
+ int[] control = new int[selectInts];
+ for (int i = 0; i < selectInts; i++) {
+ control[i] = EtUtils.bytesToInt(params, index += 4);
+ }
+ ev.setControl(control);
+ // only read data if modifying everything
+ if (ev.getModify() == Modify.ANYTHING) {
+ in.readFully(ev.getData(), 0, ev.getLength());
+ }
+
+ EtEventImpl[] evArray = new EtEventImpl[1];
+ evArray[0] = ev;
+
+ sys.putEvents(att, evArray);
+
+ out.writeInt(ok);
+ out.flush();
+ }
+ break;
+
+
+ case EtConstants.netEvsPut: {
+ in.readFully(params, 0, 16);
+ int attId = EtUtils.bytesToInt(params, 0);
+ AttachmentLocal att = attachments.get(new Integer(attId));
+ int numEvents = EtUtils.bytesToInt(params, 4);
+ long size = EtUtils.bytesToLong(params, 8);
+
+ long len;
+ int id, priAndStat, index;
+ int byteChunk = 28 + 4 * selectInts;
+ evs = new EtEventImpl[numEvents];
+
+ for (int j = 0; j < numEvents; j++) {
+ in.readFully(params, 0, byteChunk);
+
+ id = EtUtils.bytesToInt(params, 0);
+ evs[j] = sys.getEvents().get(id);
+ // skip 4 bytes here
+
+ len = EtUtils.bytesToLong(params, 8);
+ if (len > Integer.MAX_VALUE) {
+ throw new EtException("Event is too long for this (java) ET system");
+ }
+ evs[j].setLengthFromServer((int) len);
+
+ priAndStat = EtUtils.bytesToInt(params, 16);
+ evs[j].setPriority(Priority.getPriority(priAndStat & priorityMask));
+ evs[j].setDataStatus(DataStatus.getStatus((priAndStat & dataMask) >> dataShift));
+ evs[j].setRawByteOrder(EtUtils.bytesToInt(params, 20));
+ index = 24;
+ int[] control = new int[selectInts];
+ for (int i = 0; i < selectInts; i++) {
+ control[i] = EtUtils.bytesToInt(params, index += 4);
+ }
+ evs[j].setControl(control);
+ if (evs[j].getModify() == Modify.ANYTHING) {
+ // If user increased data length beyond memSize,
+ // use more memory.
+ if (evs[j].getLength() > evs[j].getMemSize()) {
+ evs[j].setData(new byte[evs[j].getLength()]);
+ evs[j].setMemSize(evs[j].getLength());
+ }
+ in.readFully(evs[j].getData(), 0, evs[j].getLength());
+ }
+ }
+ sys.putEvents(att, evs);
+ out.writeInt(ok);
+ out.flush();
+ }
+ break;
+
+
+ case EtConstants.netEvNew: {
+ in.readFully(params, 0, 24);
+ int err = ok;
+ int attId = EtUtils.bytesToInt(params, 0);
+ int mode = EtUtils.bytesToInt(params, 4);
+ long size = EtUtils.bytesToLong(params, 8);
+ int sec = EtUtils.bytesToInt(params, 16);
+ int nsec = EtUtils.bytesToInt(params, 20);
+ AttachmentLocal att = attachments.get(new Integer(attId));
+
+ if (bit64 && size > Integer.MAX_VALUE/5) {
+ out.writeInt(EtConstants.errorTooBig);
+ out.writeLong(0L);
+ break;
+ }
+
+ try {
+ if (mode == EtConstants.timed) {
+ int uSec = sec * 1000000 + nsec / 1000;
+ evs = sys.newEvents(att, mode, uSec, 1, (int)size);
+ }
+ else if (mode == EtConstants.sleep) {
+ // There's a problem if we have a remote client that is waiting
+ // for another event by sleeping and the events stop flowing. In
+ // that case, the client can be killed and the ET system does NOT
+ // know about it. Since this thread will be stuck in "getEvents",
+ // it will not immediately detect the break in the socket - at least
+ // not until events start flowing again. To circumvent this, implement
+ // "sleep" by repeats of "timed" every few seconds to allow
+ // detection of broken socket between calls to "getEvents".
+
+ // Store the fact we're trying to sleep - necessary when
+ // told to wake up.
+ att.setSleepMode(true);
+
+ tryToGetEvents:
+ while (true) {
+ // try a 4 second wait for an event
+ try {
+ if (att.isWakeUp()) {
+ att.setWakeUp(false);
+ throw new EtWakeUpException("attachment " + att.getId() + " woken up");
+ }
+ evs = sys.newEvents(att, EtConstants.timed, 4000000, 1, (int)size);
+ // no longer in sleep mode
+ att.setSleepMode(false);
+ // may have been told to wake up between last 2 statements.
+ att.setWakeUp(false);
+ break;
+ }
+ // if timeout, check socket to see if still open
+ catch (EtTimeoutException tx) {
+ try {
+ // 1/2 second max delay on read
+ in.readInt();
+ // should never be able to get here
+ att.setSleepMode(false);
+ throw new EtException("communication protocol error");
+ }
+ // if there's an interrupted ex, socket is OK
+ catch (InterruptedIOException ex) { }
+ }
+ }
+
+ }
+ else {
+ evs = sys.newEvents(att, mode, 0, 1, (int)size);
+ }
+ }
+ catch (EtException ex) {
+ err = EtConstants.error;
+ }
+ catch (EtBusyException ex) {
+ err = EtConstants.errorBusy;
+ }
+ catch (EtEmptyException ex) {
+ err = EtConstants.errorEmpty;
+ }
+ catch (EtWakeUpException ex) {
+ err = EtConstants.errorWakeUp;
+ att.setSleepMode(false);
+ }
+ catch (EtTimeoutException ex) {
+ err = EtConstants.errorTimeout;
+ }
+
+ if (err != ok) {
+ out.writeInt(err);
+ out.writeLong(0);
+ out.flush();
+ break;
+ }
+
+ evs[0].setModify(Modify.ANYTHING);
+
+ out.writeInt(err);
+ out.writeInt(evs[0].getId());
+ out.writeInt(0); // unused
+ out.flush();
+ evs = null;
+ }
+ break;
+
+
+ case EtConstants.netEvsNew: {
+ in.readFully(params, 0, 28);
+ int err = ok;
+ int attId = EtUtils.bytesToInt(params, 0);
+ int mode = EtUtils.bytesToInt(params, 4);
+ long size = EtUtils.bytesToLong(params, 8);
+ int count = EtUtils.bytesToInt(params, 16);
+ int sec = EtUtils.bytesToInt(params, 20);
+ int nsec = EtUtils.bytesToInt(params, 24);
+
+ AttachmentLocal att = attachments.get(new Integer(attId));
+
+ if (bit64 && count*size > Integer.MAX_VALUE/5) {
+ out.writeInt(EtConstants.errorTooBig);
+ break;
+ }
+
+ try {
+ if (mode == EtConstants.timed) {
+ int uSec = sec * 1000000 + nsec / 1000;
+ evs = sys.newEvents(att, mode, uSec, count, (int)size);
+ }
+ else if (mode == EtConstants.sleep) {
+ // There's a problem if we have a remote client that is waiting
+ // for another event by sleeping and the events stop flowing. In
+ // that case, the client can be killed and the ET system does NOT
+ // know about it. Since this thread will be stuck in "getEvents",
+ // it will not immediately detect the break in the socket - at least
+ // not until events start flowing again. To circumvent this, implement
+ // "sleep" by repeats of "timed" every few seconds to allow
+ // detection of broken socket between calls to "getEvents".
+
+ // Store the fact we're trying to sleep - necessary when
+ // told to wake up.
+ att.setSleepMode(true);
+
+ tryToGetEvents:
+ while (true) {
+ // try a 4 second wait for events
+ try {
+ if (att.isWakeUp()) {
+ att.setWakeUp(false);
+ throw new EtWakeUpException("attachment " + att.getId() + " woken up");
+ }
+ evs = sys.newEvents(att, EtConstants.timed, 4000000, count, (int)size);
+ // no longer in sleep mode
+ att.setSleepMode(false);
+ // may have been told to wake up between last 2 statements.
+ att.setWakeUp(false);
+ break;
+ }
+ // if timeout, check socket to see if still open
+ catch (EtTimeoutException tx) {
+ try {
+ // 1/2 second max delay on read
+ in.readInt();
+ // should never be able to get here
+ att.setSleepMode(false);
+ throw new EtException("communication protocol error");
+ }
+ // if there's an interrupted ex, socket is OK
+ catch (InterruptedIOException ex) { }
+ }
+ }
+
+ }
+ else {
+ evs = sys.newEvents(att, mode, 0, count, (int)size);
+ }
+
+ }
+ catch (EtException ex) {
+ err = EtConstants.error;
+ }
+ catch (EtBusyException ex) {
+ err = EtConstants.errorBusy;
+ }
+ catch (EtEmptyException ex) {
+ err = EtConstants.errorEmpty;
+ }
+ catch (EtWakeUpException ex) {
+ err = EtConstants.errorWakeUp;
+ att.setSleepMode(false);
+ }
+ catch (EtTimeoutException ex) {
+ err = EtConstants.errorTimeout;
+ }
+
+ if (err != ok) {
+ out.writeInt(err);
+ out.flush();
+ break;
+ }
+
+ // handle buffering by hand
+ int index = 0;
+ byte[] buf = new byte[4 + 4 * evs.length];
+
+ // first send number of events
+ EtUtils.intToBytes(evs.length, buf, 0);
+ for (EtEventImpl ev : evs) {
+ ev.setModify(Modify.ANYTHING);
+ EtUtils.intToBytes(ev.getId(), buf, index += 4);
+ }
+ out.write(buf);
+ out.flush();
+
+ evs = null;
+ }
+ break;
+
+
+ case EtConstants.netEvDump: {
+ int attId = in.readInt();
+ int id = in.readInt();
+
+ AttachmentLocal att = attachments.get(new Integer(attId));
+ EtEventImpl ev = sys.getEvents().get(id);
+ EtEventImpl[] evArray = new EtEventImpl[1];
+ evArray[0] = ev;
+ sys.dumpEvents(att, evArray);
+
+ out.writeInt(ok);
+ out.flush();
+ }
+ break;
+
+
+ case EtConstants.netEvsDump: {
+ int attId = in.readInt();
+ int numEvents = in.readInt();
+ evs = new EtEventImpl[numEvents];
+ AttachmentLocal att = attachments.get(new Integer(attId));
+
+ int id;
+ byte[] buf = new byte[4 * numEvents];
+ in.readFully(buf, 0, 4 * numEvents);
+ int index = -4;
+
+ for (int j = 0; j < numEvents; j++) {
+ id = EtUtils.bytesToInt(buf, index += 4);
+ evs[j] = sys.getEvents().get(id);
+ }
[truncated at 1000 lines; 805 more skipped]
hps-et-java/src/main/java/org/jlab/coda/et/system
diff -N SystemUdpServer.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ SystemUdpServer.java 13 Feb 2012 22:50:54 -0000 1.3
@@ -0,0 +1,385 @@
+/*----------------------------------------------------------------------------*
+ * Copyright (c) 2001 Southeastern Universities Research Association, *
+ * Thomas Jefferson National Accelerator Facility *
+ * *
+ * This software was developed under a United States Government license *
+ * described in the NOTICE file included as part of this distribution. *
+ * *
+ * Author: Carl Timmer *
+ * [log in to unmask] Jefferson Lab, MS-12H *
+ * Phone: (757) 269-5130 12000 Jefferson Ave. *
+ * Fax: (757) 269-5800 Newport News, VA 23606 *
+ * *
+ *----------------------------------------------------------------------------*/
+
+package org.jlab.coda.et.system;
+
+import java.lang.*;
+import java.io.*;
+import java.net.*;
+import org.jlab.coda.et.*;
+
+/**
+ * This class implements a thread which starts other threads - each of which
+ * listen at a different IP address for users trying to find the ET system by
+ * broadcasting, multicasting, or the direct sending of a udp packet.
+ *
+ * @author Carl Timmer
+ */
+
+class SystemUdpServer extends Thread {
+
+ /** Udp port to listen on. */
+ private int port;
+
+ /** ET system object. */
+ private SystemCreate sys;
+
+ /** ET system configuration. */
+ private SystemConfig config;
+
+
+ /**
+ * Createes a new SystemUdpServer object.
+ * @param sys ET system object
+ */
+ SystemUdpServer(SystemCreate sys) {
+ this.sys = sys;
+ config = sys.getConfig();
+ port = config.getServerPort();
+ }
+
+ /** Starts threads to listen for packets at a different addresses. */
+ public void run() {
+ if (config.getDebug() >= EtConstants.debugInfo) {
+ System.out.println("Running UDP Listening Threads");
+ }
+
+ // use the default port number since one wasn't specified
+ if (port < 1) {
+ port = EtConstants.serverPort;
+ }
+
+ // If we're broadcasting, then we use 1 thread with 1 socket,
+ // bound to the wildcard address, to listen to broadcasts from all local
+ // subnets.
+ //
+ // If we're multicasting and the specified multicast port is the same as the
+ // broadcast port, then we use 1 thread to listen to multicasts and broadcasts
+ // on one socket.
+ //
+ // If we're multicasting with a different port than the broadcasting/direct
+ // port, then multicasting is treated separately from everything else and has
+ // its own socket and thread.
+
+ if (config.getMulticastAddrs().size() > 0) {
+ try {
+System.out.println("setting up for multicast on port " + config.getMulticastPort());
+ MulticastSocket sock = new MulticastSocket(config.getMulticastPort());
+ sock.setReceiveBufferSize(512);
+ sock.setSendBufferSize(512);
+ ListeningThread lis = new ListeningThread(sys, sock);
+ lis.start();
+ }
+ catch (IOException e) {
+ System.out.println("cannot listen on port " + config.getMulticastPort() + " for multicasting");
+ e.printStackTrace();
+ }
+
+ if (config.getMulticastPort() == config.getUdpPort()) {
+ // only need to listen on the multicast socket, so we're done
+ return;
+ }
+ }
+
+ try {
+System.out.println("setting up for broadcast on port " + config.getUdpPort());
+ DatagramSocket sock = new DatagramSocket(config.getUdpPort());
+ sock.setBroadcast(true);
+ sock.setReceiveBufferSize(512);
+ sock.setSendBufferSize(512);
+ ListeningThread lis = new ListeningThread(sys, sock);
+ lis.start();
+ }
+ catch (SocketException e) {
+ e.printStackTrace();
+ }
+ catch (UnknownHostException e) {
+ e.printStackTrace();
+ }
+ }
+}
+
+
+/**
+ * This class implements a thread which listens on a particular address for a
+ * udp packet. It sends back a udp packet with the tcp server port, host name,
+ * and other information necessary to establish a tcp connection between the
+ * tcp server thread of the ET system and the user.
+ *
+ * @author Carl Timmer
+ */
+
+class ListeningThread extends Thread {
+
+ /** ET system object. */
+ private SystemCreate sys;
+
+ /** ET system configuration object. */
+ private SystemConfig config;
+
+ /** Setup a socket for receiving udp packets. */
+ private DatagramSocket sock;
+
+ /** Is this thread responding to a multicast or broadcast or perhaps either. */
+ private int cast;
+
+ /** Don't know which address the broad/multicast was sent to since we're using
+ * "INADDR_ANY" so just return this. */
+ private String incomingAddress = "0.0.0.0";
+
+
+ /**
+ * Creates a new ListeningThread object for a UDP multicasts.
+ *
+ * @param sys ET system object
+ * @param mSock multicast udp socket
+ */
+ ListeningThread(SystemCreate sys, MulticastSocket mSock) throws IOException {
+ this.sys = sys;
+ config = sys.getConfig();
+ for (InetAddress address : config.getMulticastAddrs()) {
+ if (address.isMulticastAddress()) {
+ mSock.joinGroup(address);
+ }
+ }
+ sock = mSock;
+ cast = EtConstants.broadAndMulticast;
+ }
+
+
+ /**
+ * Creates a new ListeningThread object for a UDP broadcasts.
+ *
+ * @param sys ET system object
+ * @param sock udp socket
+ */
+ ListeningThread(SystemCreate sys, DatagramSocket sock) throws UnknownHostException {
+ this.sys = sys;
+ config = sys.getConfig();
+ this.sock = sock;
+ cast = EtConstants.broadcast;
+ }
+
+
+ /**
+ * Starts a single thread to listen for udp packets at a specific address
+ * and respond with ET system information.
+ */
+ public void run() {
+ // packet & buffer to receive UDP packets
+ byte[] rBuffer = new byte[512]; // much larger than needed
+ DatagramPacket rPacket = new DatagramPacket(rBuffer, 512);
+
+ // Prepare output buffer we send in answer to inquiries:
+ //
+ // (0) ET magic numbers (3 ints)
+ // (1) ET version #
+ // (2) port of tcp server thread (not udp config->port)
+ // (3) ET_BROADCAST or ET_MULTICAST (int)
+ // (4) length of next string
+ // (5) broadcast address (dotted-dec) if broadcast received or
+ // multicast address (dotted-dec) if multicast received
+ // (see int #3)
+ // (6) length of next string
+ // (7) hostname given by "uname" (used as a general
+ // identifier of this host no matter which interface is used)
+
+ // (8) length of next string
+ // (9) canonical name of host
+ // (10) number of IP addresses
+ // (11) 32bit, net-byte ordered IPv4 address assoc with following address
+ // (12) length of next string
+ // (13) first dotted-decimal IPv4 address
+ // (14) 32bit, net-byte ordered IPv4 address assoc with following address
+ // (15) length of next string
+ // (16) second dotted-decimal IPv4 address ...
+ //
+ // All known IP addresses are sent here both in numerical & dotted-decimal forms.
+ //
+
+ // buffer for reading ET name
+ byte[] etNameBytes = new byte[EtConstants.fileNameLengthMax];
+
+ // Put outgoing packet into byte array
+ ByteArrayOutputStream baos = null;
+
+ try {
+ InetAddress addr = InetAddress.getLocalHost();
+ String canon = addr.getCanonicalHostName();
+ String hostName = addr.getHostName();
+
+ // the send buffer needs to be of byte size ...
+ int bufferSize = 10*4 + incomingAddress.length() + hostName.length() + canon.length() + 3;
+ for (InetAddress netAddress : sys.getNetAddresses()) {
+ bufferSize += 8 + netAddress.getHostAddress().length() + 1;
+ }
+
+ baos = new ByteArrayOutputStream(bufferSize);
+ DataOutputStream dos = new DataOutputStream(baos);
+
+ // (0) magic #s
+ dos.writeInt(EtConstants.magicNumbers[0]);
+ dos.writeInt(EtConstants.magicNumbers[1]);
+ dos.writeInt(EtConstants.magicNumbers[2]);
+
+ // (1), (2) & (3)
+ dos.writeInt(EtConstants.version);
+ dos.writeInt(config.getServerPort());
+ dos.writeInt(cast);
+
+ // (4) & (5) incomingAddress = 0.0.0.0 since this is Java
+ dos.writeInt(incomingAddress.length() + 1);
+ dos.write(incomingAddress.getBytes("ASCII"));
+ dos.writeByte(0);
+
+ // (6) & (7) Local host name (equivalent to uname?)
+ dos.writeInt(hostName.length() + 1);
+ dos.write(hostName.getBytes("ASCII"));
+ dos.writeByte(0);
+
+ // (8) & (9) canonical host name
+ dos.writeInt(canon.length() + 1);
+ dos.write(canon.getBytes("ASCII"));
+ dos.writeByte(0);
+
+ // (10) number of addresses to follow
+ dos.writeInt(sys.getNetAddresses().length);
+
+ // Send all addresses (32 bit and dot-decimal) associated with this host
+ int addr32;
+ for (InetAddress netAddress : sys.getNetAddresses()) {
+ // convert array of 4 bytes into 32 bit network byte-ordered address
+ addr32 = 0;
+ for (int j = 0; j < 4; j++) {
+ addr32 = addr32 << 8 | (((int) (netAddress.getAddress())[j]) & 0xFF);
+ }
+// System.out.println("sending addr32 = " + addr32 + ", IP addr = " + netAddress.getHostAddress());
+ // (11)
+ dos.writeInt(addr32);
+ // (12)
+ dos.writeInt(netAddress.getHostAddress().length() + 1);
+ // (13)
+ dos.write(netAddress.getHostAddress().getBytes("ASCII"));
+ dos.writeByte(0);
+ }
+
+ dos.flush();
+ }
+ catch (UnsupportedEncodingException ex) {
+ ex.printStackTrace();
+ // this will never happen.
+ }
+ catch (UnknownHostException ex) {
+ ex.printStackTrace();
+ // local host is always known
+ }
+ catch (IOException ex) {
+ ex.printStackTrace();
+ // this will never happen since we're writing to array
+ }
+
+ // construct byte array to send over a socket
+ byte[] sBuffer = baos.toByteArray();
+
+ while (true) {
+ try {
+ // read incoming data without blocking forever
+ while (true) {
+ try {
+//System.out.println("Waiting to receive packet, sock broadcast = " + sock.getBroadcast());
+ sock.receive(rPacket);
+//System.out.println("Received packet ...");
+ break;
+ }
+ // socket receive timeout
+ catch (InterruptedIOException ex) {
+ // check to see if we've been commanded to die
+ if (sys.killAllThreads()) {
+ return;
+ }
+ }
+ }
+
+ // decode the data:
+ // (1) ET magic numbers (3 ints),
+ // (2) ET version #,
+ // (3) length of string,
+ // (4) ET file name
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(rPacket.getData());
+ DataInputStream dis = new DataInputStream(bais);
+
+ int magic1 = dis.readInt();
+ int magic2 = dis.readInt();
+ int magic3 = dis.readInt();
+ if (magic1 != EtConstants.magicNumbers[0] ||
+ magic2 != EtConstants.magicNumbers[1] ||
+ magic3 != EtConstants.magicNumbers[2]) {
+//System.out.println("SystemUdpServer: Magic numbers did NOT match");
+ continue;
+ }
+
+ int version = dis.readInt();
+ int length = dis.readInt();
+//System.out.println("et_listen_thread: received packet version = " + version +
+// ", length = " + length);
+
+ // reject incompatible ET versions
+ if (version != EtConstants.version) {
+ continue;
+ }
+ // reject improper formats
+ if ((length < 1) || (length > EtConstants.fileNameLengthMax)) {
+ continue;
+ }
+
+ // read all string bytes
+ if (length > etNameBytes.length) {
+ etNameBytes = new byte[length];
+ }
+ dis.readFully(etNameBytes, 0, length-1);
+ String etName = new String(etNameBytes, 0, length-1, "US-ASCII");
+
+//System.out.println("et_listen_thread: received packet version = " + version +
+// ", ET = " + etName);
+ if (config.getDebug() >= EtConstants.debugInfo) {
+ System.out.println("et_listen_thread: received packet from " +
+ rPacket.getAddress().getHostName() +
+ " @ " + rPacket.getAddress().getHostAddress() +
+ " for " + etName);
+ }
+
+ // check if the ET system the client wants is ours
+ if (etName.equals(sys.getName())) {
+ // we're the one the client is looking for, send a reply
+ DatagramPacket sPacket = new DatagramPacket(sBuffer, sBuffer.length,
+ rPacket.getAddress(), rPacket.getPort());
+ if (config.getDebug() >= EtConstants.debugInfo) {
+ System.out.println("et_listen_thread: send return packet");
+ }
+ sock.send(sPacket);
+ }
+ }
+ catch (IOException ex) {
+ if (config.getDebug() >= EtConstants.debugError) {
+ System.out.println("error handling UDP packets");
+ ex.printStackTrace();
+ }
+ }
+ }
+ }
+
+
+}
+
hps-et-java/src/main/java/org/jlab/coda/et/test
diff -N EmuTest.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EmuTest.java 13 Feb 2012 22:50:54 -0000 1.3
@@ -0,0 +1,330 @@
+package org.jlab.coda.et.test;
+
+import org.jlab.coda.et.*;
+import org.jlab.coda.et.enums.Mode;
+import org.jlab.coda.et.enums.Modify;
+import org.jlab.coda.jevio.*;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Try to mimic what a evio producer, event builder, and evio consumer do in succession
+ * in order to test the chain of events that the emu goes through.
+ */
+public class EmuTest {
+
+ public EmuTest() {
+ }
+
+
+ private static void usage() {
+ System.out.println("\nUsage: java EmuTest -etin <name of input et> -etout <name of output et>\n" +
+ " [-d <delay>] [-host <host>] [-pin <input et port>] [-pout <output et port>]\n\n" +
+ " -etin input ET system's name\n" +
+ " -etout output ET system's name\n" +
+ " -pin port number for input et udp broadcast\n" +
+ " -pout port number for output et udp broadcast\n" +
+ " -d delay in millisec between getting and putting events\n" +
+ " -g group number of new events to get\n" +
+ " -host host the ET system resides on (defaults to anywhere)\n\n" +
+ " This consumer works by making a connection to the\n" +
+ " ET system's tcp server port.\n");
+ }
+
+
+ /**
+ * Create a simple evio bank for sending.
+ */
+ public static ByteBuffer evioBytes() throws EvioException {
+
+ // count the events we make for testing
+ int eventNumber = 1;
+
+ // use a tag of 2 for no particular reason
+ int tag = 2;
+
+ // bank of banks
+ EventBuilder eventBuilder = new EventBuilder(tag, DataType.BANK, eventNumber);
+ EvioEvent event = eventBuilder.getEvent();
+
+ // add a bank of ints
+ EvioBank bank = new EvioBank(3, DataType.INT32, 0);
+ eventBuilder.appendIntData(bank, new int[] {1,2,3, 0, -1, -2, -3});
+ eventBuilder.addChild(event, bank);
+
+ event.setAllHeaderLengths();
+
+ // write the event
+ ByteBuffer buf = ByteBuffer.allocate(event.getTotalBytes());
+ event.write(buf);
+ buf.flip();
+
+ //System.out.println("Event = \n"+ event2.toXML());
+ return buf;
+ }
+
+
+ /**
+ * Main program for testing.
+ */
+ public static void main(String[] args) {
+
+ String etNameIn = null, etNameOut = null, host = null;
+ int portIn = EtConstants.serverPort, portOut = EtConstants.serverPort;
+ int group = 1;
+ int delay = 0;
+ int size = 32;
+
+ try {
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].equalsIgnoreCase("-etin")) {
+ etNameIn = args[++i];
+ }
+ else if (args[i].equalsIgnoreCase("-etout")) {
+ etNameOut = args[++i];
+ }
+ else if (args[i].equalsIgnoreCase("-host")) {
+ host = args[++i];
+ }
+ else if (args[i].equalsIgnoreCase("-pin")) {
+ try {
+ portIn = Integer.parseInt(args[++i]);
+ if ((portIn < 1024) || (portIn > 65535)) {
+ System.out.println("Input port number must be between 1024 and 65535.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper input port number.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-pout")) {
+ try {
+ portOut = Integer.parseInt(args[++i]);
+ if ((portOut < 1024) || (portOut > 65535)) {
+ System.out.println("Output port number must be between 1024 and 65535.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper output port number.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-s")) {
+ try {
+ size = Integer.parseInt(args[++i]);
+ if (size < 1) {
+ System.out.println("Size needs to be positive int.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper size.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-g")) {
+ try {
+ group = Integer.parseInt(args[++i]);
+ if ((group < 1) || (group > 10)) {
+ System.out.println("Group number must be between 0 and 10.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper group number.");
+ usage();
+ return;
+ }
+ }
+ else if (args[i].equalsIgnoreCase("-d")) {
+ try {
+ delay = Integer.parseInt(args[++i]);
+ if (delay < 1) {
+ System.out.println("delay must be > 0.");
+ usage();
+ return;
+ }
+ }
+ catch (NumberFormatException ex) {
+ System.out.println("Did not specify a proper delay.");
+ usage();
+ return;
+ }
+ }
+ else {
+ usage();
+ return;
+ }
+ }
+
+ if (host == null) {
+ host = EtConstants.hostAnywhere;
+ /*
+ try {
+ host = InetAddress.getLocalHost().getHostName();
+ }
+ catch (UnknownHostException ex) {
+ System.out.println("Host not specified and cannot find local host name.");
+ usage();
+ return;
+ }
+ */
+ }
+
+ if (etNameIn == null || etNameOut == null) {
+ usage();
+ return;
+ }
+
+ ///////////////////////////////////////////////////////////
+ // INPUT
+ ///////////////////////////////////////////////////////////
+
+ // make a direct connection to ET system's tcp server
+ EtSystemOpenConfig configIn = new EtSystemOpenConfig(etNameIn, host, portIn);
+
+ // create ET system object with verbose debugging output
+ EtSystem sysIn = new EtSystem(configIn, EtConstants.debugInfo);
+ sysIn.open();
+
+ // get GRAND_CENTRAL station object
+ EtStation gcIn = sysIn.stationNameToObject("GRAND_CENTRAL");
+
+ // attach to grandcentral
+ EtAttachment gcAttIn = sysIn.attach(gcIn);
+
+ // default configuration of a new station
+ EtStationConfig statConfig = new EtStationConfig();
+
+ // create new station
+ EtStation statIn = sysIn.createStation(statConfig, "in", 1, 0);
+
+ // attach to new station
+ EtAttachment attIn1 = sysIn.attach(statIn);
+
+ ///////////////////////////////////////////////////////////
+ // OUTPUT
+ ///////////////////////////////////////////////////////////
+
+ EtSystemOpenConfig configOut = new EtSystemOpenConfig(etNameOut, host, portOut);
+ EtSystem sysOut = new EtSystem(configOut, EtConstants.debugInfo);
+ sysOut.open();
+ EtStation gcOut = sysOut.stationNameToObject("GRAND_CENTRAL");
+ EtAttachment gcAttOut = sysOut.attach(gcOut);
+ EtStation statOut = sysOut.createStation(statConfig, "out", 1, 0);
+ EtAttachment attOut1 = sysOut.attach(statOut);
+
+ ///////////////////////////////////////////////////////////
+
+ // arrays of events
+ EtEvent[] mevsIn, mevsOut;
+
+ int chunk = 1, count = 0;
+ long t1, t2, counter = 0, totalT = 0, totalCount = 0;
+ double rate, avgRate;
+ int[] con = {1, 2, 3, 4};
+ String s;
+
+ // keep track of time for event rate calculations
+ t1 = System.currentTimeMillis();
+
+ for (int i = 0; i < 50; i++) {
+ while (count < 300000L) {
+ // get array of new events from input ET
+ mevsIn = sysIn.newEvents(gcAttIn, Mode.SLEEP, 0, chunk, 512);
+
+ if (delay > 0) Thread.sleep(delay);
+
+ // put data into events
+ if (true) {
+ for (EtEvent aMevsIn : mevsIn) {
+ ByteBuffer buf = evioBytes();
+ aMevsIn.getDataBuffer().put(buf);
+ int len = buf.position();
+ //aMevsIn.setByteOrder(ByteOrder.LITTLE_ENDIAN);
+ aMevsIn.setLength(len);
+ }
+ }
+
+ // put events back into input ET system
+ sysIn.putEvents(gcAttIn, mevsIn);
+
+ ///////////////////////////////////////////////////////////
+ // now transfer events from one ET system to another
+ ///////////////////////////////////////////////////////////
+
+ // get array of events from input ET
+ mevsIn = sysIn.getEvents(attIn1, Mode.SLEEP, Modify.NOTHING, 0, chunk);
+
+ // get array of new events from output ET
+ mevsOut = sysOut.newEvents(gcAttOut, Mode.SLEEP, 0, mevsIn.length, 2048);
+
+ if (mevsIn.length != mevsOut.length) {
+ System.out.println("NON-matching lengths!!!");
+ }
+
+ for (int j=0; j < mevsOut.length; j++) {
+ ByteBuffer buf = mevsIn[j].getDataBuffer();
+ mevsOut[j].getDataBuffer().put(buf);
+ int len = buf.position();
+ mevsOut[j].setLength(len);
+ }
+
+ // put events back into input & output ET systems
+ sysIn.putEvents(attIn1, mevsIn);
+ sysOut.putEvents(gcAttOut, mevsOut);
+
+ ///////////////////////////////////////////////////////////
+ // now look at events from output ET system
+ ///////////////////////////////////////////////////////////
+
+ // get array of events from input ET
+ mevsOut = sysOut.getEvents(attOut1, Mode.SLEEP, Modify.NOTHING, 0, chunk);
+
+ System.out.println("event's data buffer is " + mevsOut[0].getDataBuffer().order() + ", limit = " + mevsOut[0].getDataBuffer().limit() +
+ ", capacity = " + mevsOut[0].getDataBuffer().capacity());
+ System.out.println("swap = " + mevsOut[0].needToSwap());
+
+ ByteParser parser = new ByteParser();
+ EvioEvent ev = parser.parseEvent(mevsOut[0].getDataBuffer());
+ System.out.println("Event = \n"+ev.toXML());
+
+ sysOut.putEvents(attOut1, mevsOut);
+
+ if (delay > 0) Thread.sleep(delay);
+ count++;
+ }
+
+ // calculate the event rate
+ t2 = System.currentTimeMillis();
+ rate = 1000.0 * ((double) count) / ((double) (t2 - t1));
+ totalCount += count;
+ totalT += t2 - t1;
+ avgRate = 1000.0 * ((double) totalCount) / totalT;
+ System.out.println("rate = " + String.format("%.3g", rate) +
+ " Hz, avg = " + String.format("%.3g", avgRate));
+ count = 0;
+ t1 = System.currentTimeMillis();
+ }
+ System.out.println("End of program, now close et systems");
+ sysIn.close();
+ sysOut.close();
+ }
+ catch (Exception ex) {
+ System.out.println("Error using ET system as emu test");
+ ex.printStackTrace();
+ }
+ }
+
+
+}
CVSspam 0.2.12