sofya.ed.structural
Class SocketProbe

java.lang.Object
  extended by sofya.ed.structural.SocketProbe
All Implemented Interfaces:
java.lang.Runnable, SConstants

public final class SocketProbe
extends java.lang.Object
implements SConstants, java.lang.Runnable

The SocketProbe class is responsible for transmitting instrumentation trace statements from the subject to the event dispatcher. It is calls to methods implemented by this class which are actually inserted into subjects by the instrumentor.

This class establishes a persistent socket connection to the event dispatcher on a specified port and implements the instrumentation methods which send trace messages to the dispatcher over that socket. The instrumentor is responsible for inserting a call to the start method of this class as the first executable instruction of a subject class. This will create an instance of this class which has connected a socket to the dispatcher and is kept alive as a daemon thread.

To enable this mechanism to work with the greatest possible genericity, and to avoid naming and dynamic linking conflicts when an instrumented dispatcher is being run as a subject, this class is handled in a special fashion. When a dispatcher runs, it constructs a jar file which contains this class (among others) and prepends the jar file to the bootstrap classpath for the subject. Thus when a subject seeks to resolve a call to the static methods implemented by this class, the first definition of the class to be located by the class loader is the one provided on the bootstrap classpath, including when the subject is an instrumented dispatcher. However, since the bootstrap classpath contains no other Sofya related classes (except SConstants, which as an* interface contains no code, and is universally backwards compatible), all other subject classes will be found by the class loader in their expected locations on the subject's own classpath. Note that this also means that the SocketProbe runs inside the same JVM that is running the subject, so the fact that an instrumented dispatcher locates the shared SocketProbe before it locates its own is not problematic (it will however copy its own SocketProbe when constructing its own jar file for its subject).

When the SocketProbe itself is instrumented, the instrumentor inserts special calls to methods of the same name in a class named SocketProbeAlt. That class is created dynamically by the invoking dispatcher at runtime, as a clone of its SocketProbe, and shared in the same manner. This permits the instrumented SocketProbe to call instrumentation methods that do not resolve to itself and cause infinite recursion.

With this mechanism it is possible to create a chain of dispatchers executing other dispatchers as subjects, although intervention to set the ports correctly is required beyond the first subject dispatcher. This is likely only useful up to the second level of self analysis, as data obtained from further chaining is redundant. (The first level of sel analysis will provide trace information for the SocketProcessingStrategy.processProbesSynchronized(java.net.Socket, sofya.ed.structural.ControlData) method and the second level of self analysis will provide trace information for SocketProcessingStrategy.processProbes(java.net.Socket, sofya.ed.structural.ControlData)).

Version:
08/04/2006
Author:
Alex Kinneer
See Also:
ProgramEventDispatcher, cfInstrumentor

Nested Class Summary
 
Nested classes/interfaces inherited from interface sofya.base.SConstants
SConstants.BlockLabel, SConstants.BlockObjectType, SConstants.BlockSubType, SConstants.BlockType, SConstants.BranchObjectType, SConstants.BranchType, SConstants.EDObjectType, SConstants.TraceObjectType
 
Field Summary
protected static int BRANCH_EXIT_MARKER
          Constant which marks in the sequence array that the current method is exiting.
protected static int NEW_METHOD_MARKER
          Constant which marks that the next element in the object sequence array contains the index to a new method signature.
static int[] sequenceArray
          Array which stores the hit object IDs sequentially, using special marker/index pairs to indicate entry into new methods.
static int sequenceIndex
          Index pointing to the next open entry in the sequence array.
 
Fields inherited from interface sofya.base.SConstants
DEFAULT_PORT, INST_COMPATIBLE, INST_OLD_UNSUPPORTED, INST_OPT_NORMAL, INST_OPT_SEQUENCE, SIG_CHKALIVE, SIG_ECHO
 
Constructor Summary
protected SocketProbe(int port)
          Standard constructor.
 
Method Summary
static void finish()
           
