Skip to content

Commit

Permalink
Merge branch 'release/0.4.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
arminbalalaie committed Jan 18, 2019
2 parents b333e1f + ff6686c commit 3922b3a
Show file tree
Hide file tree
Showing 29 changed files with 859 additions and 465 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

<groupId>me.arminb.spidersilk</groupId>
<artifactId>spidersilk-parent</artifactId>
<version>0.3.1</version>
<version>0.4.0</version>
<packaging>pom</packaging>
<name>SpiderSilk parent POM</name>
<description>Parent POM for SpiderSilk testing library</description>
Expand Down
2 changes: 1 addition & 1 deletion sample-multithread/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<parent>
<groupId>me.arminb.spidersilk</groupId>
<artifactId>spidersilk-parent</artifactId>
<version>0.3.1</version>
<version>0.4.0</version>
</parent>

<groupId>me.arminb.spidersilk.samples</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public static void main(String[] args) {
public void start() {
new Thread(()-> fileNameUtil()).start();
new Thread(()-> helloWorld1()).start();
new Thread(()-> helloWorld2()).start();
new Thread(()-> {helloWorld2(); helloWorld2();}).start();
new Thread(()-> helloWorld3()).start();

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,17 @@
import me.arminb.spidersilk.dsl.entities.ServiceType;
import me.arminb.spidersilk.exceptions.DeploymentVerificationException;
import me.arminb.spidersilk.exceptions.RuntimeEngineException;
import me.arminb.spidersilk.execution.single_node.SingleNodeRuntimeEngine;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeoutException;

public class MultithreadTest {
public static final Logger logger = LoggerFactory.getLogger(MultithreadTest.class);

@Test
public void simpleDefinition() throws DeploymentVerificationException, RuntimeEngineException {
public void simpleDefinition() throws DeploymentVerificationException, RuntimeEngineException, TimeoutException {
Deployment deployment = new Deployment.DeploymentBuilder("sample-multithread")
// Service Definitions
.withServiceFromJvmClasspath("s1", "target/classes", "**commons-io*.jar")
Expand Down Expand Up @@ -68,17 +69,16 @@ public void simpleDefinition() throws DeploymentVerificationException, RuntimeEn
// Run Sequence Definition
.runSequence("bbe2 * e1 * ubbe2 * x1 * e2 * we1 * e3 * we2 * x2 * e4")
.sharedDirectory("/spidersilk")
.nextEventReceiptTimeout(15)
.build();

SpiderSilkRunner runner = SpiderSilkRunner.run(deployment, new SingleNodeRuntimeEngine(deployment));
SpiderSilkRunner runner = SpiderSilkRunner.run(deployment);
// Injecting network partition in a specific time in the test case
runner.runtime().waitFor("x1");
runner.runtime().waitFor("x1",10);
runner.runtime().networkPartition("n1,n2");
runner.runtime().clockDrift("n1", -1000);
runner.runtime().sendEvent("we1");
runner.runtime().clockDrift("n1", -10000);
runner.runtime().enforceOrder("we1", 10);
// Removing network partition in a specific time in the test case
runner.runtime().enforceOrder("we2", () -> runner.runtime().removeNetworkPartition());
runner.waitForRunSequenceCompletion(true);
runner.runtime().enforceOrder("we2", () -> runner.runtime().removeNetworkPartition(), 10);
runner.waitForRunSequenceCompletion(60, 20, true);
}
}
2 changes: 1 addition & 1 deletion spidersilk/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<parent>
<groupId>me.arminb.spidersilk</groupId>
<artifactId>spidersilk-parent</artifactId>
<version>0.3.1</version>
<version>0.4.0</version>
</parent>

<artifactId>spidersilk</artifactId>
Expand Down
2 changes: 2 additions & 0 deletions spidersilk/src/main/java/me/arminb/spidersilk/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ public class Constants {
public final static String DOCKER_CONTAINER_NAME_PREFIX = "spidersilk_";
public final static Integer DEFAULT_SECONDS_TO_WAIT_BEFORE_FORCED_RESTART = 5;
public final static Integer DEFAULT_SECONDS_TO_WAIT_BEFORE_FORCED_STOP = 5;
public final static String SPIDERSILK_EVENT_SERVER_IP_ADDRESS_ENV_VAR = "SPIDERSILK_EVENT_SERVER_IP_ADDRESS";
public final static String SPIDERSILK_EVENT_SERVER_PORT_NUMBER_ENV_VAR = "SPIDERSILK_EVENT_SERVER_PORT_NUMBER";
}
118 changes: 78 additions & 40 deletions spidersilk/src/main/java/me/arminb/spidersilk/SpiderSilkRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,28 @@
import me.arminb.spidersilk.execution.EventService;
import me.arminb.spidersilk.execution.RuntimeEngine;
import me.arminb.spidersilk.execution.LimitedRuntimeEngine;
import me.arminb.spidersilk.execution.NextEventReceiptTimeoutCheckerThread;
import me.arminb.spidersilk.instrumentation.InstrumentationEngine;
import me.arminb.spidersilk.instrumentation.RunSequenceInstrumentationEngine;
import me.arminb.spidersilk.verification.*;
import me.arminb.spidersilk.workspace.NodeWorkspace;
import me.arminb.spidersilk.workspace.WorkspaceManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.TimeoutException;

public class SpiderSilkRunner {
private static final Logger logger = LoggerFactory.getLogger(SpiderSilkRunner.class);
private WorkspaceManager workspaceManager;
private final Deployment deployment;
private final List<DeploymentVerifier> verifiers;
private RuntimeEngine runtimeEngine;
private InstrumentationEngine instrumentationEngine;
private List<InstrumentationEngine> instrumentationEngines;

private SpiderSilkRunner(Deployment deployment, RuntimeEngine runtimeEngine) {
public SpiderSilkRunner(Deployment deployment) {
this.deployment = deployment;
this.runtimeEngine = runtimeEngine;
this.instrumentationEngines = new ArrayList<>();
this.workspaceManager = new WorkspaceManager(deployment);

// Verifiers
Expand All @@ -61,46 +62,78 @@ private SpiderSilkRunner(Deployment deployment, RuntimeEngine runtimeEngine) {
new RunSequenceVerifier(deployment),
new SchedulingOperationVerifier(deployment)
));

// Add the default instrumentation engine
instrumentationEngines.add(new RunSequenceInstrumentationEngine());
}

public void addInstrumentationEngine(InstrumentationEngine instrumentationEngine) {
instrumentationEngines.add(instrumentationEngine);
}

public static SpiderSilkRunner run(Deployment deployment, RuntimeEngine runtimeEngine) {
public static SpiderSilkRunner run(Deployment deployment) {
logger.info("Starting SpiderSilkRunner ...");
SpiderSilkRunner spiderSilkRunner = new SpiderSilkRunner(deployment, runtimeEngine);
SpiderSilkRunner spiderSilkRunner = new SpiderSilkRunner(deployment);
spiderSilkRunner.start();
return spiderSilkRunner;
}

// Starts last event receipt timeout checker
if (deployment.getNextEventReceiptTimeout() != null && deployment.getRunSequence() != null
&& !deployment.getRunSequence().isEmpty()) {
logger.info("Starting next event receipt timeout checker thread with {} seconds timeout ..."
, deployment.getNextEventReceiptTimeout());
new NextEventReceiptTimeoutCheckerThread(spiderSilkRunner).start();
}

return spiderSilkRunner;
public void waitForRunSequenceCompletion() throws TimeoutException {
waitForRunSequenceCompletion(null,null,false);
}

public void waitForRunSequenceCompletion(boolean stopAfter) throws TimeoutException {
waitForRunSequenceCompletion(null,null, stopAfter);
}

public void waitForRunSequenceCompletion(Integer timeout) throws TimeoutException {
waitForRunSequenceCompletion(timeout,null,false);
}

public void waitForRunSequenceCompletion(Integer timeout, boolean stopAfter) throws TimeoutException {
waitForRunSequenceCompletion(timeout,null, stopAfter);
}

public void waitForRunSequenceCompletion() {
waitForRunSequenceCompletion(false);
public void waitForRunSequenceCompletion(Integer timeout, Integer nextEventReceiptTimeout) throws TimeoutException {
waitForRunSequenceCompletion(timeout,nextEventReceiptTimeout,false);
}

public void waitForRunSequenceCompletion(boolean stopAfter) {
while (!isStopped()) {
public void waitForRunSequenceCompletion(Integer timeout, Integer nextEventReceiptTimeout, boolean stopAfter)
throws TimeoutException {

Integer originalTimeout = timeout;
while (!isStopped() && (timeout == null || timeout > 0)) {
if (EventService.getInstance().isTheRunSequenceCompleted()) {
logger.info("The run sequence is completed!");
if (deployment.getSecondsToWaitForCompletion() > 0) {
logger.info("Waiting for {} seconds before stopping the runner ...",
deployment.getSecondsToWaitForCompletion());
try {
Thread.sleep(deployment.getSecondsToWaitForCompletion() * 1000);
} catch (InterruptedException e) {
logger.error("The SpiderSilkRunner wait for completion thread sleep has been interrupted!", e);
}
}

if (stopAfter && !isStopped()) {
stop();
}

return;
}

if (deployment.getRunSequence() != null && !deployment.getRunSequence().isEmpty() &&
EventService.getInstance().isLastEventReceivedTimeoutPassed(nextEventReceiptTimeout)) {
throw new TimeoutException("The timeout for receiving the next event (" + nextEventReceiptTimeout + " seconds) is passed!");
}

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO is this the best thing to do ?
logger.warn("The run sequence completion wait sleep thread is interrupted");
}

if (timeout != null) {
timeout--;
}
}

if (timeout != null && timeout <= 0) {
throw new TimeoutException("The Wait timeout for run sequence completion (" + originalTimeout + " seconds) is passed!");
}
}

public Deployment getDeployment() {
Expand All @@ -126,33 +159,30 @@ private void start() {
logger.info("Creating the nodes' workspaces ...");
Map<String, NodeWorkspace> nodeWorkspaceMap = workspaceManager.createWorkspace(deployment);

// Starting the Event Server to get the port number for instrumentation
logger.info("Starting event server ...");
runtimeEngine.startEventServer();
logger.info("Event server is started at port " + runtimeEngine.getEventServerPortNumber());

// Instrument the nodes binaries. This shouldn't change any of the application paths
logger.info("Starting the instrumentation process ...");
instrumentationEngine = new InstrumentationEngine(deployment, nodeWorkspaceMap);
instrumentationEngine.instrumentNodes(runtimeEngine.getEventServerPortNumber());
for (InstrumentationEngine instrumentationEngine: instrumentationEngines) {
logger.info("Instrumenting using {}", instrumentationEngine.getClass().getName());
instrumentationEngine.instrumentNodes(deployment, nodeWorkspaceMap);
}
logger.info("Instrumentation process is completed!");

// Starting the runtime engine
logger.info("Starting the runtime engine ...");

runtimeEngine.setNodeWorkspaceMap(nodeWorkspaceMap);
runtimeEngine = RuntimeEngine.getRuntimeEngine(deployment, nodeWorkspaceMap);
runtimeEngine.start(this);
} catch (RuntimeEngineException e) {
logger.error("An error happened while starting the runtime engine. Stopping ...", e);
if (!isStopped()) {
stop();
}
throw new RuntimeException(e);
} catch (InstrumentationException e) {
throw new RuntimeException(e);
} catch (WorkspaceException e) {
} catch (WorkspaceException | InstrumentationException e) {
logger.error("An error happened while instrumenting the nodes", e);
throw new RuntimeException(e);
} catch (Throwable e) {
logger.error("An unexpected error has happened. Stopping ...");
logger.error("An unexpected error has happened. Stopping ...", e);
if (!isStopped()) {
stop();
}
Expand All @@ -161,8 +191,16 @@ private void start() {
}

public void stop() {
stop(true, 0);
}

public void stop(boolean kill) {
stop(kill, Constants.DEFAULT_SECONDS_TO_WAIT_BEFORE_FORCED_STOP);
}

public void stop(boolean kill, Integer secondsUntilForcedStop) {
logger.info("Stopping SpiderSilkRunner ...");
runtimeEngine.stop();
runtimeEngine.stop(kill, secondsUntilForcedStop);
}

public boolean isStopped() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,11 @@ public class Deployment extends DeploymentEntity {
private final Map<String, DeploymentEntity> deploymentEntities;
private final Map<String, BlockingEvent> blockingEvents;
private final Map<String, SchedulingEvent> blockingSchedulingEvents;
private final Integer secondsToWaitForCompletion;
private final String runSequence;
private final Integer secondsUntilForcedStop;
private final Integer nextEventReceiptTimeout;

private Deployment(DeploymentBuilder builder) {
super(builder.getName());
runSequence = builder.runSequence;
secondsToWaitForCompletion = new Integer(builder.secondsToWaitForCompletion);
nodes = Collections.unmodifiableMap(builder.nodes);
services = Collections.unmodifiableMap(builder.services);
sharedDirectories = Collections.unmodifiableSet(builder.sharedDorectories);
Expand All @@ -83,8 +79,6 @@ private Deployment(DeploymentBuilder builder) {
// List of blocking type scheduling events that are present in the run sequence
blockingSchedulingEvents = Collections.unmodifiableMap(generateBlockingSchedulingEventsMap());
referableDeploymentEntities = Collections.unmodifiableMap(generateReferableEntitiesMap());
secondsUntilForcedStop = builder.secondsUntilForcedStop;
nextEventReceiptTimeout = builder.nextEventReceiptTimeout;
}

private Map<String,ReferableDeploymentEntity> generateReferableEntitiesMap() {
Expand Down Expand Up @@ -227,18 +221,6 @@ public Map<String, DeploymentEntity> getDeploymentEntities() {
return deploymentEntities;
}

public Integer getSecondsToWaitForCompletion() {
return secondsToWaitForCompletion;
}

public Integer getSecondsUntilForcedStop() {
return secondsUntilForcedStop;
}

public Integer getNextEventReceiptTimeout() {
return nextEventReceiptTimeout;
}

// TODO make this more efficient and refactor other places that uses this functionality
public Boolean isInRunSequence(String eventName) {
String[] eventNames = runSequence.split("\\W+");
Expand All @@ -257,9 +239,6 @@ public static class DeploymentBuilder extends DeploymentEntity.DeploymentBuilder
private Set<String> sharedDorectories;
private Map<String, WorkloadEvent> workloadEvents;
private Map<String, ExternalEvent> externalEvents;
private Integer secondsToWaitForCompletion;
private Integer secondsUntilForcedStop;
private Integer nextEventReceiptTimeout;

public DeploymentBuilder(String name) {
super(null, name);
Expand All @@ -269,9 +248,6 @@ public DeploymentBuilder(String name) {
externalEvents = new HashMap<>();
workloadEvents = new HashMap<>();
runSequence = "";
secondsToWaitForCompletion = 0;
secondsUntilForcedStop = Constants.DEFAULT_SECONDS_TO_WAIT_BEFORE_FORCED_STOP;
nextEventReceiptTimeout = null;
}

public DeploymentBuilder(Deployment instance) {
Expand All @@ -282,9 +258,6 @@ public DeploymentBuilder(Deployment instance) {
externalEvents = new HashMap<>(instance.externalEvents);
workloadEvents = new HashMap<>(instance.workloadEvents);
runSequence = new String(instance.runSequence);
secondsToWaitForCompletion = new Integer(instance.secondsToWaitForCompletion);
secondsUntilForcedStop = new Integer(instance.secondsUntilForcedStop);
nextEventReceiptTimeout = new Integer(instance.nextEventReceiptTimeout);
}

public DeploymentBuilder node(Node node) {
Expand Down Expand Up @@ -340,8 +313,7 @@ public Service.ServiceBuilder withServiceFromJvmClasspath(String name, String...
instrumentablePathSet.add(Paths.get(instrumentablePath).toAbsolutePath().normalize().toString());
}
} catch (IOException e) {
logger.error("Error while trying to expand instrumentable path {}", instrumentablePathPattern, e);
throw new RuntimeException("Error while trying to expand instrumentable path " + instrumentablePathPattern);
throw new RuntimeException("Error while trying to expand instrumentable path " + instrumentablePathPattern, e);
}
}
}
Expand Down Expand Up @@ -502,21 +474,6 @@ public DeploymentBuilder runSequence(String sequence) {
return this;
}

public DeploymentBuilder secondsToWaitForCompletion(Integer secondsToWaitForCompletion) {
this.secondsToWaitForCompletion = secondsToWaitForCompletion;
return this;
}

public DeploymentBuilder secondsUntilForcedStop(Integer secondsUntilForcedStop) {
this.secondsUntilForcedStop = secondsUntilForcedStop;
return this;
}

public DeploymentBuilder nextEventReceiptTimeout(Integer nextEventReceiptTimeout) {
this.nextEventReceiptTimeout = nextEventReceiptTimeout;
return this;
}

public Deployment build() {
return new Deployment(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
package me.arminb.spidersilk.exceptions;

public class InstrumentationException extends Exception {
public InstrumentationException(String msg, Throwable cause) {
super(msg, cause);
}

public InstrumentationException(String msg) {
super(msg);
}
Expand Down

0 comments on commit 3922b3a

Please sign in to comment.