...
 
Commits (83)
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="output/build/disl" path="src-disl"/>
<classpathentry kind="src" output="output/build/shvm" path="src-shvm"/>
<classpathentry kind="src" output="output/build/util" path="src-util"/>
<classpathentry kind="src" output="output/build/test" path="src-test"/>
<classpathentry kind="src" output="output/build/shvm-dispatch" path="src-shvm-dispatch"/>
......@@ -25,6 +24,24 @@
<classpathentry kind="src" path="disl/src/src-annotation"/>
<classpathentry kind="src" path="disl/src/src-context"/>
<classpathentry kind="src" path="disl/src-test"/>
<classpathentry kind="src" path="shvm/src/src-dislreserver"/>
<classpathentry kind="src" path="shvm/src/src-msg-analyze"/>
<classpathentry kind="src" path="shvm/src/src-msg-close"/>
<classpathentry kind="src" path="shvm/src/src-msg-classinfo"/>
<classpathentry kind="src" path="shvm/src/src-msg-newclass"/>
<classpathentry kind="src" path="shvm/src/src-msg-objfree"/>
<classpathentry kind="src" path="shvm/src/src-msg-reganalysis"/>
<classpathentry kind="src" path="shvm/src/src-msg-instr"/>
<classpathentry kind="src" path="shvm/src/src-msg-stringinfo"/>
<classpathentry kind="src" path="shvm/src/src-msg-threadend"/>
<classpathentry kind="src" path="shvm/src/src-msg-threadinfo"/>
<classpathentry kind="src" path="shvm/src/src-msg-analyze-mtdispatch"/>
<classpathentry kind="src" path="shvm/src/src-remoteanalysis"/>
<classpathentry kind="src" path="shvm/src/src-reqdispatch"/>
<classpathentry kind="src" path="shvm/src/src-shadow"/>
<classpathentry kind="src" path="shvm/src/src-util"/>
<classpathentry kind="src" path="shvm/src/src-server-api"/>
<classpathentry kind="src" path="shvm/src-test"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="output/lib/disl-bypass.jar"/>
<classpathentry kind="lib" path="lib/disl/log4j.jar" sourcepath="lib/devel/log4j-source.jar"/>
......
# Backup files
*~
# Generated dependency files
src-disl-agent/*.d
src-disl-agent/linux-*
src-disl-agent/windows-*
*.d
# Compiled shared libraries
*.so
......@@ -17,12 +18,15 @@ examples/**/*.jar
# Logs
*.log
# Output directories
src-disl-agent/linux-*
src-disl-agent/windows-*
# Anything in the output
output/*
# Libraries
# Runtime libraries
lib/*/*.jar
# Fallout from method uid generator
methodid.txt
......@@ -6,17 +6,17 @@ cache: &cache
key: "${CI_COMMIT_REF_SLUG}"
# Cache deps and compiled classes
paths:
- 'output/'
- 'lib/'
- 'src-disl-agent/linux-x86_64' # Specific architecture of used container
- 'output/'
- 'lib/'
- 'src-disl-agent/linux-x86_64' # Specific architecture of used container
# Adjust modification date to prevent recompiling sources in different stages.
before_script:
- find . -exec touch -t 200001010000 {} \;
- find . -exec touch -t 200001010000 {} \;
stages:
- build
- test
- build
- test
# Jobs definitions
# The YAML Anchors are used because of Gitlab Issue#2838
......@@ -29,13 +29,29 @@ build:
policy:
push
script:
- ant build
- ant build
# Run tests
test:
test compound:
stage: test
cache:
<<: *cache
policy: pull
script:
- ant test
- ant test-compound
test disl:
stage: test
cache:
<<: *cache
policy: pull
script:
- ant test-disl
test shvm:
stage: test
cache:
<<: *cache
policy: pull
script:
- ant test-shvm
......@@ -18,7 +18,7 @@ src.examples=examples
disl.bypass.lib=disl-bypass.jar
disl.agent.lib.base=dislagent
shvm.lib=dislre-server.jar
shvm.dispatch.lib=dislre-dispatch.jar
shvm.agent.lib.base=dislreagent
......
......@@ -278,7 +278,7 @@
</path>
<path id="shvm.classpath">
<pathelement location="${build.shvm}"/>
<pathelement location="${src.shvm.prefix}/${build.shvm}"/>
<pathelement location="${build.shvm.dispatch}"/>
</path>
</target>
......@@ -633,28 +633,13 @@
<target name="compile-shvm" depends="compile-util,compile-shvm-dispatch">
<mkdir dir="${build.shvm}"/>
<javac destdir="${build.shvm}" srcdir="${src.shvm}" debug="true">
<classpath refid="util.classpath"/>
<classpath refid="asm.classpath"/>
</javac>
<ant antfile="${src.shvm.prefix}/build.xml" target="compile" usenativebasedir="true"/>
</target>
<target name="build-shvm" depends="compile-shvm,build-shvm-dispatch">
<local name="shvm.server.class"/>
<find-class property="shvm.server.class" dir="${build.shvm}" name="DiSLREServer"/>
<jar destfile="${out.lib}/${shvm.lib}">
<manifest>
<attribute name="Class-Path" value="${asm.libs}"/>
<attribute name="Main-Class" value="${shvm.server.class}"/>
<attribute name="DiSL-Version" value="${disl.version}"/>
</manifest>
<fileset dir="${build.util}"/>
<fileset dir="${build.shvm}"/>
</jar>
<ant antfile="${src.shvm.prefix}/build.xml" target="build" usenativebasedir="true"/>
<copy file="${src.shvm.prefix}/${out.lib}/${shvm.lib}" tofile="${out.lib}/${shvm.lib}" />
</target>
<!-- Shadow VM agent -->
......@@ -786,12 +771,22 @@
</sequential>
</macrodef>
<!-- Run nested instrumentation library tests -->
<target name="disl-test">
<!-- Run the instrumentation library unit tests -->
<target name="test-disl">
<ant antfile="${src.disl.prefix}/build.xml" target="test" usenativebasedir="true"/>
</target>
<target name="test" depends="build,build-test,disl-test" description="Runs all tests or a selected (-Dtest.name=...) test suite.">
<!-- Run the shadow VM unit tests -->
<target name="test-shvm">
<ant antfile="${src.shvm.prefix}/build.xml" target="test" usenativebasedir="true" />
</target>
<!-- Run all tests -->
<target name="test" depends="test-disl,test-shvm,test-compound"></target>
<!-- Run compound tests -->
<target name="test-compound" depends="build,build-test" description="Runs all tests or a selected (-Dtest.name=...) test suite.">
<!--
If test.name is set to a name of a test suite, only include the test suite
in the batch of tests to be run, otherwise include all tests and suites.
......@@ -830,7 +825,7 @@
<pathelement location="${build.util}"/>
<pathelement location="${src.disl-server.prefix}/${build.disl-server}" />
<pathelement location="${src.disl.prefix}/${build.disl}"/>
<pathelement location="${build.shvm}"/>
<pathelement location="${src.shvm.prefix}/${build.shvm}" />
</classpath>
<!-- pass properties starting with "disl.", "dislserver.", and "dislreserver." to the tests -->
......@@ -1066,16 +1061,13 @@
<ant dir="${src.examples}" target="clean"/>
</target>
<target name="clean-disl">
<ant dir="${src.disl.prefix}" target="clean" />
</target>
<target name="clean-disl-server">
<ant dir="${src.disl-server.prefix}" target="clean" />
</target>
<target name="clean" description="Removes all files produced during the build.">
<ant dir="${src.shvm.prefix}" target="clean" />
<ant dir="${src.disl-server.prefix}" target="clean" />
<ant dir="${src.disl.prefix}" target="clean" />
<target name="clean" depends="clean-disl, clean-disl-server" description="Removes all files produced during the build.">
<exec executable="make" dir="${src.disl.agent}">
<arg value="cleanall"/>
</exec>
......
......@@ -18,8 +18,10 @@ build.ivy.file = dependencies.xml
src.bin=bin
src.disl.prefix=disl
src.disl-server.prefix=disl-server
src.shvm.prefix=shvm
disl.lib=disl-server.jar
shvm.lib=dislre-server.jar
# Base output directory
out.dir=output
......
# Shadow VM server
# Build properties related to the SHVM package
src.shvm.test=src-test
build.shvm.test=${build.dir}/test
<project name="disl-server" default="build" basedir=".">
<!--
Import required property files.
-->
<property file="../common.properties"/>
<property file="build.properties" />
<property file="../disl.version.properties" />
<!--
Initialize the build directory
-->
<target name="init">
<mkdir dir="${build.shvm}" />
<mkdir dir="${build.shvm.test}" />
</target>
<!--
Dependency class paths
-->
<path id="asm.classpath">
<fileset dir="../${lib.disl.dir}" includes="asm*.jar" id="asm.fileset"/>
</path>
<path id="util.classpath">
<pathelement location="../${build.util}"/>
</path>
<path id="junit.classpath">
<fileset dir="../${lib.test.dir}" includes="*.jar"/>
</path>
<path id="protobuf.classpath">
<fileset dir="../${lib.disl.dir}" includes="protobuf*.jar"/>
</path>
<!--
Refer to the parent targets
-->
<target name="compile-util">
<ant antfile="../build.xml" target="compile-util" usenativebasedir="true" />
</target>
<target name="compile-shvm-dispatch">
<ant antfile="../build.xml" target="compile-shvm-dispatch" usenativebasedir="true" />
</target>
<target name="build-shvm-dispatch">
<ant antfile="../build.xml" target="build-shvm-dispatch" usenativebasedir="true" />
</target>
<!-- SHVM Server -->
<target name="compile" depends="compile-util,compile-shvm-dispatch,init">
<javac destdir="${build.shvm}" debug="true">
<src path="src/src-dislreserver" />
<src path="src/src-msg-analyze" />
<src path="src/src-msg-analyze-mtdispatch" />
<src path="src/src-msg-classinfo" />
<src path="src/src-msg-close" />
<src path="src/src-msg-instr" />
<src path="src/src-msg-newclass" />
<src path="src/src-msg-objfree" />
<src path="src/src-msg-reganalysis" />
<src path="src/src-msg-stringinfo" />
<src path="src/src-msg-threadend" />
<src path="src/src-msg-threadinfo" />
<src path="src/src-remoteanalysis" />
<src path="src/src-reqdispatch" />
<src path="src/src-server-api" />
<src path="src/src-shadow" />
<src path="src/src-util" />
<classpath>
<path path="../${src.shvm.prefix}/${build.shvm}" />
<path refid="util.classpath"/>
<path refid="asm.classpath" />
<path refid="protobuf.classpath"/>
</classpath>
</javac>
</target>
<!-- Get ASM libs from ASM class path. -->
<pathconvert pathsep=" " property="asm.libs" refid="asm.classpath">
<mapper type="flatten"/>
</pathconvert>
<!-- Get ProtoBuf Java libs from ProtoBuf class path. -->
<pathconvert pathsep=" " property="protobuf.libs" refid="protobuf.classpath">
<mapper type="flatten"/>
</pathconvert>
<target name="build" depends="compile, build-shvm-dispatch">
<jar destfile="${out.lib}/${shvm.lib}">
<manifest>
<attribute name="Class-Path" value="${asm.libs} ${protobuf.libs}"/>
<attribute name="Main-Class" value="ch.usi.dag.dislreserver.DiSLREServer"/>
<attribute name="DiSL-Version" value="${disl.version}"/>
</manifest>
<service type="javax.annotation.processing.Processor" provider="ch.usi.dag.disl.DislClassFinder"/>
<fileset dir="${build.shvm}" />
<fileset dir="../${build.util}"/>
</jar>
</target>
<target name="compile-tests" depends="compile">
<javac destdir="${build.shvm.test}" debug="true" srcdir="${src.shvm.test}" includeantruntime="false">
<classpath>
<path refid="util.classpath"/>
<path refid="asm.classpath"/>
<path refid="junit.classpath"/>
<path path="${build.shvm}"/>
</classpath>
</javac>
</target>
<target name="test" depends="compile-tests" description="Run all unit tests">
<echo>Running SHVM instrumentation library tests...</echo>
<junit haltonfailure="yes" haltonerror="yes" failureproperty="junit.failure">
<formatter type="brief" usefile="false"/>
<classpath>
<path refid="asm.classpath"/>
<path refid="junit.classpath"/>
<path path="${build.shvm.test}"/>
<path path="../${build.util}"/>
<path path="${build.shvm}"/>
</classpath>
<batchtest fork="yes">
<fileset dir="${src.shvm.test}">
<include name="**/*Test.java"/>
</fileset>
</batchtest>
</junit>
</target>
<!--
Clean the build directory
-->
<target name="clean">
<delete dir="output" />
</target>
</project>
package ch.usi.dag.dislreserver.shadow;
import ch.usi.dag.dislreserver.shadow.NetReferenceHelper;
import org.junit.Assert;
import org.junit.Test;
import org.junit.experimental.theories.Theories;
......
......@@ -12,6 +12,9 @@ import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import ch.usi.dag.dislreserver.shadow.FieldInfo;
import ch.usi.dag.dislreserver.shadow.MethodInfo;
import ch.usi.dag.dislreserver.shadow.ShadowClass;
import org.junit.Assert;
import org.junit.experimental.theories.PotentialAssignment;
import org.objectweb.asm.Type;
......@@ -155,7 +158,7 @@ abstract class ShadowClassTestBase {
private void __assertFieldArraysEqual (
final Field [] fields, final FieldInfo [] shadowFields
final Field [] fields, final FieldInfo[] shadowFields
) {
Assert.assertEquals (fields.length, shadowFields.length);
......
package ch.usi.dag.dislreserver;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.StandardSocketOptions;
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import ch.usi.dag.dislreserver.reqdispatch.RequestDispatcher;
import ch.usi.dag.dislreserver.util.Logging;
import ch.usi.dag.util.logging.Logger;
......@@ -29,6 +18,7 @@ public abstract class DiSLREServer {
//
private static final String PROP_DEBUG = "debug";
@Deprecated
private static final boolean debug = Boolean.getBoolean(PROP_DEBUG);
private static final String PROP_PORT = "dislreserver.port";
......@@ -55,7 +45,9 @@ public abstract class DiSLREServer {
__log.debug ("server started");
__serverStarted ();
run (socket);
ISHVM server = new SHVM (socket, __log, debug);
server.run ();
__log.debug ("server shutting down");
__closeSocket (socket);
......@@ -65,87 +57,7 @@ public abstract class DiSLREServer {
}
private static void run (final ServerSocketChannel socket) {
try {
final SocketChannel clientSocket = socket.accept ();
__log.debug (
"connection from %s", clientSocket.getRemoteAddress ()
);
processRequests (clientSocket.socket ());
clientSocket.close ();
} catch (final ClosedByInterruptException cbie) {
//
// The server was interrupted, we are shutting down.
//
} catch (final IOException ioe) {
//
// Communication error -- just log a message here.
//
__log.error ("error accepting a connection: %s", ioe.getMessage ());
}
}
private static void processRequests (final Socket sock) {
try {
final DataInputStream is = new DataInputStream (
new BufferedInputStream (sock.getInputStream ()));
final DataOutputStream os = new DataOutputStream (
new BufferedOutputStream (sock.getOutputStream ()));
REQUEST_LOOP: while (true) {
final byte requestNo = is.readByte ();
if (RequestDispatcher.dispatch (requestNo, is, os, debug)) {
break REQUEST_LOOP;
}
}
} catch (final Exception e) {
__logError (e);
}
}
private static void __logError (final Throwable throwable) {
if (throwable instanceof DiSLREServerException) {
__logNestedErrors (throwable);
if (__log.debugIsLoggable ()) {
__log.debug (__getFullMessage (throwable));
}
} else {
// some other exception
__log.error ("fatal error: %s", __getFullMessage (throwable));
}
}
private static void __logNestedErrors (final Throwable throwable) {
String prefix = "server error: ";
Throwable current = throwable;
do {
final String message = throwable.getMessage ();
if (message != null) {
__log.error ("%s%s", prefix, message);
}
prefix = "\t";
current = throwable.getCause ();
} while (current != null);
}
private static String __getFullMessage (final Throwable t) {
final StringWriter result = new StringWriter ();
t.printStackTrace (new PrintWriter (result));
return result.toString ();
}
//
......@@ -197,12 +109,24 @@ public abstract class DiSLREServer {
}
/**
* Returns reference to the file named by the property provided
* in parameter name.
*
* @param name Name of the property
* @return file reference or null while non-existing property
*/
private static File __getFileProperty (final String name) {
final String value = System.getProperty (name, "").trim ();
return value.isEmpty () ? null : new File (value);
}
/**
* Close the socket
*
* @param socket
*/
private static void __closeSocket (final Closeable socket) {
try {
socket.close ();
......
/**
* Logging methods extracted from DiSLREServer class
*
* Author: Vit Kabele <vit@kabele.me>
* Created on the 21/02/2019
*/
package ch.usi.dag.dislreserver;
import ch.usi.dag.util.logging.Logger;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* Logging methods extracted from DiSLREServer class
*/
abstract class Log {
private static String __getFullMessage (final Throwable t) {
final StringWriter result = new StringWriter ();
t.printStackTrace (new PrintWriter (result));
return result.toString ();
}
private static void __logNestedErrors (final Throwable throwable, final Logger __log) {
String prefix = "server error: ";
Throwable current = throwable;
do {
final String message = throwable.getMessage ();
if (message != null) {
__log.error ("%s%s", prefix, message);
}
prefix = "\t";
current = throwable.getCause ();
} while (current != null);
}
static void __logError (final Throwable throwable, final Logger __log) {
if (throwable instanceof DiSLREServerException) {
__logNestedErrors (throwable, __log);
if (__log.debugIsLoggable ()) {
__log.debug (Log.__getFullMessage (throwable));
}
} else {
// some other exception
__log.error ("fatal error: %s", Log.__getFullMessage (throwable));
}
}
}
/**
* ISHVM implementation
*
* Author: Vit Kabele <vit@kabele.me>
* Created on the 21/02/2019
*/
package ch.usi.dag.dislreserver;
import java.io.*;
import java.net.Socket;
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import ch.usi.dag.util.logging.Logger;
/**
* Implementation of ISHVM.
*
* This class should represent the one re-usable class that will represent
* i.e. one analysis session. All the needed data including reflective information
* should be available in its instance.
*/
public class SHVM implements ISHVM {
/**
* Socket for communication with client
*/
private final ServerSocketChannel __socket;
/**
* Logger instance
*/
private final Logger __log;
/**
* Debug flag
*/
@Deprecated
private final boolean __debug;
/**
* Request dispatcher
*/
private final RequestDispatcher __requestDispatcher;
/**
* Shadow VM context. It's used in the request dispatcher,
* but since the name is {@link SHVMContext} it does make
* a sense to initialize the instance here.
*/
private final SHVMContext __shvmContext;
/**
* Public constructor
*
* @param socket
* @param logger
* @param debug
*/
SHVM (
final ServerSocketChannel socket,
final Logger logger,
final boolean debug
) {
__socket = socket;
__log = logger;
__debug = debug;
__shvmContext = new SHVMContext (__log);
__requestDispatcher = new RequestDispatcher (__shvmContext);
}
@Override
public void run () {
try {
final SocketChannel clientSocket = __socket.accept ();
__log.debug (
"connection from %s", clientSocket.getRemoteAddress ()
);
processRequests (clientSocket.socket ());
clientSocket.close ();
} catch (final ClosedByInterruptException cbie) {
//
// The server was interrupted, we are shutting down.
//
} catch (final IOException ioe) {
//
// Communication error -- just log a message here.
//
__log.error ("error accepting a connection: %s", ioe.getMessage ());
}
}
private void processRequests (final Socket sock) {
try {
final DataInputStream is = new DataInputStream (
new BufferedInputStream (sock.getInputStream ()));
final DataOutputStream os = new DataOutputStream (
new BufferedOutputStream (sock.getOutputStream ()));
while (true) {
final byte requestNo = is.readByte ();
if (__requestDispatcher.dispatch (requestNo, is, os, __debug)) {
break;
}
}
} catch (final Exception e) {
Log.__logError (e, __log);
}
}
}
/**
* This file is part of disl project
* Author: Vit Kabele <vit@kabele.me>
* Created on the 22/02/2019
*/
package ch.usi.dag.dislreserver;
import ch.usi.dag.dislreserver.shadow.ShadowClassTable;
import ch.usi.dag.dislreserver.shadow.ShadowObjectTable;
import ch.usi.dag.util.logging.Logger;
/**
* This class is meant to keep all the information about
* Shadow object and classes, remote analysis methods etc.
*
* It's the main class that ties together the components
* of SHVM application.
*/
public class SHVMContext {
private final Logger __logger;
private final ShadowClassTable __shadowClassTable;
private final ShadowObjectTable __shadowObjectTable;
private final AnalysisResolver __analysisResolver;
/**
* Default constructor. Creates the instances of
* dependent classes and provide them the reference
* to itself.
*
* This can be possibly extended to use some factory
* based magic if more complicated initialization
* will be required.
*/
SHVMContext(final Logger logger) {
__shadowClassTable = new ShadowClassTable (this);
__shadowObjectTable = new ShadowObjectTable (this);
__analysisResolver = new AnalysisResolver (this);
__logger = logger;
}
/**
* Gets the {@link ShadowClassTable}
* @return An registered instance of {@link ShadowClassTable}
*/
public ShadowClassTable getShadowClassTable()
{
return __shadowClassTable;
}
/**
* Gets the {@link ShadowObjectTable}
* @return An registered instance of {@link ShadowObjectTable}
*/
public ShadowObjectTable getShadowObjectTable()
{
return __shadowObjectTable;
}
/**
* Gets the {@link AnalysisResolver}
* @return An registered instance of {@link AnalysisResolver}
*/
public AnalysisResolver getAnalysisResolver()
{
return __analysisResolver;
}
/**
* Gets the {@link Logger}
* @return An registered instance of {@link Logger}
*/
public Logger getLogger()
{
return __logger;
}
}
package ch.usi.dag.dislreserver.msg.analyze.mtdispatch;
package ch.usi.dag.dislreserver;
import java.util.Collections;
import java.util.concurrent.BlockingQueue;
......@@ -6,7 +6,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.LinkedBlockingQueue;
import ch.usi.dag.dislreserver.DiSLREServerFatalException;
/**
* Manages executors
......
package ch.usi.dag.dislreserver.msg.analyze.mtdispatch;
package ch.usi.dag.dislreserver;
import java.util.List;
import ch.usi.dag.dislreserver.DiSLREServerFatalException;
import ch.usi.dag.dislreserver.msg.analyze.AnalysisInvocation;
// Each thread has dedicated queue where new tasks are submitted.
public class AnalysisDispatcher {
......@@ -17,17 +15,19 @@ public class AnalysisDispatcher {
protected final ATEManager ateManager = new ATEManager();
protected final ObjectFreeTaskExecutor oftExec =
new ObjectFreeTaskExecutor(ateManager);
protected final ObjectFreeTaskExecutor oftExec;
public AnalysisDispatcher() {
AnalysisDispatcher(final SHVMContext shvmContext) {
super();
oftExec =
new ObjectFreeTaskExecutor(ateManager, shvmContext);
// start object free thread
oftExec.start();
}
public void addTask(long orderingID,
void addTask(long orderingID,
List<AnalysisInvocation> invocations) {
// add task to the executor
......@@ -40,7 +40,7 @@ public class AnalysisDispatcher {
}
public void objectsFreedEvent(long[] objFreeIDs) {
void objectsFreedEvent(long[] objFreeIDs) {
// create object free task
ObjectFreeTask oft = new ObjectFreeTask(objFreeIDs, globalEpoch);
......
package ch.usi.dag.dislreserver.msg.analyze.mtdispatch;
package ch.usi.dag.dislreserver;
import java.util.List;
import ch.usi.dag.dislreserver.msg.analyze.AnalysisInvocation;
import ch.usi.dag.dislreserver.AnalysisInvocation;
/**
* Holds unprocessed task data for some thread
......@@ -37,4 +37,4 @@ class AnalysisTask {
public long getEpoch() {
return epoch;
}
}
\ No newline at end of file
}
package ch.usi.dag.dislreserver.msg.analyze.mtdispatch;
package ch.usi.dag.dislreserver;
import java.util.LinkedList;
import java.util.Queue;
......
package ch.usi.dag.dislreserver.msg.analyze.mtdispatch;
import ch.usi.dag.dislreserver.DiSLREServerFatalException;
import ch.usi.dag.dislreserver.msg.analyze.AnalysisInvocation;
package ch.usi.dag.dislreserver;
/**
* Thread processing analysis tasks
......@@ -38,4 +35,4 @@ class AnalysisThread extends Thread {
}
}
}
\ No newline at end of file
}
package ch.usi.dag.dislreserver.msg.analyze.mtdispatch;
package ch.usi.dag.dislreserver;
import ch.usi.dag.dislreserver.remoteanalysis.RemoteAnalysis;
import ch.usi.dag.dislreserver.shadow.ShadowObject;
import ch.usi.dag.dislreserver.shadow.ShadowObjectTable;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import ch.usi.dag.dislreserver.DiSLREServerFatalException;
import ch.usi.dag.dislreserver.msg.analyze.AnalysisResolver;
import ch.usi.dag.dislreserver.remoteanalysis.RemoteAnalysis;
import ch.usi.dag.dislreserver.shadow.ShadowObject;
import ch.usi.dag.dislreserver.shadow.ShadowObjectTable;
/**
* The executor for {@link ObjectFreeTask} tasks.
*/
class ObjectFreeTaskExecutor extends Thread {
protected final ATEManager ateManager;
final ATEManager ateManager;
protected final BlockingQueue<ObjectFreeTask> taskQueue =
final BlockingQueue<ObjectFreeTask> taskQueue =
new LinkedBlockingQueue<ObjectFreeTask>();
public ObjectFreeTaskExecutor(ATEManager ateManager) {
/**
* Current shadow VM context.
*/
final SHVMContext __shvmContext;
/**
* Default constructor.
*
* @param ateManager
* @param shvmContext Shadow VM context.
*/
ObjectFreeTaskExecutor(
final ATEManager ateManager,
final SHVMContext shvmContext
)
{
super();
this.ateManager = ateManager;
__shvmContext = shvmContext;
}
public void addTask(ObjectFreeTask oft) {
/**
* Enqueue new task to execute.
*
* @param oft
*/
void addTask(ObjectFreeTask oft) {
taskQueue.add(oft);
}
......@@ -30,11 +55,13 @@ class ObjectFreeTaskExecutor extends Thread {
// TODO free events should be sent to analysis that sees the shadow object
final ShadowObjectTable shadowObjectTable = __shvmContext.getShadowObjectTable ();
// retrieve shadow object
ShadowObject obj = ShadowObjectTable.get(objectFreeID);
ShadowObject obj = shadowObjectTable.get(objectFreeID);
// get all analysis objects
Set<RemoteAnalysis> raSet = AnalysisResolver.getAllAnalyses();
Set<RemoteAnalysis> raSet = __shvmContext.getAnalysisResolver ().getAllAnalyses();
// invoke object free
for (RemoteAnalysis ra : raSet) {
......@@ -56,9 +83,16 @@ class ObjectFreeTaskExecutor extends Thread {
}
// release shadow object
ShadowObjectTable.freeShadowObject(obj);
shadowObjectTable.freeShadowObject(obj);
}
/**
* Thread main method.
*
* Dequeue single {@link ObjectFreeTask} wait for all the analysis executors
* to finish the closing epoch, invoke
*/
public void run() {
try {
......
package ch.usi.dag.dislreserver.msg.analyze;
package ch.usi.dag.dislreserver;
import java.io.DataInputStream;
import java.io.DataOutputStream;
......@@ -7,22 +7,34 @@ import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;
import ch.usi.dag.dislreserver.DiSLREServerException;
import ch.usi.dag.dislreserver.msg.analyze.AnalysisResolver.AnalysisMethodHolder;
import ch.usi.dag.dislreserver.msg.analyze.mtdispatch.AnalysisDispatcher;
import ch.usi.dag.dislreserver.reqdispatch.RequestHandler;
import ch.usi.dag.dislreserver.AnalysisResolver.AnalysisMethodHolder;
import ch.usi.dag.dislreserver.shadow.ShadowObject;
import ch.usi.dag.dislreserver.shadow.ShadowObjectTable;
/**
* AnalysisHandler class
*
* Takes care of handling the requests to analysis invocations.
*/
public final class AnalysisHandler implements RequestHandler {
private AnalysisDispatcher dispatcher = new AnalysisDispatcher ();
private AnalysisDispatcher dispatcher;
public AnalysisDispatcher getDispatcher() {
return dispatcher;
}
private final SHVMContext __shvmContext;
AnalysisHandler(
final SHVMContext shvmContext
) {
__shvmContext = shvmContext;
dispatcher = new AnalysisDispatcher (__shvmContext);
}
@Override
public void handle (
final DataInputStream is, final DataOutputStream os, final boolean debug
) throws DiSLREServerException {
......@@ -74,7 +86,7 @@ public final class AnalysisHandler implements RequestHandler {
// read method id from network and retrieve method
final short methodId = is.readShort ();
AnalysisMethodHolder amh = AnalysisResolver.getMethod (methodId);
AnalysisMethodHolder amh = __shvmContext.getAnalysisResolver ().getMethod (methodId);
// *** retrieve method argument values ***
......@@ -187,7 +199,7 @@ public final class AnalysisHandler implements RequestHandler {
if (ShadowObject.class.isAssignableFrom (argClass)) {
// zero tag means null
final long tag = is.readLong();
args [index] = (tag == 0) ? null : ShadowObjectTable.get (tag);
args [index] = (tag == 0) ? null : __shvmContext.getShadowObjectTable().get (tag);
return Long.SIZE / Byte.SIZE;
}
......@@ -198,14 +210,15 @@ public final class AnalysisHandler implements RequestHandler {
));
}
public void threadEnded(long threadId) {
void threadEnded(long threadId) {
dispatcher.threadEndedEvent(threadId);
}
public void objectsFreed(long[] objFreeIDs) {
void objectsFreed(long[] objFreeIDs) {
dispatcher.objectsFreedEvent(objFreeIDs);
}
@Override
public void exit() {
dispatcher.exit();
}
......
package ch.usi.dag.dislreserver.msg.analyze;
package ch.usi.dag.dislreserver;
import java.lang.reflect.Method;
......
package ch.usi.dag.dislreserver.msg.analyze;
package ch.usi.dag.dislreserver;
import ch.usi.dag.dislreserver.remoteanalysis.RemoteAnalysis;
import java.lang.reflect.Method;
import java.util.ArrayList;
......@@ -8,49 +10,85 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import ch.usi.dag.dislreserver.DiSLREServerException;
import ch.usi.dag.dislreserver.DiSLREServerFatalException;
import ch.usi.dag.dislreserver.remoteanalysis.RemoteAnalysis;
public final class AnalysisResolver {
/**
* 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 static final Map <Short, AnalysisMethodHolder>
private final Map <Short, AnalysisMethodHolder>
methodMap = new HashMap <Short, AnalysisMethodHolder> ();
private static final Map <String, RemoteAnalysis>
/**
* Cache the analysis classes
*/
private final Map <String, RemoteAnalysis>
analysisMap = new HashMap <String, RemoteAnalysis> ();
// for fast set access - contains all values from analysisMap
private static final Set <RemoteAnalysis>
/**
* for fast set access - contains all values from analysisMap
*/
private final Set <RemoteAnalysis>
analysisSet = new HashSet <RemoteAnalysis> ();
//
private final SHVMContext __shvmContext;
public static final class AnalysisMethodHolder {
/**
* Holds the instance of analysis and the analysis method.
*/
static final class AnalysisMethodHolder {
private final RemoteAnalysis analysisInstance;
private final Method analysisMethod;
public AnalysisMethodHolder(
AnalysisMethodHolder(
final RemoteAnalysis analysisInstance, final Method analysisMethod
) {
this.analysisInstance = analysisInstance;
this.analysisMethod = analysisMethod;
}
public RemoteAnalysis getAnalysisInstance() {
RemoteAnalysis getAnalysisInstance() {
return analysisInstance;
}
public Method getAnalysisMethod() {
Method getAnalysisMethod() {
return analysisMethod;
}
}
//
private static AnalysisMethodHolder resolveMethod (String methodStr
) throws DiSLREServerException {
/**
* Default constructor.
*
* @param shvmContext Current shadow VM context
*/
AnalysisResolver(final SHVMContext shvmContext)
{
__shvmContext = shvmContext;
}
/**
* Resolve the analysis method by name.
*
* The resulting instances are retreived via native reflection
* and the repeating calls are cached in analysisMap.
*
* @param methodStr Fully qualified name of the method (containing class name)