static byte[] getObjectArray(java.lang.String mSignature, int objCount)
          Gets the byte array recording which trace objects have been witnessed in a given method.
static void markMethodInSequence(java.lang.String mSignature, int objCount)
          Inserts a new method marker and index into the sequence array.
 void run()
          Runs the (daemon) thread.
static void start(int port, int _instMode, boolean _doTimestamps, boolean _useSignalSocket, int _objType)
          Creates SocketProbe and starts daemon thread to keep it memory resident.
static void writeObjectCount(java.lang.String mSignature, int objCount)
          Writes the number of objects (trace entities) in the current method to the socket so that the event dispatcher can notify listeners.
static void writeSequenceData()
          Writes the current contents of the object sequence array to the socket to be relayed to listeners by the event dispatcher.
static void writeTraceMessage(int bId, java.lang.String mSignature)
          Transmits a trace message to the event dispatcher via the socket.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

NEW_METHOD_MARKER

protected static final int NEW_METHOD_MARKER
Constant which marks that the next element in the object sequence array contains the index to a new method signature.

See Also:
Constant Field Values

BRANCH_EXIT_MARKER

protected static final int BRANCH_EXIT_MARKER
Constant which marks in the sequence array that the current method is exiting.

See Also:
Constant Field Values

sequenceArray

public static int[] sequenceArray
Array which stores the hit object IDs sequentially, using special marker/index pairs to indicate entry into new methods. It is public so that the instrumentation is not required to make a method call to retrieve a reference to it.


sequenceIndex

public static int sequenceIndex
Index pointing to the next open entry in the sequence array. Instrumentation is responsible for updating this pointer when recording an object ID, and calling writeSequenceData when the array is filled.

Constructor Detail

SocketProbe

protected SocketProbe(int port)
Standard constructor.

Attempts to open the static socket used to send trace messages to the event dispatcher. This constructor should be called by start(int, int, boolean, boolean, int), which will be invoked by the subject with the port number embedded by the Instrumentor. Naturally, if the subject is instrumented on a different port than the event dispatcher is listening on, this action will fail. If the connection cannot be made, the system exits (an action which will occur before any subject code is executed).

Parameters:
port - Port number to be used to connect the socket. This should be set by the instrumentor and supplied by the subject via a call to start(int, int, boolean, boolean, int).
Method Detail

start

public static void start(int port,
                         int _instMode,
                         boolean _doTimestamps,
                         boolean _useSignalSocket,
                         int _objType)
Creates SocketProbe and starts daemon thread to keep it memory resident.

Creates an instance of the SocketProbe connected to the specified port. Once the SocketProbe is created it is executed in a daemon thread. This guarantees that the same SocketProbe object will handle all instrumentation and ensures that the underlying socket remains persistent. It is run as a daemon thread to ensure that it is terminated automatically when the subject is finished. The thread itself does not take any action (See run()). If this method has already been called by the current subject, it returns immediately without taking any action.

