Commit fade3520 authored by Lubomir Bulej's avatar Lubomir Bulej

Remove unused code for reflection-based analysis invocation

parent 76eb4501
Pipeline #6731 failed with stages
in 5 minutes and 50 seconds
package ch.usi.dag.shvm;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import ch.usi.dag.dislreserver.remoteanalysis.RemoteAnalysis;
import ch.usi.dag.dislreserver.shadow.ShadowObject;
import ch.usi.dag.dislreserver.shadow.ShadowObjectTable;
import ch.usi.dag.shvm.AnalysisResolver.AnalysisMethodHolder;
import ch.usi.dag.shvm.ArgumentUnmarshaller.UnmarshallerException;
import ch.usi.dag.shvm.SHVMContext.LookupException;
import ch.usi.dag.util.logging.Logger;
/**
* AnalysisHandler class
*
* Handles requests for analysis invocation.
* Handles analysis invocation requests and notifications of thread termination,
* object garbage collection, and client VM termination.
*/
final class AnalysisHandler {
private final Logger __log = Logging.getPackageInstance ();
private final SHVMContext __shvmContext;
private final AnalysisDispatcher __dispatcher;
......@@ -90,137 +82,6 @@ final class AnalysisHandler {
}
private AnalysisInvocation __unmarshalInvocation (
final ByteBuffer rawData
) throws DiSLREServerException {
try {
// *** retrieve method ***
// read method id from network and retrieve method
final short methodId = rawData.getShort ();
final AnalysisMethodHolder amh = null; // __shvmContext.getAnalysisResolver ().getMethod (methodId);
// *** retrieve method argument values ***
final Method method = amh.getAnalysisMethod ();
// read the length of argument data in the request
final short argsLength = rawData.getShort ();
if (argsLength < 0) {
throw new DiSLREServerException (
"invalid length of argument data for analysis method %d (%s.%s): %d",
methodId, method.getDeclaringClass ().getName (),
method.getName (), argsLength
);
}
// read argument values data according to argument types
//
// TODO LB: Consider keeping the result of getParameterTypes() in
// the AnalysisMethodHolder -- otherwise the method argument array
// is cloned on each invocation.
//
final Class <?> [] paramTypes = method.getParameterTypes ();
final Object [] args = new Object [paramTypes.length];
int argsRead = 0;
int argIndex = 0;
for (final Class <?> argClass : paramTypes) {
argsRead += unmarshalArgument (
rawData, argClass, method, argIndex, args
);
argIndex += 1;
}
if (argsRead != argsLength) {
throw new DiSLREServerException (
"received %d, but unmarshalled %d bytes of argument data for analysis method %d (%s.%s)",
argsLength, argsRead, methodId, method.getDeclaringClass ().getName (),
method.getName ()
);
}
// *** create analysis invocation ***
__log.trace (
"dispatching analysis method %d to %s.%s()",
methodId, amh.getAnalysisInstance().getClass().getSimpleName (),
method.getName()
);
return new AnalysisInvocation (
method, amh.getAnalysisInstance (), args
);
} catch (final IOException ioe) {
throw new DiSLREServerException (ioe);
} catch (final IllegalArgumentException iae) {
throw new DiSLREServerException (iae);
}
}
private int unmarshalArgument (
final ByteBuffer rawData, final Class <?> argClass,
final Method analysisMethod, final int index, final Object [] args
) throws IOException, DiSLREServerException {
if (boolean.class.equals (argClass)) {
args [index] = rawData.get () != 0;
return Byte.SIZE / Byte.SIZE;
}
if (char.class.equals (argClass)) {
args [index] = rawData.getChar ();
return Character.SIZE / Byte.SIZE;
}
if (byte.class.equals (argClass)) {
args [index] = rawData.get ();
return Byte.SIZE / Byte.SIZE;
}
if (short.class.equals (argClass)) {
args [index] = rawData.getShort ();
return Short.SIZE / Byte.SIZE;
}
if (int.class.equals (argClass)) {
args [index] = rawData.getInt ();
return Integer.SIZE / Byte.SIZE;
}
if (long.class.equals (argClass)) {
args [index] = rawData.getLong ();
return Long.SIZE / Byte.SIZE;
}
if (float.class.equals (argClass)) {
args [index] = rawData.getFloat ();
return Float.SIZE / Byte.SIZE;
}
if (double.class.equals (argClass)) {
args [index] = rawData.getDouble ();
return Double.SIZE / Byte.SIZE;
}
if (ShadowObject.class.isAssignableFrom (argClass)) {
// zero tag means null
final long tag = rawData.getLong ();
args [index] = (tag == 0) ? null : __shvmContext.getShadowObjectTable().get (tag);
return Long.SIZE / Byte.SIZE;
}
throw new DiSLREServerException (
"Unsupported data type %s in analysis method %s.%s",
argClass.getName (), analysisMethod.getDeclaringClass ().getName (),
analysisMethod.getName ()
);
}
void threadEnded (final long threadId) {
__dispatcher.threadEndedEvent (threadId);
}
......
package ch.usi.dag.shvm;
import java.lang.reflect.Method;
final class AnalysisInvocation {
private final Method __method;
private final Object __target;
private final Object [] __args;
//
AnalysisInvocation (
final Method method, final Object target, final Object [] args
) {
__method = method;
__target = target;
__args = args;
}
void invoke () throws Exception {
__method.invoke (__target, __args);
}
@Override
public String toString () {
return String.format ("%s.%s()",
__method.getDeclaringClass ().getName (),
__method.getName ()
);
}
}
package ch.usi.dag.shvm;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import ch.usi.dag.dislreserver.remoteanalysis.RemoteAnalysis;
/**
* AnalysisResolver class
*
* Takes care of resolving the analysis methods,
* registering their IDs and finding them back.
*
* Each SHVM session should have own instance because of
* different analysis might want to register methods with
* the same name.
*
*/
final class AnalysisResolver {
private static final String METHOD_DELIM = ".";
private final Map <Short, AnalysisMethodHolder> methodMap = new HashMap <> ();
/**
* Cache the analysis classes
*/
private final Map <String, RemoteAnalysis> analysisMap = new HashMap <> ();
/**
* for fast set access - contains all values from analysisMap
*/
private final Set <RemoteAnalysis> analysisSet = new HashSet <> ();
/**
* Holds the instance of analysis and the analysis method.
*/
static final class AnalysisMethodHolder {
private final RemoteAnalysis __analysis;
private final Method __method;
AnalysisMethodHolder(
final RemoteAnalysis analysis, final Method method
) {
__analysis = analysis;
__method = method;
}
RemoteAnalysis getAnalysisInstance () {
return __analysis;
}
Method getAnalysisMethod () {
return __method;
}
}
/**
* Resolves the analysis method using the given fully qualified method name.
* The name includes package name(s) and class name(s) and ends with a
* method name. Method signature is not supported.
*
* @param methodQualifier
* Fully qualified name of the method (containing class name).
* @return An {@link AnalysisMethodHolder} instance associating and analysis
* method with a {@link RemoteAnalysis} instance.
* @throws DiSLREServerException
* If the method qualifier cannot be resolved.
*/
private AnalysisMethodHolder resolveMethod (
final String methodQualifier
) throws DiSLREServerException {
try {
final int splitIndex = methodQualifier.lastIndexOf (METHOD_DELIM);
final String className = methodQualifier.substring (0, splitIndex);
final String methodName = methodQualifier.substring (splitIndex + 1);
// Resolve or create analysis instance.
RemoteAnalysis analysis = analysisMap.get (className);
if (analysis == null) {
final Class <? extends RemoteAnalysis> analysisClass =
Class.forName (className).asSubclass (RemoteAnalysis.class);
analysis = analysisClass.newInstance ();
analysisMap.put (className, analysis);
analysisSet.add (analysis);
}
// Resolve analysis method.
final Method analysisMethod = __getAnalysisMethod (analysis, methodName);
return new AnalysisMethodHolder (analysis, analysisMethod);
}
catch (final ClassCastException | ReflectiveOperationException e) {
throw new DiSLREServerException (
e, "failed to resolve analysis method %s", methodQualifier
);
}
}
/**
* Obtains the instance of RemoteAnalysis class and extracts the method with given name.
*
* @param analysis
* @param methodName
* @return Method
* @throws DiSLREServerException
*/
private Method __getAnalysisMethod (
final RemoteAnalysis analysis, final String methodName
) throws DiSLREServerException {
final Class <?> analysisClass = analysis.getClass ();
final List <Method> methods = new ArrayList <> ();
for (final Method analysisMethod : analysisClass.getMethods ()) {
if (analysisMethod.getName ().equals (methodName)) {
methods.add (analysisMethod);
}
}
//
// Throw an exception if there are multiple methods
//
final int methodCount = methods.size ();
if (methodCount == 1) {
return methods.get (0);
} else if (methodCount > 1) {
throw new DiSLREServerException (
"class '%s' has multiple methods matching '%s'",
analysisClass.getName (), methodName
);
} else {
throw new DiSLREServerException (
"class '%s' has no method matching '%s'",
analysisClass.getName (), methodName
);
}
}
/**
* Retrieves the (previously registered) method mapped to the give method
* id.
*
* @param methodId
* The analysis method id.
* @return The {@link AnalysisMethodHolder} instance corresponding to the
* method id.
* @throws DiSLREServerException
* If there is no method associated with the method id.
*/
AnalysisMethodHolder getMethod (
final short methodId
) throws DiSLREServerException {
final AnalysisMethodHolder result = methodMap.get (methodId);
if (result != null) {
return result;
}
throw new DiSLREServerFatalException ("invalid analysis method id: " + methodId);
}
/**
* Resolves the given method qualifier into an {@link AnalysisMethodHolder}
* which associates the method with a {@link RemoteAnalysis} instance and
* registers the method holder under the given method id.
*
* @param methodId
* Method id to register the resolved analysis method with.
* @param methodQualifier
* The fully qualified name of the method (including class name).
* @throws DiSLREServerException
* If the method qualifier cannot be resolved.
*/
void registerMethodId (
final short methodId, final String methodQualifier
) throws DiSLREServerException {
// TODO LB: method resolution should be done upstream.
methodMap.put (methodId, resolveMethod (methodQualifier));
}
/**
* Retrieves all {@link RemoteAnalysis} instances.
*
* @return Set of all {@link RemoteAnalysis} instances.
*/
Set <RemoteAnalysis> getAllAnalyses () {
return analysisSet;
}
}
......@@ -153,7 +153,7 @@ public final class SHVMImpl implements SHVM {
* @param methodQualifier
* Fully qualified method name without signature.
* @throws DiSLREServerException
* If analysis registraction fails.
* If analysis registration fails.
*/
@Override
public void HandleRegisterAnalysis (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment