Commit in hps-et-java/src/main/java/org/jlab/coda/et on MAIN | |||
EtAttachment.java | +167 | 1.2 -> 1.3 | |
EtConstants.java | +479 | 1.2 -> 1.3 | |
EtEvent.java | +216 | 1.2 -> 1.3 | |
EtEventImpl.java | +648 | 1.2 -> 1.3 | |
EtEventSelectable.java | +36 | 1.2 -> 1.3 | |
EtJniAccess.java | +250 | 1.2 -> 1.3 | |
EtStation.java | +587 | 1.2 -> 1.3 | |
EtStationConfig.java | +399 | 1.2 -> 1.3 | |
EtStationSelection.java | +41 | 1.2 -> 1.3 | |
EtSystem.java | +2700 | 1.2 -> 1.3 | |
EtSystemOpen.java | +1471 | 1.2 -> 1.3 | |
EtSystemOpenConfig.java | +804 | 1.2 -> 1.3 | |
EtUtils.java | +291 | 1.2 -> 1.3 | |
apps/Blaster.java | +280 | 1.2 -> 1.3 | |
/Consumer.java | +267 | 1.2 -> 1.3 | |
/EtMonitor.java | +548 | 1.2 -> 1.3 | |
/EvioProducer.java | +314 | 1.2 -> 1.3 | |
/Producer.java | +271 | 1.2 -> 1.3 | |
/StartEt.java | +226 | 1.2 -> 1.3 | |
data/AllData.java | +52 | 1.2 -> 1.3 | |
/AttachmentData.java | +214 | 1.2 -> 1.3 | |
/ProcessData.java | +114 | 1.2 -> 1.3 | |
/StationData.java | +347 | 1.2 -> 1.3 | |
/SystemData.java | +398 | 1.2 -> 1.3 | |
enums/Age.java | +79 | 1.2 -> 1.3 | |
/DataStatus.java | +80 | 1.2 -> 1.3 | |
/Mode.java | +82 | 1.2 -> 1.3 | |
/Modify.java | +85 | 1.2 -> 1.3 | |
/Priority.java | +76 | 1.2 -> 1.3 | |
exception/EtBusyException.java | +38 | 1.2 -> 1.3 | |
/EtDeadException.java | +20 | 1.2 -> 1.3 | |
/EtEmptyException.java | +37 | 1.2 -> 1.3 | |
/EtException.java | +36 | 1.2 -> 1.3 | |
/EtExistsException.java | +37 | 1.2 -> 1.3 | |
/EtReadException.java | +36 | 1.2 -> 1.3 | |
/EtTimeoutException.java | +36 | 1.2 -> 1.3 | |
/EtTooManyException.java | +39 | 1.2 -> 1.3 | |
/EtWakeUpException.java | +38 | 1.2 -> 1.3 | |
/EtWriteException.java | +36 | 1.2 -> 1.3 | |
monitorGui/Monitor.java | +2048 | 1.2 -> 1.3 | |
/MonitorConfiguration.java | +814 | 1.2 -> 1.3 | |
/MonitorFonts.java | +36 | 1.2 -> 1.3 | |
/MonitorSingleSystem.java | +1826 | 1.2 -> 1.3 | |
/WholeNumberField.java | +162 | 1.2 -> 1.3 | |
system/AttachmentLocal.java | +286 | 1.2 -> 1.3 | |
/EventList.java | +595 | 1.2 -> 1.3 | |
/StationLocal.java | +942 | 1.2 -> 1.3 | |
/SystemConfig.java | +448 | 1.2 -> 1.3 | |
/SystemCreate.java | +1962 | 1.2 -> 1.3 | |
/SystemTcpServer.java | +1801 | 1.2 -> 1.3 | |
/SystemUdpServer.java | +385 | 1.2 -> 1.3 | |
test/EmuTest.java | +330 | 1.2 -> 1.3 | |
+23510 |
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); + } +} + + +
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; +}
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(); +}
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; + } + +}
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); + +}
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; +}
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; + } + + +}
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; + } +}
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; + } +}
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]
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]
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; + } + + +}
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; + } + + + + +}
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(); + } + } + +}
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(); + } + } + +}
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); + + } + + + + +}
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(); + } + } + + +}
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(); + } + } + +}
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(); + } + + } +}
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[]; +}
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"); + } +} + + +
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(); + } + } +} + + + + + + +
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"); + } + + } +} +
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"); + } + +}
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; + } +}
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; + } + +}
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; + } + +}
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; + } + + +}
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; + } + +}
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); + } + +}
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); + } + +}
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); + } + +}
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); + } + +}
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); + } + +}
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); + } + +}
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); + } + +}
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); + } + +} +
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); + } + +}
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); + } + +}
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]
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) {} + } + + +}
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; +}
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]
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); + } + } +}
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; + } + + +} + + +
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; + } +}
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 + + +}
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; + } +} +
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]
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]
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(); + } + } + } + } + + +} +
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(); + } + } + + +}
Use REPLY-ALL to reply to list
To unsubscribe from the LCD-CVS list, click the following link:
https://listserv.slac.stanford.edu/cgi-bin/wa?SUBED1=LCD-CVS&A=1