The Instrumentor should guarantee that a call to this method is inserted into the subject class as the first possible executable statement in the class, either in the static initializer (<clinit>) or in main. This will ensure that all instrumentation is sent correctly. If SocketProbe itself is instrumented, a call to this method on SocketProbeAlt (the clone of the invoking filter's SocketProbe, see ProgramEventDispatcher) will be inserted in its static initializer, which allows the SocketProbe to be traced without introducing infinite recursion scenarios.

If the subject being run is an event dispacher, the subject dispatcher's SocketProbe will be running in its own subject's JVM. As a result, to trace the SocketProbe (logically considered a component of the subject event dispatcher), the main invoking dispatcher will need to accept two instrumentation connections, one from the subject event dispatcher and one from the SocketProbe. This requires it to synchronize the trace messages it receives. To make this possible, the doTimestamping flag should be set by the instrumentor, which will cause the SocketProbe to insert timestamps at the front of each trace message, which can then be used by the event dispatcher to order the trace messages. Under no other circumstance should this flag be set. (See ProgramEventDispatcher).

All parameters should be set by the instrumentor.

Parameters:
port - Port number to be used to connect the socket.
_instMode - Integer flag specifying the type of instrumentation present in the subject.
_doTimestamps - Flag indicating whether trace messages are to be timestamped. This is only used with the subject is an event dispatcher.
_useSignalSocket - Flag indicating whether a signal socket connection should be made to the event dispatcher. This is only used when the subject is an event dispatcher.
_objType - Integer flag specifying the type of program entity traced by the instrumentation present in the subject.

finish

public static void finish()

run

public void run()
Runs the (daemon) thread.

The run method simply sleeps indefinitely, so as to keep the same instance of the SocketProbe alive. Note that the run method is uninterruptable. Instead, since it is running as a daemon thread, it will die automatically when the subject exits.

Specified by:
run in interface java.lang.Runnable

writeTraceMessage

public static void writeTraceMessage(int bId,
                                     java.lang.String mSignature)
Transmits a trace message to the event dispatcher via the socket.

The correct port should be set by start(int, int, boolean, boolean, int) and thus will be known internally as part of the state of the SocketProbe object. Since the SocketProbe object is kept resident by the daemon thread, any class throughout the subject can call this method and successfully transmit a message, assuming start(int, int, boolean, boolean, int) has been called previously.

A single threaded subject can only call this method sequentially, resulting in typical in-order processing of trace statements. Multithreaded subjects, however, may call this method from different threads, in which case the order of processing of trace statements is not guaranteed to be deterministic. The actual transmission of the message through the socket is synchronized, however, ensuring that the message will not be corrupted.

This method will not block unless the buffer of the underlying socket has been filled.

Parameters:
bId - The ID of the trace object marked by this instrumentation probe.
mSignature - Full signature of the method which contains the trace object being marked.

getObjectArray

public static byte[] getObjectArray(java.lang.String mSignature,
                                    int objCount)
Gets the byte array recording which trace objects have been witnessed in a given method.

If this is the first time the method has been traced (or the method has been removed from the cache), an array of the necessary size is allocated and initialized. Calls to this method are inserted at the beginning of methods in the subject by the instrumentor.

Parameters:
mSignature - Signature of the method for which the byte array is to be retrieved. The signature guarantees uniqueness.
objCount - Number of trace objects in the method, used only when the array must be allocated. This value should be determined by the CFG builder and set by the instrumentor.
Returns:
The byte array recording trace objects witnessed in the method.

markMethodInSequence

public static void markMethodInSequence(java.lang.String mSignature,
                                        int objCount)
Inserts a new method marker and index into the sequence array.

A map is checked to see if an index has already been created for the given signature string. If it has, the existing index is retrieved, otherwise a new index is created and added. A new method marker is then inserted, followed by the index to the signature string. The index pointer is advanced by two so that it is left pointing to the next open element in the array. If advancing the pointer two elements will exceed the size of the array, the array is first committed to the trace and the pointer is reset to zero before proceeding.

Parameters:
mSignature - Signature of the method which has been entered and needs to be marked in the array.
objCount - Number of trace objects in the method.

writeSequenceData

public static void writeSequenceData()
Writes the current contents of the object sequence array to the socket to be relayed to listeners by the event dispatcher.

New-method markers are used to transmit object IDs in a series of chunks associated with the correct method signature string. If the array begins with a continuation of object IDs for a method from the previous contents of the array, the currentMethodSig field is used to properly associate the objects with that method. When this method returns, all of the object IDs currently in the array will have been transmitted to the filter and the array index pointer reset to zero.


writeObjectCount

public static void writeObjectCount(java.lang.String mSignature,
                                    int objCount)
Writes the number of objects (trace entities) in the current method to the socket so that the event dispatcher can notify listeners.

Parameters:
mSignature - Signature of the method for which the object count is being sent.
objCount - Number of objects in the method.