diff --git a/dev/cosbench-config/bin/com/intel/cosbench/config/castor/stage-mapping.xml b/dev/cosbench-config/bin/com/intel/cosbench/config/castor/stage-mapping.xml
index 12024363..805df753 100644
--- a/dev/cosbench-config/bin/com/intel/cosbench/config/castor/stage-mapping.xml
+++ b/dev/cosbench-config/bin/com/intel/cosbench/config/castor/stage-mapping.xml
@@ -13,6 +13,10 @@
+
+
+
+
diff --git a/dev/cosbench-config/bin/com/intel/cosbench/config/castor/workload-mapping.xml b/dev/cosbench-config/bin/com/intel/cosbench/config/castor/workload-mapping.xml
index 0c1c84a4..78873a42 100644
--- a/dev/cosbench-config/bin/com/intel/cosbench/config/castor/workload-mapping.xml
+++ b/dev/cosbench-config/bin/com/intel/cosbench/config/castor/workload-mapping.xml
@@ -12,6 +12,10 @@
+
+
+
+
diff --git a/dev/cosbench-config/src/com/intel/cosbench/config/Stage.java b/dev/cosbench-config/src/com/intel/cosbench/config/Stage.java
index c6ab71ec..18ddcab1 100644
--- a/dev/cosbench-config/src/com/intel/cosbench/config/Stage.java
+++ b/dev/cosbench-config/src/com/intel/cosbench/config/Stage.java
@@ -32,7 +32,8 @@ public class Stage implements Iterable {
private String name;
private int closuredelay;
- private Auth auth;
+ private String trigger=null;
+ private Auth auth;
private Storage storage;
private List works;
@@ -59,6 +60,14 @@ public void setName(String name) {
public int getClosuredelay() {
return closuredelay;
}
+
+ public String getTrigger() {
+ return trigger;
+ }
+
+ public void setTrigger(String trigger) {
+ this.trigger = trigger;
+ }
public void setClosuredelay(int closuredelay) {
if (closuredelay < 0)
diff --git a/dev/cosbench-config/src/com/intel/cosbench/config/Work.java b/dev/cosbench-config/src/com/intel/cosbench/config/Work.java
index 5b254abf..919e2448 100644
--- a/dev/cosbench-config/src/com/intel/cosbench/config/Work.java
+++ b/dev/cosbench-config/src/com/intel/cosbench/config/Work.java
@@ -39,7 +39,7 @@ public class Work implements Iterable {
private int runtime = 0;
private int rampup = 0;
private int rampdown = 0;
- private int afr = 200000; /* acceptable failure ratio, the unit is samples per one million,
+ private int afr = -1; /* acceptable failure ratio, the unit is samples per one million,
* default is 200000 for normal work, and 0 for init/prepare/cleanup/dispose/delay work */
private int totalOps = 0;
private long totalBytes = 0;
@@ -254,7 +254,7 @@ private void toPrepareWork() {
name = "prepare";
setDivision("object");
setRuntime(0);
- setAfr(0);
+ setDefaultAfr(0);
setTotalBytes(0);
setTotalOps(getWorkers());
Operation op = new Operation();
@@ -274,7 +274,7 @@ private void toCleanupWork() {
name = "cleanup";
setDivision("object");
setRuntime(0);
- setAfr(0);
+ setDefaultAfr(0);
setTotalBytes(0);
setTotalOps(getWorkers());
Operation op = new Operation();
@@ -294,7 +294,7 @@ private void toInitWork() {
name = "init";
setDivision("container");
setRuntime(0);
- setAfr(0);
+ setDefaultAfr(0);
setTotalBytes(0);
setTotalOps(getWorkers());
Operation op = new Operation();
@@ -310,7 +310,7 @@ private void toDisposeWork() {
name = "dispose";
setDivision("container");
setRuntime(0);
- setAfr(0);
+ setDefaultAfr(0);
setTotalBytes(0);
setTotalOps(getWorkers());
Operation op = new Operation();
@@ -326,7 +326,7 @@ public void toDelayWork() {
name = "delay";
setDivision("none");
setRuntime(0);
- setAfr(0);
+ setDefaultAfr(0);
setTotalBytes(0);
setWorkers(1);
setTotalOps(getWorkers());
@@ -336,6 +336,11 @@ public void toDelayWork() {
op.setConfig("");
setOperations(Collections.singletonList(op));
}
+
+ private void setDefaultAfr(int def) {
+ if (afr < 0)
+ setAfr(def);
+ }
public void validate() {
if (type.equals("prepare"))
@@ -348,6 +353,8 @@ else if (type.equals("dispose"))
toDisposeWork();
else if (type.equals("delay"))
toDelayWork();
+ else
+ setDefaultAfr(200000);
setName(getName());
setWorkers(getWorkers());
if (runtime == 0 && totalOps == 0 && totalBytes == 0)
diff --git a/dev/cosbench-config/src/com/intel/cosbench/config/Workload.java b/dev/cosbench-config/src/com/intel/cosbench/config/Workload.java
index 3b387440..1872e2f6 100644
--- a/dev/cosbench-config/src/com/intel/cosbench/config/Workload.java
+++ b/dev/cosbench-config/src/com/intel/cosbench/config/Workload.java
@@ -33,6 +33,7 @@ public class Workload {
private String name;
private String description;
+ private String trigger=null;
private Auth auth = DEFAULT_AUTH;
private Storage storage = DEFAULT_STORAGE;
private Workflow workflow;
@@ -59,6 +60,14 @@ public void setDescription(String description) {
/* description might be empty */
this.description = description;
}
+
+ public String getTrigger() {
+ return trigger;
+ }
+
+ public void setTrigger(String trigger) {
+ this.trigger = trigger;
+ }
public Auth getAuth() {
return auth;
diff --git a/dev/cosbench-config/src/com/intel/cosbench/config/castor/stage-mapping.xml b/dev/cosbench-config/src/com/intel/cosbench/config/castor/stage-mapping.xml
index 12024363..805df753 100644
--- a/dev/cosbench-config/src/com/intel/cosbench/config/castor/stage-mapping.xml
+++ b/dev/cosbench-config/src/com/intel/cosbench/config/castor/stage-mapping.xml
@@ -13,6 +13,10 @@
+
+
+
+
diff --git a/dev/cosbench-config/src/com/intel/cosbench/config/castor/workload-mapping.xml b/dev/cosbench-config/src/com/intel/cosbench/config/castor/workload-mapping.xml
index 0c1c84a4..78873a42 100644
--- a/dev/cosbench-config/src/com/intel/cosbench/config/castor/workload-mapping.xml
+++ b/dev/cosbench-config/src/com/intel/cosbench/config/castor/workload-mapping.xml
@@ -12,6 +12,10 @@
+
+
+
+
diff --git a/dev/cosbench-controller/src/com/intel/cosbench/controller/model/DriverContext.java b/dev/cosbench-controller/src/com/intel/cosbench/controller/model/DriverContext.java
index e518a325..381f6921 100644
--- a/dev/cosbench-controller/src/com/intel/cosbench/controller/model/DriverContext.java
+++ b/dev/cosbench-controller/src/com/intel/cosbench/controller/model/DriverContext.java
@@ -17,6 +17,9 @@
package com.intel.cosbench.controller.model;
+import java.util.HashMap;
+import java.util.Map;
+
import com.intel.cosbench.model.DriverInfo;
import com.intel.cosbench.utils.MapRegistry;
@@ -31,8 +34,9 @@ public class DriverContext implements DriverInfo, MapRegistry.Item {
private String name;
private String url;
private boolean aliveState;
+ private Map pIDMap = new HashMap();
- public DriverContext() {
+ public DriverContext() {
/* empty */
}
@@ -64,4 +68,16 @@ public boolean getAliveState(){
return aliveState;
}
+
+ public String getPIDMap(String scriptName) {
+ String pid = pIDMap.remove(scriptName);
+ return (pid == null) ? "0" : pid;
+ }
+
+ public void putPIDMap(String scriptName, String pid) {
+ if (pid == null)
+ pIDMap.put(scriptName, "0");
+ pIDMap.put(scriptName, pid);
+ }
+
}
diff --git a/dev/cosbench-controller/src/com/intel/cosbench/controller/service/TriggerRunner.java b/dev/cosbench-controller/src/com/intel/cosbench/controller/service/TriggerRunner.java
new file mode 100644
index 00000000..95bbaa8b
--- /dev/null
+++ b/dev/cosbench-controller/src/com/intel/cosbench/controller/service/TriggerRunner.java
@@ -0,0 +1,53 @@
+package com.intel.cosbench.controller.service;
+
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import com.intel.cosbench.controller.model.DriverRegistry;
+import com.intel.cosbench.controller.tasklet.Tasklet;
+import com.intel.cosbench.controller.tasklet.Tasklets;
+import com.intel.cosbench.log.LogFactory;
+import com.intel.cosbench.log.Logger;
+
+public class TriggerRunner {
+ DriverRegistry registry;
+ private ExecutorService executor;
+ private static final Logger LOGGER = LogFactory.getSystemLogger();
+
+ public TriggerRunner(DriverRegistry registry) {
+ this.registry = registry;
+ createExecutor();
+ }
+
+ public void runTrigger(boolean option, String trigger, String wid) {
+ List tasklets = Tasklets.newTriggers(trigger, registry, option, wid);
+ executeTasklets(tasklets, option);
+ dispose();//shutdown too quick?
+ }
+
+ private void createExecutor() {
+ int taskCount = registry.getSize();
+ executor = Executors.newFixedThreadPool(taskCount);
+ }
+
+ public void dispose() {
+ if (executor != null)
+ executor.shutdown();
+ executor = null;
+ }
+
+ private void executeTasklets(List tasklets, boolean option) {
+ int num = tasklets.size();
+ LOGGER.debug("begin to execute {}-trigger tasklets, {} in total",
+ option ? "enable" : "kill", num);
+ try {
+ executor.invokeAll(tasklets);
+ } catch (InterruptedException e) {
+ LOGGER.debug("{}-trigger tasklets have interrupted",
+ option ? "enable" : "kill", num);
+ return; //no return is ok?
+ }
+ LOGGER.debug("all {} trigger tasklets have finished execution", num);
+ }
+}
diff --git a/dev/cosbench-controller/src/com/intel/cosbench/controller/service/WorkloadProcessor.java b/dev/cosbench-controller/src/com/intel/cosbench/controller/service/WorkloadProcessor.java
index fbf70c51..26f54538 100644
--- a/dev/cosbench-controller/src/com/intel/cosbench/controller/service/WorkloadProcessor.java
+++ b/dev/cosbench-controller/src/com/intel/cosbench/controller/service/WorkloadProcessor.java
@@ -149,11 +149,14 @@ private void processWorkload() throws InterruptedException {
workloadContext.setState(PROCESSING);
workloadContext.setStartDate(new Date());
Iterator iter = queue.iterator();
+ String trigger = workloadContext.getWorkload().getTrigger();
+ executeTrigger(trigger, true);
while (iter.hasNext()) {
StageContext stageContext = iter.next();
iter.remove();
runStage(stageContext);
}
+ executeTrigger(trigger, false);
workloadContext.setStopDate(new Date());
workloadContext.setCurrentStage(null);
for (StageContext stageContext : workloadContext.getStageRegistry()
@@ -204,7 +207,6 @@ private void runStage(StageContext stageContext) throws InterruptedException {
if(closuredelay > 0)
executeDelay(stageContext, closuredelay);
}
-
LOGGER.info("successfully ran stage {}", id);
}
@@ -222,12 +224,16 @@ private void executeStage(StageContext stageContext) {
StageRunner runner = createStageRunner(stageContext);
StageChecker checker = createStageChecker(stageContext);
StageCallable[] callables = new StageCallable[] { runner, checker };
+ String trigger = stageContext.getStage().getTrigger();
+ executeTrigger(trigger, true);
try {
executor.invokeAll(Arrays.asList(callables));
} catch (InterruptedException ie) {
+ executeTrigger(trigger, false);
throw new CancelledException(); // workload cancelled
}
runner.dispose(); // early dispose runner
+ executeTrigger(trigger, false);
if (!stageContext.getState().equals(StageState.TERMINATED))
return;
String id = stageContext.getId();
@@ -254,10 +260,18 @@ private void terminateWorkload() {
LOGGER.info("begin to terminate workload {}", id);
for (StageContext stageContext : queue)
stageContext.setState(StageState.ABORTED);
+ executeTrigger(workloadContext.getWorkload().getTrigger(), false);
workloadContext.setStopDate(new Date());
workloadContext.setState(TERMINATED);
LOGGER.info("successfully terminated workload {}", id);
}
+
+ private void executeTrigger(String trigger, boolean isEnable) {
+ if (trigger == null || trigger.isEmpty())
+ return;
+ TriggerRunner runner = new TriggerRunner(controllerContext.getDriverRegistry());
+ runner.runTrigger(isEnable, trigger, workloadContext.getId());
+ }
public void cancel() {
String id = workloadContext.getId();
@@ -310,6 +324,7 @@ private void cancelWorkload() {
*/
for (StageContext stageContext : queue)
stageContext.setState(StageState.CANCELLED);
+ executeTrigger(workloadContext.getWorkload().getTrigger(), false);
workloadContext.setStopDate(new Date());
workloadContext.setState(CANCELLED);
LOGGER.info("successfully cancelled workload {}", id);
diff --git a/dev/cosbench-controller/src/com/intel/cosbench/controller/tasklet/Tasklets.java b/dev/cosbench-controller/src/com/intel/cosbench/controller/tasklet/Tasklets.java
index 97215780..6de0e18f 100644
--- a/dev/cosbench-controller/src/com/intel/cosbench/controller/tasklet/Tasklets.java
+++ b/dev/cosbench-controller/src/com/intel/cosbench/controller/tasklet/Tasklets.java
@@ -78,5 +78,13 @@ public static List newAborters(TaskRegistry tasks) {
}
return result;
}
+
+ public static List newTriggers(String trigger, DriverRegistry registry, boolean option, String wid) {
+ List result = new ArrayList();
+ for (DriverContext driver : registry) {
+ result.add(new Trigger(driver, trigger, option, wid));
+ }
+ return result;
+ }
}
diff --git a/dev/cosbench-controller/src/com/intel/cosbench/controller/tasklet/Trigger.java b/dev/cosbench-controller/src/com/intel/cosbench/controller/tasklet/Trigger.java
new file mode 100644
index 00000000..b24a50c8
--- /dev/null
+++ b/dev/cosbench-controller/src/com/intel/cosbench/controller/tasklet/Trigger.java
@@ -0,0 +1,52 @@
+package com.intel.cosbench.controller.tasklet;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.intel.cosbench.controller.model.DriverContext;
+import com.intel.cosbench.protocol.TriggerResponse;
+
+
+public class Trigger extends TriggerHttpTasklet {
+ public Trigger(DriverContext driver, String trigger, boolean option, String wid) {
+ super(driver, trigger, option, wid);
+ }
+
+ @Override
+ public void execute() {
+ initHttpClient();
+ initObjectMapper();
+ String content = getCmdLine();
+ if (content == null || content.isEmpty())
+ return;
+ issueCommand("trigger", content);
+ try {
+ closeHttpClient();
+ } catch (Exception e) {
+ LOGGER.error("unexpected exception", e);
+ }
+ }
+
+ private String getCmdLine() {
+ trigger.replace(" ", "");
+ int idxLeft = StringUtils.indexOf(trigger, '(');
+ int idxRight = StringUtils.indexOf(trigger, ')');
+ if (idxLeft < 3 || ( idxRight != trigger.length()-1)){
+ LOGGER.error("can't enable trigger, the format is illegal!");
+ return null;
+ }
+ scriptName = StringUtils.left(trigger, idxLeft);
+ String argStr = StringUtils.substring(trigger, idxLeft+1, idxRight);
+ return isEnable ? ("enableTrigger," + scriptName + "," + argStr + "," + wID)
+ : ("killTrigger," + driver.getPIDMap(scriptName) + "," + scriptName + "," + wID);
+ }
+
+ @Override
+ protected void handleResponse(TriggerResponse response) {
+ if (!isEnable) {
+ driver.putPIDMap(scriptName, "0");
+ return;
+ }
+ driver.putPIDMap(scriptName, response.getPID());
+ }
+
+}
diff --git a/dev/cosbench-controller/src/com/intel/cosbench/controller/tasklet/TriggerHttpTasklet.java b/dev/cosbench-controller/src/com/intel/cosbench/controller/tasklet/TriggerHttpTasklet.java
new file mode 100644
index 00000000..1a7480cb
--- /dev/null
+++ b/dev/cosbench-controller/src/com/intel/cosbench/controller/tasklet/TriggerHttpTasklet.java
@@ -0,0 +1,150 @@
+package com.intel.cosbench.controller.tasklet;
+
+import java.io.IOException;
+import java.net.SocketTimeoutException;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.StatusLine;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.conn.ConnectTimeoutException;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.util.EntityUtils;
+import org.codehaus.jackson.map.DeserializationConfig;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.DeserializationConfig.Feature;
+
+import com.intel.cosbench.client.http.HttpClientUtil;
+import com.intel.cosbench.controller.model.DriverContext;
+import com.intel.cosbench.log.LogFactory;
+import com.intel.cosbench.log.Logger;
+import com.intel.cosbench.protocol.TriggerResponse;
+import com.intel.cosbench.service.UnexpectedException;
+
+abstract class TriggerHttpTasklet implements Tasklet{
+ private transient HttpClient httpClient;
+ private transient ObjectMapper mapper;
+ protected DriverContext driver;
+ protected String trigger = null;
+ protected boolean isEnable; //true=enableTrigger; false=killTrigger
+ protected String wID = null;
+ protected String scriptName = null;
+
+ Class clazz = TriggerResponse.class;
+
+ private static final int TIMEOUT = 300 * 1000;
+ protected static final Logger LOGGER = LogFactory.getSystemLogger();
+
+ protected abstract void execute();
+ protected abstract void handleResponse(TriggerResponse response);
+
+ public TriggerHttpTasklet(DriverContext driver, String trigger, boolean option, String wid) {
+ this.driver = driver;
+ this.trigger = trigger;
+ this.isEnable = option;
+ this.wID = wid;
+ }
+
+ protected void initObjectMapper() {
+ ObjectMapper mapper = new ObjectMapper();
+ DeserializationConfig config = mapper.copyDeserializationConfig();
+ config.disable(Feature.FAIL_ON_UNKNOWN_PROPERTIES);
+ mapper.setDeserializationConfig(config);
+ this.mapper = mapper;
+ }
+
+ protected void initHttpClient() {
+ HttpClient client = HttpClientUtil.createHttpClient(TIMEOUT);
+ this.httpClient = client;
+ }
+
+ protected synchronized void closeHttpClient() {
+ HttpClient client = this.httpClient;
+ HttpClientUtil.disposeHttpClient(client);
+ }
+
+ private String issueHttpRequest(String command, String content) {
+ String url = driver.getUrl() + "/i/" + command + ".command";
+ HttpClient client = this.httpClient;
+ HttpPost request = prepareRequest(content, url);
+ String body = null;
+ try {
+ HttpResponse response = client.execute(request);
+ body = fetchResponseBody(response);
+ } catch (SocketTimeoutException ste) {
+ LOGGER.error("fail to POST driver while execute trigger", ste);
+ } catch (ConnectTimeoutException cte) {
+ LOGGER.error("fail to POST driver while execute trigger", cte);
+ } catch (Exception e) {
+ LOGGER.error("fail to POST driver while execute trigger", e);
+ }
+ return body; // HTTP response body retrieved
+ }
+
+ private static HttpPost prepareRequest(String content, String url) {
+ HttpPost POST = new HttpPost(url);
+ try {
+ if (StringUtils.isNotEmpty(content))
+ POST.setEntity(new StringEntity(content));
+ } catch (Exception e) {
+ throw new UnexpectedException(e); // will not happen
+ }
+ if (content != null && content.length() > 0)
+ if (!content.startsWith("> ] - {} -> {}", content, url);
+ else
+ LOGGER.debug("[ >> ] - [xml-content] -> {}", url);
+ else
+ LOGGER.debug("[ >> ] - [empty-body] -> {}", url);
+ return POST; // HTTP request prepared
+ }
+
+ private static String fetchResponseBody(HttpResponse response)
+ throws IOException {
+ String body = null;
+ HttpEntity entity = response.getEntity();
+ StatusLine status = response.getStatusLine();
+ try {
+ body = EntityUtils.toString(entity);
+ } finally {
+ EntityUtils.consume(entity);
+ }
+ if (body.length() < 2048)
+ LOGGER.debug("[ << ] - {} {}", status, body);
+ else
+ LOGGER.debug("[ << ] - {} [body-omitted]", status);
+ return body; // the response body
+ }
+
+ protected void issueCommand(String command, String content) {
+ TriggerResponse response = null;
+ String body = issueHttpRequest(command, content);
+ try {
+ response = this.mapper.readValue(body, clazz);
+ } catch (Exception e) {
+ LOGGER.error("cannot parse TriggerResponse body", e);
+ return;
+ }
+ if (!response.isSucc()) {
+ String msg = "driver report error: HTTP {} - {}";
+ LOGGER.error(msg, response.getCode(), response.getError());
+ return;
+ }
+ handleResponse(response);
+ }
+
+ @Override
+ public Tasklet call() {
+ try {
+ execute();
+ LOGGER.debug("{}-trigger executes normally", isEnable ? "enable" : "kill");
+ } catch (Exception e) {
+ LOGGER.error("unexpected exception of trigger", e);
+ }
+ return this; /* okay -- done */
+ }
+
+}
+
diff --git a/dev/cosbench-core/src/com/intel/cosbench/protocol/TriggerResponse.java b/dev/cosbench-core/src/com/intel/cosbench/protocol/TriggerResponse.java
new file mode 100644
index 00000000..729f3ced
--- /dev/null
+++ b/dev/cosbench-core/src/com/intel/cosbench/protocol/TriggerResponse.java
@@ -0,0 +1,37 @@
+/**
+
+Copyright 2013 Intel Corporation, All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+
+package com.intel.cosbench.protocol;
+
+public class TriggerResponse extends Response{
+ private String PID;//int(check)/string default
+
+ public TriggerResponse() {
+ /*empty*/
+ }
+
+ public String getPID() {
+ return PID;
+ }
+
+ public void setPID(String pID) {
+ //check
+ PID = pID;
+ }
+
+}
diff --git a/dev/cosbench-driver-web/WEB-INF/spring/driver-handler-context.xml b/dev/cosbench-driver-web/WEB-INF/spring/driver-handler-context.xml
index 1ffc0a09..0dbd05eb 100644
--- a/dev/cosbench-driver-web/WEB-INF/spring/driver-handler-context.xml
+++ b/dev/cosbench-driver-web/WEB-INF/spring/driver-handler-context.xml
@@ -40,6 +40,11 @@
class="com.intel.cosbench.driver.handler.AbortHandler">
+
+
+
+
diff --git a/dev/cosbench-driver-web/WEB-INF/spring/driver-web-context.xml b/dev/cosbench-driver-web/WEB-INF/spring/driver-web-context.xml
index eaf081f5..77f1b1ac 100644
--- a/dev/cosbench-driver-web/WEB-INF/spring/driver-web-context.xml
+++ b/dev/cosbench-driver-web/WEB-INF/spring/driver-web-context.xml
@@ -50,6 +50,11 @@
class="com.intel.cosbench.driver.web.AbortMissionController">
+
+
+
+
diff --git a/dev/cosbench-driver-web/src/com/intel/cosbench/driver/handler/MissionHandler.java b/dev/cosbench-driver-web/src/com/intel/cosbench/driver/handler/MissionHandler.java
index 9f7bc69d..28295754 100644
--- a/dev/cosbench-driver-web/src/com/intel/cosbench/driver/handler/MissionHandler.java
+++ b/dev/cosbench-driver-web/src/com/intel/cosbench/driver/handler/MissionHandler.java
@@ -21,6 +21,8 @@
import javax.servlet.http.*;
+import com.intel.cosbench.log.LogFactory;
+import com.intel.cosbench.log.Logger;
import com.intel.cosbench.model.MissionInfo;
import com.intel.cosbench.protocol.Response;
import com.intel.cosbench.service.DriverService;
@@ -29,6 +31,7 @@
abstract class MissionHandler extends AbstractCommandHandler {
protected DriverService driver;
+ protected static final Logger LOGGER = LogFactory.getSystemLogger();
public void setDriver(DriverService driver) {
this.driver = driver;
diff --git a/dev/cosbench-driver-web/src/com/intel/cosbench/driver/handler/PingHandler.java b/dev/cosbench-driver-web/src/com/intel/cosbench/driver/handler/PingHandler.java
index 306c7a37..db9680f3 100644
--- a/dev/cosbench-driver-web/src/com/intel/cosbench/driver/handler/PingHandler.java
+++ b/dev/cosbench-driver-web/src/com/intel/cosbench/driver/handler/PingHandler.java
@@ -63,9 +63,11 @@ private void setSysTime(long ctrTime) throws IOException {
String[] cmd = {"date", "-s", dateTime.format(new Date(ctrTime))};
String osType = System.getProperty("os.name").toLowerCase();
if (osType.contains("linux")) {
+ LOGGER.debug("setting system time {} on driver {}", ctrTime, driver.getDriverInfo().getName());
Runtime.getRuntime().exec(cmd);
} else {
- /* skip for non linux system */
+ LOGGER.warn("os type on driver {} is {}!",
+ driver.getDriverInfo().getName(), osType);
}
}
diff --git a/dev/cosbench-driver-web/src/com/intel/cosbench/driver/handler/TriggerHandler.java b/dev/cosbench-driver-web/src/com/intel/cosbench/driver/handler/TriggerHandler.java
new file mode 100644
index 00000000..38f05576
--- /dev/null
+++ b/dev/cosbench-driver-web/src/com/intel/cosbench/driver/handler/TriggerHandler.java
@@ -0,0 +1,244 @@
+/**
+
+Copyright 2013 Intel Corporation, All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.intel.cosbench.driver.handler;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang.StringUtils;
+import com.intel.cosbench.protocol.Response;
+import com.intel.cosbench.protocol.TriggerResponse;
+import com.intel.cosbench.service.DriverService;
+
+public class TriggerHandler extends AbstractCommandHandler {
+
+ private int currPID = 0;
+ private int xferPID = 0;
+ private boolean isEnable = false;
+ protected static String scriptsDir = "scripts/";
+ protected DriverService driver;
+ private String wID = null;
+
+ public void setDriver(DriverService driver) {
+ this.driver = driver;
+ }
+
+ @Override
+ protected Response process(HttpServletRequest req, HttpServletResponse res)
+ throws Exception {
+ Scanner scanner = new Scanner(req.getInputStream());
+ String trigger = getTrigger(scanner);
+ runTrigger(trigger);
+
+ return createResponse();
+ }
+
+ private String getTrigger(Scanner scanner) {
+ if (!scanner.hasNext())
+ LOGGER.error("bad request exception");
+ String trigger = scanner.next();
+ if (trigger == null)
+ LOGGER.error("no found exception");
+ return trigger;
+ }
+
+ private void runTrigger(String trigger) {
+ String cmdLine = getCmdLine(trigger);
+ if (cmdLine == null || cmdLine.isEmpty()) {
+ LOGGER.error("trigger command line is empty!");
+ return;
+ }
+ LOGGER.debug("executing trigger command line : {}", cmdLine);
+ String osType = System.getProperty("os.name").toLowerCase();
+ if (osType.contains("linux")) {
+ try {
+ Process process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", cmdLine});
+ getPID(process);
+ } catch (Exception e) {
+ LOGGER.error("execute trigger command failed!");
+ return;
+ }
+ } else {
+ LOGGER.warn("can not execute trigger, the OS type({}) isn't linux!", osType);
+ return;
+ }
+ if (!isEnable) {
+ if (!isTriggerKilled(currPID)) {
+ killByPID(currPID);
+ }
+ if (!isTriggerKilled(xferPID))
+ killByPID(xferPID);
+ }
+ }
+
+ private String getCmdLine(String trigger) {
+ String cmdLine = null;
+ String fileName = null;
+
+ trigger.replace(" ", "");
+ String[] triggerArr = StringUtils.split(trigger, ',');
+ if (triggerArr == null) {
+ LOGGER.warn("trigger command array is empty!");
+ return null;
+ }
+ if (triggerArr[0].equals("killTrigger")) {
+ this.isEnable = false;
+ if (triggerArr.length != 4) {
+ LOGGER.error("kill-trigger command line is illegal!");
+ return null;
+ }
+ xferPID = parsePID(triggerArr[1]);
+ fileName = triggerArr[2];
+ this.wID = triggerArr[3];
+ cmdLine = "/bin/sh " + scriptsDir + fileName + " -k";
+ } else if (triggerArr[0].equals("enableTrigger")) {
+ this.isEnable = true;
+ fileName = triggerArr[1];
+ cmdLine = "/bin/sh " + scriptsDir + fileName;
+ for (int i = 2; i < triggerArr.length - 1; i++)
+ cmdLine += " " + triggerArr[i];
+ this.wID = triggerArr[triggerArr.length-1];
+ } else {
+ LOGGER.error("trigger command line is illegal!");
+ return null;
+ }
+ String filePath = scriptsDir + fileName;
+ File tempPath = new File(filePath);
+ if (!tempPath.exists() || !tempPath.isFile()) {
+ LOGGER.error("trigger file {} dosen't exist in {}!", filePath);
+ return null;
+ }
+ cmdLine += " >> " + scriptsDir + "log/" + wID + "_" + fileName + ".log";
+ return cmdLine;
+ }
+
+ private int parsePID(String str) {
+ int num = 0;
+ try {
+ num = Integer.parseInt(str);
+ } catch (NumberFormatException e) {
+ LOGGER.error("can not parse PID from String to Int {}!", str);
+ }
+ return num;
+ }
+
+ private void getPID(Process process) {
+ Field field = null;
+ if (!process.getClass().getName().equals("java.lang.UNIXProcess")) {
+ LOGGER.error("failed to get PID by {}", process.getClass().getName());
+ return;
+ }
+ try {
+ field = process.getClass().getDeclaredField("pid");
+ field.setAccessible(true);
+ currPID = (Integer) field.get(process);
+ } catch (Exception e) {
+ LOGGER.error("get PID failed!");
+ }
+ if (isEnable)
+ xferPID = currPID;
+ LOGGER.debug("current PID is: {}", currPID);
+ }
+
+ private boolean isTriggerKilled(int pid) {
+ List pids = getAllPID(pid);
+ if (pids != null && pids.size() >= 1)
+ return false;
+ return true;
+ }
+
+ private void killByPID(int pid) {
+ List pidList = getAllPID(pid);
+ if (pidList == null || pidList.isEmpty()) {
+ //LOGGER.debug("pid {} have been killed", pid);
+ return;
+ }
+ if (pidList.size() == 1) {
+ //LOGGER.debug("pid {} have no child process", pid);
+ } else {
+ //LOGGER.debug("pid {} have child process {}", pid, pidList);
+ for (int i = 1; i < pidList.size(); i++) {
+ killByPID(pidList.get(i));
+ }
+ }
+ runKill9(pid);
+ }
+
+ private List getAllPID(int pid) {
+ if (pid <= 0) {
+ LOGGER.warn("pid is illegal: {}", pid);
+ return null;
+ }
+ List pidList = new ArrayList();
+ String cmdLine = "ps -ef | grep " + pid + " | awk '{print $2}'";
+ try {
+ Process process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", cmdLine});
+ InputStream is = process.getInputStream();
+ BufferedReader buff = new BufferedReader(new InputStreamReader(is));
+
+ String line = null;
+ while ((line = buff.readLine()) != null) {
+ int tmp = 0;
+ if ((tmp = parsePID(line.trim())) <= 0){
+ LOGGER.error("buffer line is illegal: {}", line);
+ continue;
+ }
+ //LOGGER.debug("child pid of {} : {}", pid, tmp);
+ pidList.add(new Integer(tmp));
+ }
+ process.waitFor();
+ } catch (Exception e) {
+ LOGGER.error("get all PID failed!");
+ return null;
+ }
+ if (pidList == null || pidList.isEmpty())
+ return null;
+ pidList.remove(pidList.size()-1);
+ pidList.remove(pidList.size()-1);
+ return pidList;
+ }
+
+ private void runKill9(int pid) {
+ String osType = System.getProperty("os.name").toLowerCase();
+ if (osType.contains("linux")) {
+ try {
+ Runtime.getRuntime().exec(new String[]{"kill","-9",Integer.toString(pid)});
+ LOGGER.debug("pid {} have been killed directly", pid);
+ } catch (Exception e) {
+ LOGGER.error("run failed!", pid);
+ }
+ } else {
+ LOGGER.warn("can not run kill command, the OS type({}) isn't linux!", osType);
+ }
+ }
+
+ private Response createResponse() {
+ TriggerResponse response = new TriggerResponse();
+ response.setPID(isEnable ? Integer.toString(xferPID) : "0");
+ return response;
+ }
+
+}
diff --git a/dev/cosbench-driver-web/src/com/intel/cosbench/driver/web/TriggerController.java b/dev/cosbench-driver-web/src/com/intel/cosbench/driver/web/TriggerController.java
new file mode 100644
index 00000000..23db135c
--- /dev/null
+++ b/dev/cosbench-driver-web/src/com/intel/cosbench/driver/web/TriggerController.java
@@ -0,0 +1,23 @@
+package com.intel.cosbench.driver.web;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.servlet.ModelAndView;
+
+import com.intel.cosbench.service.DriverService;
+import com.intel.cosbench.web.AbstractController;
+
+public class TriggerController extends AbstractController {
+ protected DriverService driver;
+
+ public void setDriver(DriverService driver) {
+ this.driver = driver;
+ }
+ @Override
+ protected ModelAndView process(HttpServletRequest req,
+ HttpServletResponse res) throws Exception {
+ return new ModelAndView();
+ }
+
+}