Merged asterix_lsm_stabilization upto r1547
git-svn-id: https://asterixdb.googlecode.com/svn/trunk/asterix@1622 eaa15691-b419-025a-1212-ee371bd00084
diff --git a/asterix-events/src/main/assembly/binary-assembly.xml b/asterix-events/src/main/assembly/binary-assembly.xml
new file mode 100644
index 0000000..29ebbdd
--- /dev/null
+++ b/asterix-events/src/main/assembly/binary-assembly.xml
@@ -0,0 +1,27 @@
+<assembly>
+ <id>bin</id>
+ <formats>
+ <format>tar.gz</format>
+ <format>tar.bz2</format>
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <directory>src/main/resources/events</directory>
+ <outputDirectory>events</outputDirectory>
+ <includes></includes>
+ </fileSet>
+ <fileSet>
+ <directory>src/main/resources/scripts</directory>
+ <outputDirectory>scripts</outputDirectory>
+ <includes></includes>
+ </fileSet>
+ <fileSet>
+ <directory>target</directory>
+ <outputDirectory>target</outputDirectory>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/api/ClusterInfo.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/api/ClusterInfo.java
new file mode 100644
index 0000000..630f9b3
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/api/ClusterInfo.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.api;
+
+import java.util.List;
+
+public class ClusterInfo {
+
+ List<NodeInfo> nodes;
+
+ public ClusterInfo(List<NodeInfo> nodes) {
+ this.nodes = nodes;
+ }
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/api/NodeInfo.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/api/NodeInfo.java
new file mode 100644
index 0000000..835e0dc
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/api/NodeInfo.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.api;
+
+public class NodeInfo {
+
+ private final String id;
+ private final String ip;
+
+ public NodeInfo(String id, String ip) {
+ this.id = id;
+ this.ip = ip;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getIp() {
+ return ip;
+ }
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventConfig.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventConfig.java
new file mode 100644
index 0000000..9d0138b
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventConfig.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.driver;
+
+import org.kohsuke.args4j.Option;
+
+public class EventConfig {
+
+ @Option(name = "-h", required = false, usage = "Help")
+ public boolean help = false;
+
+ @Option(name = "-d", required = false, usage = "Show the execution on a timeline")
+ public boolean dryRun = false;
+
+ @Option(name = "-s", required = false, usage = "Seed for randomization")
+ public int seed = -1;
+
+ @Option(name = "-c", required = true, usage = "Path to cluster configuration (REQUIRED)")
+ public String clusterPath;
+
+ @Option(name = "-p", required = true, usage = "Path to pattern configuration (REQUIRED)")
+ public String patternPath;
+
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventDriver.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventDriver.java
new file mode 100644
index 0000000..66c0102
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventDriver.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.driver;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+import org.kohsuke.args4j.CmdLineParser;
+
+import edu.uci.ics.asterix.event.management.DefaultOutputHandler;
+import edu.uci.ics.asterix.event.management.EventUtil;
+import edu.uci.ics.asterix.event.management.EventrixClient;
+import edu.uci.ics.asterix.event.management.IOutputHandler;
+import edu.uci.ics.asterix.event.management.Randomizer;
+import edu.uci.ics.asterix.event.schema.cluster.Cluster;
+import edu.uci.ics.asterix.event.schema.cluster.Node;
+import edu.uci.ics.asterix.event.schema.cluster.Property;
+import edu.uci.ics.asterix.event.schema.event.Events;
+import edu.uci.ics.asterix.event.schema.pattern.Patterns;
+
+public class EventDriver {
+
+ public static final String CLIENT_NODE_ID = "client_node";
+ public static final Node CLIENT_NODE = new Node(CLIENT_NODE_ID, "127.0.0.1", null, null, null, null, null, null);
+
+ private static String eventsDir;
+ private static Events events;
+ private static Map<String, String> env = new HashMap<String, String>();
+ private static String scriptDirSuffix;
+
+ public static String getEventsDir() {
+ return eventsDir;
+ }
+
+ public static Events getEvents() {
+ return events;
+ }
+
+ public static Map<String, String> getEnvironment() {
+ return env;
+ }
+
+ public static String getStringifiedEnv(Cluster cluster) {
+ StringBuffer buffer = new StringBuffer();
+ for (Property p : cluster.getEnv().getProperty()) {
+ buffer.append(p.getKey() + "=" + p.getValue() + " ");
+ }
+ return buffer.toString();
+ }
+
+ public static Cluster initializeCluster(String path) throws JAXBException, IOException {
+ File file = new File(path);
+ JAXBContext ctx = JAXBContext.newInstance(Cluster.class);
+ Unmarshaller unmarshaller = ctx.createUnmarshaller();
+ Cluster cluster = (Cluster) unmarshaller.unmarshal(file);
+ for (Property p : cluster.getEnv().getProperty()) {
+ env.put(p.getKey(), p.getValue());
+ }
+ return cluster;
+ }
+
+ public static Patterns initializePatterns(String path) throws JAXBException, IOException {
+ File file = new File(path);
+ JAXBContext ctx = JAXBContext.newInstance(Patterns.class);
+ Unmarshaller unmarshaller = ctx.createUnmarshaller();
+ return (Patterns) unmarshaller.unmarshal(file);
+ }
+
+ private static void initialize(EventConfig eventConfig) throws IOException, JAXBException {
+
+ }
+
+ public static EventrixClient getClient(String eventsDir, Cluster cluster, boolean dryRun) throws Exception {
+ return new EventrixClient(eventsDir, cluster, dryRun, new DefaultOutputHandler());
+ }
+
+ public static EventrixClient getClient(String eventsDir, Cluster cluster, boolean dryRun,
+ IOutputHandler outputHandler) throws Exception {
+ return new EventrixClient(eventsDir, cluster, dryRun, outputHandler);
+ }
+
+ public static void main(String[] args) throws Exception {
+ String eventsHome = System.getenv("EVENT_HOME");
+ if (eventsHome == null) {
+ throw new IllegalStateException("EVENT_HOME is not set");
+ }
+ eventsDir = eventsHome + File.separator + EventUtil.EVENTS_DIR;
+ EventConfig eventConfig = new EventConfig();
+ CmdLineParser parser = new CmdLineParser(eventConfig);
+ try {
+ parser.parseArgument(args);
+ if (eventConfig.help) {
+ parser.printUsage(System.out);
+ }
+ if (eventConfig.seed > 0) {
+ Randomizer.getInstance(eventConfig.seed);
+ }
+ Cluster cluster = initializeCluster(eventConfig.clusterPath);
+ Patterns patterns = initializePatterns(eventConfig.patternPath);
+ initialize(eventConfig);
+
+ if (!eventConfig.dryRun) {
+ prepare(cluster);
+ }
+ EventrixClient client = new EventrixClient(eventsDir, cluster, eventConfig.dryRun,
+ new DefaultOutputHandler());
+ client.submit(patterns);
+ if (!eventConfig.dryRun) {
+ cleanup(cluster);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ parser.printUsage(System.err);
+ }
+ }
+
+ private static void prepare(Cluster cluster) throws IOException, InterruptedException {
+
+ scriptDirSuffix = "" + System.nanoTime();
+ List<String> args = new ArrayList<String>();
+ args.add(scriptDirSuffix);
+ Node clientNode = new Node();
+ clientNode.setId("client");
+ clientNode.setClusterIp("127.0.0.1");
+ for (Node node : cluster.getNode()) {
+ args.add(node.getClusterIp());
+ }
+ EventUtil.executeLocalScript(clientNode, eventsDir + "/" + "events" + "/" + "prepare.sh", args);
+ }
+
+ private static void cleanup(Cluster cluster) throws IOException, InterruptedException {
+ List<String> args = new ArrayList<String>();
+ args.add(scriptDirSuffix);
+ Node clientNode = new Node();
+ clientNode.setId("client");
+ clientNode.setClusterIp("127.0.0.1");
+ for (Node node : cluster.getNode()) {
+ args.add(node.getClusterIp());
+ }
+ EventUtil.executeLocalScript(clientNode, eventsDir + "/" + "events" + "/" + "cleanup.sh", args);
+ }
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/DefaultOutputHandler.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/DefaultOutputHandler.java
new file mode 100644
index 0000000..e8f06a0
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/DefaultOutputHandler.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.management;
+
+import edu.uci.ics.asterix.event.schema.pattern.Event;
+
+public class DefaultOutputHandler implements IOutputHandler {
+
+ @Override
+ public OutputAnalysis reportEventOutput(Event event, String output) {
+ return new OutputAnalysis(true, null);
+ }
+
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/ErrorHandler.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/ErrorHandler.java
new file mode 100644
index 0000000..a6c038b
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/ErrorHandler.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.management;
+
+public class ErrorHandler {
+
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventExecutor.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventExecutor.java
new file mode 100644
index 0000000..6d89c88
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventExecutor.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.management;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+
+import edu.uci.ics.asterix.event.driver.EventDriver;
+import edu.uci.ics.asterix.event.schema.cluster.Cluster;
+import edu.uci.ics.asterix.event.schema.cluster.Node;
+import edu.uci.ics.asterix.event.schema.cluster.Property;
+import edu.uci.ics.asterix.event.schema.pattern.Pattern;
+
+public class EventExecutor {
+
+ public static final String EVENTS_DIR = "events";
+ private static final String EXECUTE_SCRIPT = "execute.sh";
+ private static final String IP_LOCATION = "IP_LOCATION";
+ private static final String CLUSTER_ENV = "ENV";
+ private static final String SCRIPT = "SCRIPT";
+ private static final String ARGS = "ARGS";
+ private static final String DAEMON = "DAEMON";
+
+ public void executeEvent(Node node, String script, List<String> args, boolean isDaemon, Cluster cluster,
+ Pattern pattern, IOutputHandler outputHandler, EventrixClient client) throws IOException {
+ List<String> pargs = new ArrayList<String>();
+ pargs.add("/bin/bash");
+ pargs.add(client.getEventsDir() + File.separator + "scripts" + File.separator + EXECUTE_SCRIPT);
+ StringBuffer envBuffer = new StringBuffer(IP_LOCATION + "=" + node.getClusterIp() + " ");
+ if (!node.getId().equals(EventDriver.CLIENT_NODE_ID) && cluster.getEnv() != null) {
+ for (Property p : cluster.getEnv().getProperty()) {
+ if (p.getKey().equals("JAVA_HOME")) {
+ String val = node.getJavaHome() == null ? p.getValue() : node.getJavaHome();
+ envBuffer.append(p.getKey() + "=" + val + " ");
+ } else if (p.getKey().equals("JAVA_OPTS")) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("\"");
+ String javaOpts = (node.getJavaOpts() == null ? cluster.getJavaOpts() : node.getJavaOpts());
+ if (javaOpts != null) {
+ builder.append(javaOpts);
+ }
+ if (cluster.isDebugEnabled() != null && cluster.isDebugEnabled().booleanValue()) {
+ BigInteger debugPort = node.getDebug() == null ? cluster.getDebug() : node.getDebug();
+ if (debugPort != null) {
+ builder.append("-Xdebug -Xrunjdwp:transport=dt_socket,address=" + debugPort.intValue()
+ + "," + "server=y,suspend=n");
+ }
+ }
+ builder.append("\"");
+ envBuffer.append(p.getKey() + "=" + builder + " ");
+ } else {
+ envBuffer.append(p.getKey() + "=" + p.getValue() + " ");
+ }
+
+ }
+ pargs.add(cluster.getUsername() == null ? System.getProperty("user.name") : cluster.getUsername());
+ }
+
+ StringBuffer argBuffer = new StringBuffer();
+ if (args != null && args.size() > 0) {
+ for (String arg : args) {
+ argBuffer.append(arg + " ");
+ }
+ }
+
+ ProcessBuilder pb = new ProcessBuilder(pargs);
+ pb.environment().put(IP_LOCATION, node.getClusterIp());
+ pb.environment().put(CLUSTER_ENV, envBuffer.toString());
+ pb.environment().put(SCRIPT, script);
+ pb.environment().put(ARGS, argBuffer.toString());
+ pb.environment().put(DAEMON, isDaemon ? "true" : "false");
+
+ Process p = pb.start();
+ if (!isDaemon) {
+ BufferedInputStream bis = new BufferedInputStream(p.getInputStream());
+ StringWriter writer = new StringWriter();
+ IOUtils.copy(bis, writer, "UTF-8");
+ String result = writer.getBuffer().toString();
+ OutputAnalysis analysis = outputHandler.reportEventOutput(pattern.getEvent(), result);
+ if (!analysis.isExpected()) {
+ throw new IOException(analysis.getErrorMessage() + result);
+ }
+ }
+ }
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventTask.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventTask.java
new file mode 100644
index 0000000..2586adf
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventTask.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.management;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Date;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+import org.apache.log4j.Logger;
+
+import edu.uci.ics.asterix.event.driver.EventDriver;
+import edu.uci.ics.asterix.event.schema.cluster.Node;
+import edu.uci.ics.asterix.event.schema.event.Event;
+import edu.uci.ics.asterix.event.schema.pattern.Pattern;
+import edu.uci.ics.asterix.event.schema.pattern.Period;
+
+public class EventTask extends TimerTask {
+
+ public static enum State {
+ INITIALIZED, IN_PROGRESS, COMPLETED, FAILED
+ }
+
+ private static final Logger logger = Logger.getLogger(EventTask.class
+ .getName());
+
+ private Pattern pattern;
+ private Event event;
+ private long interval = 0;
+ private long initialDelay = 0;
+ private int maxOccurs = Integer.MAX_VALUE;
+ private int occurrenceCount = 0;
+ private Timer timer;
+ private String taskScript;
+ private Node location;
+ private List<String> taskArgs;
+ private EventrixClient client;
+ private List<Node> candidateLocations;
+ private boolean dynamicLocation = false;
+ private boolean reuseLocation = false;
+ private State state;
+
+
+
+ public EventTask(Pattern pattern, EventrixClient client) {
+ this.pattern = pattern;
+ this.client = client;
+ Period period = pattern.getPeriod();
+ if (period != null && period.getAbsvalue() != null) {
+ this.interval = EventUtil.parseTimeInterval(period.getAbsvalue(),
+ period.getUnit());
+ }
+ if (pattern.getDelay() != null) {
+ this.initialDelay = EventUtil.parseTimeInterval(new ValueType(
+ pattern.getDelay().getValue()), pattern.getDelay()
+ .getUnit());
+ }
+ if (pattern.getMaxOccurs() != null) {
+ this.maxOccurs = pattern.getMaxOccurs();
+ }
+ this.timer = new Timer();
+ taskArgs = EventUtil.getEventArgs(pattern);
+ candidateLocations = EventUtil.getCandidateLocations(pattern,
+ client.getCluster());
+ if (pattern.getEvent().getNodeid().getValue().getRandom() != null
+ && period != null && maxOccurs > 1) {
+ dynamicLocation = true;
+ reuseLocation = pattern.getEvent().getNodeid().getValue()
+ .getRandom().getRange().isReuse();
+ } else {
+ location = EventUtil.getEventLocation(pattern, candidateLocations,
+ client.getCluster());
+ }
+ String scriptsDir;
+ if (location.getId().equals(EventDriver.CLIENT_NODE_ID)) {
+ scriptsDir = client.getEventsDir() + File.separator + "events";
+ } else {
+ scriptsDir = client.getCluster().getWorkingDir().getDir()
+ + File.separator + "eventrix" + File.separator + "events";
+ }
+ event = EventUtil.getEvent(pattern, client.getEvents());
+ taskScript = scriptsDir + File.separator + event.getScript();
+ state = State.INITIALIZED;
+ }
+
+ public void start() {
+ if (interval > 0) {
+ timer.schedule(this, initialDelay, interval);
+ } else {
+ timer.schedule(this, initialDelay);
+ }
+ }
+
+ @Override
+ public void run() {
+ if (candidateLocations.size() == 0) {
+ timer.cancel();
+ client.notifyCompletion(new EventTaskReport(this));
+ } else {
+ if (dynamicLocation) {
+ location = EventUtil.getEventLocation(pattern,
+ candidateLocations, client.getCluster());
+ if (!reuseLocation) {
+ candidateLocations.remove(location);
+ }
+ }
+
+ logger.debug(EventUtil.dateFormat.format(new Date()) + " "
+ + "EVENT " + pattern.getEvent().getType().toUpperCase()
+ + " at " + location.getId().toUpperCase());
+ try {
+ if (!client.isDryRun()) {
+ new EventExecutor().executeEvent(location, taskScript,
+ taskArgs, event.isDaemon(), client.getCluster(),
+ pattern, client.getErrorHandler(), client);
+ }
+ occurrenceCount++;
+ if (occurrenceCount >= maxOccurs) {
+ timer.cancel();
+ client.notifyCompletion(new EventTaskReport(this));
+ }
+ } catch (IOException ioe) {
+ timer.cancel();
+ client.notifyCompletion(new EventTaskReport(this, false, ioe));
+ }
+ }
+
+ }
+
+ public Node getLocation() {
+ return location;
+ }
+
+ public long getInterval() {
+ return interval;
+ }
+
+ public long getInitialDelay() {
+ return initialDelay;
+ }
+
+ public Pattern getPattern() {
+ return pattern;
+ }
+
+ public State getState() {
+ return state;
+ }
+
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventTaskReport.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventTaskReport.java
new file mode 100644
index 0000000..7ad3682
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventTaskReport.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.management;
+
+import java.io.Serializable;
+
+public class EventTaskReport implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ private final EventTask task;
+ private final boolean success;
+ private final Exception e;
+
+ public EventTaskReport(EventTask task, boolean success, Exception e) {
+ this.task = task;
+ this.success = success;
+ this.e = e;
+ }
+
+ public EventTaskReport(EventTask task) {
+ this.task = task;
+ this.success = true;
+ this.e = null;
+ }
+
+ public Exception getException() {
+ return e;
+ }
+
+ public EventTask getTask() {
+ return task;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventUtil.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventUtil.java
new file mode 100644
index 0000000..e6c58eb
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventUtil.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.management;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import edu.uci.ics.asterix.event.driver.EventDriver;
+import edu.uci.ics.asterix.event.management.ValueType.Type;
+import edu.uci.ics.asterix.event.schema.cluster.Cluster;
+import edu.uci.ics.asterix.event.schema.cluster.Node;
+import edu.uci.ics.asterix.event.schema.event.Event;
+import edu.uci.ics.asterix.event.schema.event.Events;
+import edu.uci.ics.asterix.event.schema.pattern.Pattern;
+
+public class EventUtil {
+
+ public static final String EVENTS_DIR = "events";
+ public static final String CLUSTER_CONF = "config/cluster.xml";
+ public static final String PATTERN_CONF = "config/pattern.xml";
+ public static final DateFormat dateFormat = new SimpleDateFormat(
+ "yyyy/MM/dd HH:mm:ss");
+
+ private static final String IP_LOCATION = "IP_LOCATION";
+ private static final String CLUSTER_ENV = "ENV";
+ private static final String SCRIPT = "SCRIPT";
+ private static final String ARGS = "ARGS";
+ private static final String EXECUTE_SCRIPT = "events/execute.sh";
+
+ public static long parseTimeInterval(ValueType v, String unit)
+ throws IllegalArgumentException {
+ int val = 0;
+ switch (v.getType()) {
+ case ABS:
+ val = Integer.parseInt(v.getAbsoluteValue());
+ break;
+ case RANDOM_MIN_MAX:
+ val = Randomizer.getInstance().getRandomInt(v.getMin(), v.getMax());
+ break;
+ case RANDOM_RANGE:
+ String[] values = v.getRangeSet();
+ val = Integer.parseInt(values[Randomizer.getInstance()
+ .getRandomInt(0, values.length - 1)]);
+ break;
+ }
+ return computeInterval(val, unit);
+ }
+
+ public static long parseTimeInterval(String v, String unit)
+ throws IllegalArgumentException {
+ int value = Integer.parseInt(v);
+ return computeInterval(value, unit);
+ }
+
+ private static long computeInterval(int val, String unit) {
+ int vmult = 1;
+ if ("hr".equalsIgnoreCase(unit)) {
+ vmult = 3600 * 1000;
+ } else if ("min".equalsIgnoreCase(unit)) {
+ vmult = 60 * 1000;
+ } else if ("sec".equalsIgnoreCase(unit)) {
+ vmult = 1000;
+ } else
+ throw new IllegalArgumentException(
+ " invalid unit value specified for frequency (hr,min,sec)");
+ return val * vmult;
+
+ }
+
+ public static Event getEvent(Pattern pattern, Events events) {
+ for (Event event : events.getEvent()) {
+ if (event.getType().equals(pattern.getEvent().getType())) {
+ return event;
+ }
+ }
+ throw new IllegalArgumentException(" Unknown event type"
+ + pattern.getEvent().getType());
+ }
+
+ public static Node getEventLocation(Pattern pattern,
+ List<Node> candidateLocations, Cluster cluster) {
+ ValueType value = new ValueType(pattern.getEvent().getNodeid()
+ .getValue());
+ Node location = null;
+ Type vtype = value.getType();
+
+ switch (vtype) {
+ case ABS:
+ location = getNodeFromId(value.getAbsoluteValue(), cluster);
+ break;
+ case RANDOM_RANGE:
+ int nodeIndex = Randomizer.getInstance().getRandomInt(0,
+ candidateLocations.size() - 1);
+ location = candidateLocations.get(nodeIndex);
+ break;
+ case RANDOM_MIN_MAX:
+ throw new IllegalStateException(
+ " Canont configure a min max value range for location");
+ }
+ return location;
+
+ }
+
+ public static List<Node> getCandidateLocations(Pattern pattern,
+ Cluster cluster) {
+ ValueType value = new ValueType(pattern.getEvent().getNodeid()
+ .getValue());
+ List<Node> candidateList = new ArrayList<Node>();
+ switch (value.getType()) {
+ case ABS:
+ candidateList.add(getNodeFromId(value.getAbsoluteValue(), cluster));
+ break;
+ case RANDOM_RANGE:
+ boolean anyOption = false;
+ String[] values = value.getRangeSet();
+ for (String v : values) {
+ if (v.equalsIgnoreCase("ANY")) {
+ anyOption = true;
+ }
+ }
+ if (anyOption) {
+ for (Node node : cluster.getNode()) {
+ candidateList.add(node);
+ }
+ } else {
+ boolean found = false;
+ for (String v : values) {
+ for (Node node : cluster.getNode()) {
+ if (node.getId().equals(v)) {
+ candidateList.add(node);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ throw new IllegalStateException("Unknonw nodeId : " + v);
+ }
+ found = false;
+ }
+
+ }
+ String[] excluded = value.getRangeExcluded();
+ if (excluded != null && excluded.length > 0) {
+ List<Node> markedForRemoval = new ArrayList<Node>();
+ for (String exclusion : excluded) {
+ for (Node node : candidateList) {
+ if (node.getId().equals(exclusion)) {
+ markedForRemoval.add(node);
+ }
+ }
+ }
+ candidateList.removeAll(markedForRemoval);
+ }
+ break;
+ case RANDOM_MIN_MAX:
+ throw new IllegalStateException(
+ " Invalid value configured for location");
+ }
+ return candidateList;
+ }
+
+ private static Node getNodeFromId(String nodeid, Cluster cluster) {
+ if (nodeid.equals(EventDriver.CLIENT_NODE.getId())) {
+ return EventDriver.CLIENT_NODE;
+ }
+
+ if (nodeid.equals(cluster.getMasterNode().getId())) {
+ String javaOpts = cluster.getMasterNode().getJavaOpts() == null ? cluster
+ .getJavaOpts() : cluster.getMasterNode().getJavaOpts();
+ String logDir = cluster.getMasterNode().getLogdir() == null ? cluster
+ .getLogdir() : cluster.getMasterNode().getLogdir();
+ String javaHome = cluster.getMasterNode().getJavaHome() == null ? cluster
+ .getJavaHome() : cluster.getMasterNode().getJavaHome();
+ BigInteger debug = cluster.getMasterNode().getDebug();
+ return new Node(cluster.getMasterNode().getId(), cluster
+ .getMasterNode().getClusterIp(), javaHome, javaOpts,
+ logDir, null, null, debug);
+ }
+
+ List<Node> nodeList = cluster.getNode();
+ for (Node node : nodeList) {
+ if (node.getId().equals(nodeid)) {
+ return node;
+ }
+ }
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(EventDriver.CLIENT_NODE.getId() + ",");
+ buffer.append(cluster.getMasterNode().getId() + ",");
+ for (Node v : cluster.getNode()) {
+ buffer.append(v.getId() + ",");
+ }
+ buffer.deleteCharAt(buffer.length() - 1);
+ throw new IllegalArgumentException("Unknown node id :" + nodeid
+ + " valid ids:" + buffer);
+ }
+
+ public static void executeEventScript(Node node, String script,
+ List<String> args, Cluster cluster) throws IOException,
+ InterruptedException {
+ List<String> pargs = new ArrayList<String>();
+ pargs.add("/bin/bash");
+ pargs.add(EventDriver.getEventsDir() + "/" + EXECUTE_SCRIPT);
+ StringBuffer argBuffer = new StringBuffer();
+ String env = EventDriver.getStringifiedEnv(cluster) + " " + IP_LOCATION
+ + "=" + node.getClusterIp();
+ if (args != null) {
+ for (String arg : args) {
+ argBuffer.append(arg + " ");
+ }
+ }
+ ProcessBuilder pb = new ProcessBuilder(pargs);
+ pb.environment().putAll(EventDriver.getEnvironment());
+ pb.environment().put(IP_LOCATION, node.getClusterIp());
+ pb.environment().put(CLUSTER_ENV, env);
+ pb.environment().put(SCRIPT, script);
+ pb.environment().put(ARGS, argBuffer.toString());
+ pb.start();
+ }
+
+ public static void executeLocalScript(Node node, String script,
+ List<String> args) throws IOException, InterruptedException {
+ List<String> pargs = new ArrayList<String>();
+ pargs.add("/bin/bash");
+ pargs.add(script);
+ if (args != null) {
+ pargs.addAll(args);
+ }
+ ProcessBuilder pb = new ProcessBuilder(pargs);
+ pb.environment().putAll(EventDriver.getEnvironment());
+ pb.environment().put(IP_LOCATION, node.getClusterIp());
+ pb.start();
+ }
+
+ public static List<String> getEventArgs(Pattern pattern) {
+ List<String> pargs = new ArrayList<String>();
+ if (pattern.getEvent().getPargs() == null) {
+ return pargs;
+ }
+ String[] args = pattern.getEvent().getPargs().split(" ");
+ for (String arg : args) {
+ pargs.add(arg.trim());
+ }
+ return pargs;
+ }
+
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventrixClient.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventrixClient.java
new file mode 100644
index 0000000..6f4336d
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventrixClient.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.management;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Logger;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+import edu.uci.ics.asterix.event.driver.EventDriver;
+import edu.uci.ics.asterix.event.schema.cluster.Cluster;
+import edu.uci.ics.asterix.event.schema.cluster.Node;
+import edu.uci.ics.asterix.event.schema.event.Events;
+import edu.uci.ics.asterix.event.schema.pattern.Event;
+import edu.uci.ics.asterix.event.schema.pattern.Nodeid;
+import edu.uci.ics.asterix.event.schema.pattern.Pattern;
+import edu.uci.ics.asterix.event.schema.pattern.Patterns;
+import edu.uci.ics.asterix.event.schema.pattern.Value;
+
+public class EventrixClient {
+
+ private static final Logger LOGGER = Logger.getLogger(EventrixClient.class.getName());
+
+ private EventTask[] tasks;
+ private boolean dryRun = false;
+ private LinkedBlockingQueue<EventTaskReport> msgInbox = new LinkedBlockingQueue<EventTaskReport>();
+ private AtomicInteger pendingTasks = new AtomicInteger(0);
+ private final Cluster cluster;
+ private IPatternListener listener;
+ private IOutputHandler outputHandler;
+ private Events events;
+ private String eventsDir;
+
+ public EventrixClient(String eventsDir, Cluster cluster, boolean dryRun, IOutputHandler outputHandler)
+ throws Exception {
+ this.eventsDir = eventsDir;
+ this.events = initializeEvents();
+ this.cluster = cluster;
+ this.dryRun = dryRun;
+ this.outputHandler = outputHandler;
+ if (!dryRun) {
+ initializeCluster(eventsDir);
+ }
+ }
+
+ public void submit(Patterns patterns) throws Exception {
+ initTasks(patterns);
+ try {
+ waitForCompletion();
+ } catch (InterruptedException ie) {
+ LOGGER.info("Interrupted exception :" + ie);
+ } catch (Exception e) {
+ throw e;
+ }
+
+ }
+
+ public void submit(Patterns patterns, IPatternListener listener) throws Exception {
+ this.listener = listener;
+ initTasks(patterns);
+ }
+
+ private void initTasks(Patterns patterns) {
+ tasks = new EventTask[patterns.getPattern().size()];
+ pendingTasks.set(tasks.length);
+ int index = 0;
+ for (Pattern pattern : patterns.getPattern()) {
+ tasks[index] = new EventTask(pattern, this);
+ tasks[index].start();
+ index++;
+ }
+ }
+
+ public Cluster getCluster() {
+ return cluster;
+ }
+
+ public boolean isDryRun() {
+ return dryRun;
+ }
+
+ public Events getEvents() {
+ return events;
+ }
+
+ public String getEventsDir() {
+ return eventsDir;
+ }
+
+ public synchronized void notifyCompletion(EventTaskReport report) {
+
+ if (report.isSuccess()) {
+ if (listener != null) {
+ pendingTasks.decrementAndGet();
+ listener.eventCompleted(report);
+ if (pendingTasks.get() == 0) {
+ listener.jobCompleted();
+ }
+ } else {
+ try {
+ msgInbox.put(report);
+ } catch (InterruptedException e) {
+ }
+ }
+ } else {
+ for (EventTask t : tasks) {
+ if (t.getState() == EventTask.State.INITIALIZED || t.getState() == EventTask.State.IN_PROGRESS) {
+ t.cancel();
+ }
+ }
+ if (listener != null) {
+ listener.jobFailed(report);
+ } else {
+ try {
+ msgInbox.put(report);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+
+ private void waitForCompletion() throws Exception {
+ while (true) {
+ EventTaskReport report = msgInbox.take();
+ if (report.isSuccess()) {
+ if (pendingTasks.decrementAndGet() == 0) {
+ break;
+ }
+ } else {
+ throw new RuntimeException(report.getException().getMessage());
+ }
+ }
+ }
+
+ private void initializeCluster(String eventsDir) throws Exception {
+ Patterns patterns = initPattern(eventsDir);
+ submit(patterns);
+ }
+
+ private Patterns initPattern(String eventsDir) {
+ Nodeid nodeid = new Nodeid(new Value(null,
+ EventDriver.CLIENT_NODE.getId()));
+ List<Pattern> patternList = new ArrayList<Pattern>();
+ String workingDir = cluster.getWorkingDir().getDir();
+ String username = cluster.getUsername() == null ? System
+ .getProperty("user.name") : cluster.getUsername();
+ patternList.add(getDirectoryTransferPattern(username, eventsDir,
+ nodeid, cluster.getMasterNode().getClusterIp(), workingDir));
+
+ if (!cluster.getWorkingDir().isNFS()) {
+ for (Node node : cluster.getNode()) {
+ patternList.add(getDirectoryTransferPattern(username,
+ eventsDir, nodeid, node.getClusterIp(), workingDir));
+ }
+ }
+ Patterns patterns = new Patterns(patternList);
+ return patterns;
+ }
+
+ private Pattern getDirectoryTransferPattern(String username, String src, Nodeid srcNode, String destNodeIp,
+ String destDir) {
+ String pargs = username + " " + src + " " + destNodeIp + " " + destDir;
+ Event event = new Event("directory_transfer", srcNode, pargs);
+ return new Pattern(null, 1, null, event);
+ }
+
+ public IOutputHandler getErrorHandler() {
+ return outputHandler;
+ }
+
+ private Events initializeEvents() throws JAXBException, FileNotFoundException {
+ File file = new File(eventsDir + File.separator + "events" + File.separator + "events.xml");
+ JAXBContext eventCtx = JAXBContext.newInstance(Events.class);
+ Unmarshaller unmarshaller = eventCtx.createUnmarshaller();
+ events = (Events) unmarshaller.unmarshal(file);
+ return events;
+ }
+
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/IOutputHandler.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/IOutputHandler.java
new file mode 100644
index 0000000..c7929cb
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/IOutputHandler.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.management;
+
+import edu.uci.ics.asterix.event.schema.pattern.Event;
+
+public interface IOutputHandler {
+
+ public OutputAnalysis reportEventOutput(Event event, String output);
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/IPatternListener.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/IPatternListener.java
new file mode 100644
index 0000000..06a56cf
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/IPatternListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.management;
+
+public interface IPatternListener {
+
+ public void eventCompleted(EventTaskReport report);
+
+ public void jobCompleted();
+
+ public void jobFailed(EventTaskReport report);
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/OutputAnalysis.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/OutputAnalysis.java
new file mode 100644
index 0000000..2845ede
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/OutputAnalysis.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.management;
+
+public class OutputAnalysis {
+
+ private final boolean expected;
+ private final String errorMessage;
+
+ public OutputAnalysis(boolean expected, String errorMessage) {
+ this.expected = expected;
+ this.errorMessage = errorMessage;
+ }
+
+ public boolean isExpected() {
+ return expected;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/Randomizer.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/Randomizer.java
new file mode 100644
index 0000000..e59e154
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/Randomizer.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.management;
+
+import java.util.Random;
+import java.util.logging.Logger;
+
+public class Randomizer {
+
+ private static final Logger LOGGER = Logger.getLogger(Randomizer.class
+ .getName());
+ private static Randomizer INSTANCE;
+ private final Random random;
+ private final int seed;
+
+ public static Randomizer getInstance(int seed) {
+ if (INSTANCE == null) {
+ INSTANCE = new Randomizer(seed);
+ }
+ return INSTANCE;
+ }
+
+ public static Randomizer getInstance() {
+ if (INSTANCE == null) {
+ INSTANCE = new Randomizer();
+ }
+ return INSTANCE;
+ }
+
+ private Randomizer() {
+ Random rm = new Random();
+ seed = rm.nextInt(10000);
+ random = new Random(seed);
+ LOGGER.info("SEED:" + seed);
+ }
+
+ private Randomizer(int seed) {
+ this.seed = seed;
+ random = new Random(seed);
+ LOGGER.info("SEED:" + seed);
+ }
+
+ public Random getRandom() {
+ return random;
+ }
+
+ public int getSeed() {
+ return seed;
+ }
+
+ public int getRandomInt(int min, int max) {
+ return min + random.nextInt(max - min + 1);
+ }
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/ValueType.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/ValueType.java
new file mode 100644
index 0000000..8aa5cc5
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/ValueType.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.management;
+
+import edu.uci.ics.asterix.event.schema.pattern.Value;
+
+public class ValueType {
+
+ public static enum Type {
+ ABS, RANDOM_RANGE, RANDOM_MIN_MAX
+ }
+
+ private Value value;
+ private Type type;
+
+ public ValueType(Value value) {
+ this.value = value;
+ if (value.getAbsvalue() != null) {
+ type = Type.ABS;
+ } else if (value.getRandom() != null) {
+ if (value.getRandom().getMinmax() != null) {
+ type = Type.RANDOM_MIN_MAX;
+ } else if (value.getRandom().getRange() != null) {
+ type = Type.RANDOM_RANGE;
+ } else {
+ throw new IllegalStateException("Incorrect value type");
+ }
+ }
+ }
+
+ public int getMin() {
+ switch (type) {
+ case RANDOM_MIN_MAX:
+ return Integer.parseInt(value.getRandom().getMinmax().getMin());
+ default:
+ throw new IllegalStateException("");
+ }
+ }
+
+ public int getMax() {
+ switch (type) {
+ case RANDOM_MIN_MAX:
+ return Integer.parseInt(value.getRandom().getMinmax().getMax());
+ default:
+ throw new IllegalStateException("");
+ }
+ }
+
+ public String[] getRangeSet() {
+ switch (type) {
+ case RANDOM_RANGE:
+ return value.getRandom().getRange().getSet().split(" ");
+ default:
+ throw new IllegalStateException("");
+ }
+ }
+
+ public String[] getRangeExcluded() {
+ switch (type) {
+ case RANDOM_RANGE:
+ String exl = value.getRandom().getRange().getExclude();
+ return exl != null ? exl.split(" ") : null;
+ default:
+ throw new IllegalStateException("");
+ }
+ }
+
+ public String getAbsoluteValue() {
+ switch (type) {
+ case ABS:
+ return value.getAbsvalue();
+ default:
+ throw new IllegalStateException("");
+ }
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/xml/PatternParser.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/xml/PatternParser.java
new file mode 100644
index 0000000..426279c
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/xml/PatternParser.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * 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 from
+ *
+ * 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 edu.uci.ics.asterix.event.xml;
+
+public class PatternParser {
+
+ public static void parsePattern(String path){
+
+ }
+}
+
diff --git a/asterix-events/src/main/resources/events/backup/backup.sh b/asterix-events/src/main/resources/events/backup/backup.sh
new file mode 100755
index 0000000..556ca39
--- /dev/null
+++ b/asterix-events/src/main/resources/events/backup/backup.sh
@@ -0,0 +1,72 @@
+WORKING_DIR=$1
+ASTERIX_INSTANCE_NAME=$2
+ASTERIX_IODEVICES=$3
+NODE_STORE=$4
+ASTERIX_ROOT_METADATA_DIR=$5
+TXN_LOG_DIR_NAME=$6
+BACKUP_ID=$7
+BACKUP_DIR=$8
+BACKUP_TYPE=$9
+NODE_ID=${10}
+
+nodeIODevices=$(echo $ASTERIX_IODEVICES | tr "," "\n")
+
+if [ $BACKUP_TYPE == "hdfs" ];
+then
+ HDFS_URL=${11}
+ HADOOP_VERSION=${12}
+ export HADOOP_HOME=$WORKING_DIR/hadoop-$HADOOP_VERSION
+ index=1
+ for nodeIODevice in $nodeIODevices
+ do
+ STORE_DIR=$nodeIODevice/$NODE_STORE
+ TXN_LOG_DIR=$nodeIODevice/$TXN_LOG_DIR_NAME
+ NODE_BACKUP_DIR=$BACKUP_DIR/$ASTERIX_INSTANCE_NAME/$BACKUP_ID/$NODE_ID/
+
+ # make the destination directory
+ $HADOOP_HOME/bin/hadoop fs -mkdir $STORE_DIR $HDFS_URL/$NODE_BACKUP_DIR
+
+ # copy store directory
+ $HADOOP_HOME/bin/hadoop fs -copyFromLocal $STORE_DIR $HDFS_URL/$NODE_BACKUP_DIR/
+
+ # copy asterix root metadata directory and log directory from the primary(first) iodevice
+ if [ $index -eq 1 ];
+ then
+ # copy asterix root metadata directory
+ $HADOOP_HOME/bin/hadoop fs -copyFromLocal $nodeIODevice/$ASTERIX_ROOT_METADATA_DIR $HDFS_URL/$NODE_BACKUP_DIR/
+
+ # copy log directory
+ $HADOOP_HOME/bin/hadoop fs -copyFromLocal $TXN_LOG_DIR $HDFS_URL/$NODE_BACKUP_DIR/
+ fi
+
+ index=`expr $index + 1`
+ done
+else
+ index=1
+ for nodeIODevice in $nodeIODevices
+ do
+ STORE_DIR=$nodeIODevice/$NODE_STORE
+ TXN_LOG_DIR=$nodeIODevice/$TXN_LOG_DIR_NAME
+ NODE_BACKUP_DIR=$BACKUP_DIR/$ASTERIX_INSTANCE_NAME/$BACKUP_ID/$NODE_ID
+
+ # create the backup directory, if it does not exists
+ if [ ! -d $NODE_BACKUP_DIR ];
+ then
+ mkdir -p $NODE_BACKUP_DIR
+ fi
+
+ # copy store directory
+ cp -r $STORE_DIR $NODE_BACKUP_DIR/
+
+ # copy asterix root metadata directory and log directory from the primary(first) iodevice
+ if [ $index -eq 1 ];
+ then
+ cp -r $nodeIODevice/$ASTERIX_ROOT_METADATA_DIR $NODE_BACKUP_DIR/
+
+ # copy log directory
+ cp -r $TXN_LOG_DIR $NODE_BACKUP_DIR/
+ fi
+
+ index=`expr $index + 1`
+ done
+fi
diff --git a/asterix-events/src/main/resources/events/cc_failure/cc_failure.sh b/asterix-events/src/main/resources/events/cc_failure/cc_failure.sh
new file mode 100755
index 0000000..aa722e5
--- /dev/null
+++ b/asterix-events/src/main/resources/events/cc_failure/cc_failure.sh
@@ -0,0 +1,6 @@
+#kill -9 `ps -ef | grep hyracks | grep -v grep | cut -d "/" -f1 | tr -s " " | cut -d " " -f2`
+CC_PARENT_ID_INFO=`ps -ef | grep asterix | grep cc_start | grep -v ssh`
+CC_PARENT_ID=`echo $CC_PARENT_ID_INFO | tr -s " " | cut -d " " -f2`
+CC_ID_INFO=`ps -ef | grep asterix | grep $CC_PARENT_ID | grep -v bash`
+CC_ID=`echo $CC_ID_INFO | tr -s " " | cut -d " " -f2`
+kill -9 $CC_ID
diff --git a/asterix-events/src/main/resources/events/cc_start/cc_start.sh b/asterix-events/src/main/resources/events/cc_start/cc_start.sh
new file mode 100755
index 0000000..37645bc
--- /dev/null
+++ b/asterix-events/src/main/resources/events/cc_start/cc_start.sh
@@ -0,0 +1,5 @@
+if [ ! -d $LOG_DIR ];
+then
+ mkdir -p $LOG_DIR
+fi
+$ASTERIX_HOME/bin/asterixcc -client-net-ip-address $CLIENT_NET_IP -client-net-port 1098 -cluster-net-ip-address $CLUSTER_NET_IP -cluster-net-port 1099 -http-port 8888 &> $LOG_DIR/cc.log
diff --git a/asterix-events/src/main/resources/events/events.xml b/asterix-events/src/main/resources/events/events.xml
new file mode 100644
index 0000000..f85e3ea
--- /dev/null
+++ b/asterix-events/src/main/resources/events/events.xml
@@ -0,0 +1,106 @@
+<events xmlns="events">
+ <event>
+ <type>node_join</type>
+ <script>node_join/nc_join.sh</script>
+ <description>Creates a NodeController process at a specified location.</description>
+ <args>location_of_cc location(hostname/ip_address) node_controller_id</args>
+ <daemon>true</daemon>
+ </event>
+ <event>
+ <type>node_failure</type>
+ <script>node_failure/nc_failure.sh</script>
+ <description>Kills a NodeController process at a specified location.</description>
+ <args>node_controller_id</args>
+ <daemon>false</daemon>
+ </event>
+ <event>
+ <type>cc_start</type>
+ <script>cc_start/cc_start.sh</script>
+ <description>Starts a ClusterController process at a specified location.</description>
+ <args></args>
+ <daemon>true</daemon>
+ </event>
+ <event>
+ <type>cc_failure</type>
+ <script>cc_failure/cc_failure.sh</script>
+ <description>Kills the Cluster Controller process running at a specified location.</description>
+ <args></args>
+ <daemon>false</daemon>
+ </event>
+ <event>
+ <type>node_restart</type>
+ <script>node_restart/nc_restart.sh</script>
+ <description>Shuts and restarts a NodeControllerProcess after a specified time interval, at a specified location</description>
+ <args>address of cc, node controller id and sleep interval(seconds)</args>
+ <daemon>true</daemon>
+ </event>
+ <event>
+ <type>asterix_deploy</type>
+ <script>asterix_deploy/asterix_deploy.sh</script>
+ <description>Deploys Asterix application on a cluster running hyracks</description>
+ <args>IP address of the node running the hyracks cluster controller</args>
+ <daemon>false</daemon>
+ </event>
+ <event>
+ <type>zookeeper_start</type>
+ <script>zookeeper/start.sh</script>
+ <description>Launches ZooKeeper server process</description>
+ <args>IP address of the ZooKeeper server</args>
+ <daemon>true</daemon>
+ </event>
+ <event>
+ <type>zookeeper_stop</type>
+ <script>zookeeper/stop.sh</script>
+ <description>Terminates ZooKeeper server process</description>
+ <args>IP address of the ZooKeeper server</args>
+ <daemon>false</daemon>
+ </event>
+ <event>
+ <type>file_transfer</type>
+ <script>file/transfer.sh</script>
+ <description>Copies a file on the local file system to a remote node</description>
+ <args>local_source_path destination_node destination_path</args>
+ <daemon>false</daemon>
+ </event>
+ <event>
+ <type>directory_transfer</type>
+ <script>file/dir_transfer.sh</script>
+ <description>Copies a directory (and its contents) on the local file system to a remote node</description>
+ <args>local_source_path destination_node destination_path</args>
+ <daemon>false</daemon>
+ </event>
+ <event>
+ <type>file_delete</type>
+ <script>file/delete.sh</script>
+ <description>Deletes a file on the local file system to a remote node</description>
+ <args>local_source_path destination_node destination_path</args>
+ <daemon>false</daemon>
+ </event>
+ <event>
+ <type>backup</type>
+ <script>backup/backup.sh</script>
+ <description>Takes a backup of an Asterix instance</description>
+ <args>Asterix_data_dir HDFSurl</args>
+ <daemon>false</daemon>
+ </event>
+ <event>
+ <type>restore</type>
+ <script>restore/restore.sh</script>
+ <description>Restores an Asterix instance from a back up</description>
+ <args>Asterix_data_dir HDFSurl</args>
+ <daemon>false</daemon>
+ </event>
+ <event>
+ <type>hdfs_delete</type>
+ <script>hdfs/delete.sh</script>
+ <description>Deletes an HDFS path</description>
+ <args>WorkingDir HadoopVersion HDFSUrl Path_to_Delete</args>
+ <daemon>false</daemon>
+ </event>
+ <event>
+ <type>node_info</type>
+ <script>node_info/node_info.sh</script>
+ <description>Retrieved environment information for a node</description>
+ <daemon>false</daemon>
+ </event>
+</events>
diff --git a/asterix-events/src/main/resources/events/file/delete.sh b/asterix-events/src/main/resources/events/file/delete.sh
new file mode 100755
index 0000000..d5ac3ff
--- /dev/null
+++ b/asterix-events/src/main/resources/events/file/delete.sh
@@ -0,0 +1,3 @@
+PATH_TO_DELETE=$1
+echo "rm -rf $PATH_TO_DELETE" >> ~/backup.log
+rm -rf $PATH_TO_DELETE
diff --git a/asterix-events/src/main/resources/events/file/dir_transfer.sh b/asterix-events/src/main/resources/events/file/dir_transfer.sh
new file mode 100755
index 0000000..af7da70
--- /dev/null
+++ b/asterix-events/src/main/resources/events/file/dir_transfer.sh
@@ -0,0 +1,7 @@
+USERNAME=$1
+DIR_TO_TRANSFER=$2
+DEST_HOST=$3
+DEST_DIR=$4
+ssh -l $USERNAME $DEST_HOST "mkdir -p $DEST_DIR"
+echo "scp -r $DIR_TO_TRANSFER $USERNAME@$DEST_HOST:$DEST_DIR/"
+scp -r $DIR_TO_TRANSFER $USERNAME@$DEST_HOST:$DEST_DIR/
diff --git a/asterix-events/src/main/resources/events/file/transfer.sh b/asterix-events/src/main/resources/events/file/transfer.sh
new file mode 100755
index 0000000..fbd4554
--- /dev/null
+++ b/asterix-events/src/main/resources/events/file/transfer.sh
@@ -0,0 +1,24 @@
+USERNAME=$1
+FILE_TO_TRANSFER=$2
+DEST_HOST=$3
+DEST_DIR=$4
+POST_ACTION=$5
+ssh -l $USERNAME $DEST_HOST "mkdir -p $DEST_DIR"
+echo "scp $FILE_TO_TRANSFER $USERNAME@$DEST_HOST:$DEST_DIR/"
+scp $FILE_TO_TRANSFER $USERNAME@$DEST_HOST:$DEST_DIR/
+if [ $POST_ACTION == "unpack" ]
+ then
+ filename=`echo ${FILE_TO_TRANSFER##*/}`
+ fileType=`echo ${FILE_TO_TRANSFER##*.}`
+ if [ $fileType == "tar" ]
+ then
+ echo "ssh -l $USERNAME $DEST_HOST cd $DEST_DIR && tar xf $filename"
+ ssh -l $USERNAME $DEST_HOST "cd $DEST_DIR && tar xf $filename"
+ else if [ $fileType == "zip" ]
+ then
+ echo "ssh -l $USERNAME $DEST_HOST unzip -o -q -d $DEST_DIR $DEST_DIR/$filename"
+ ssh -l $USERNAME $DEST_HOST "unzip -o -q -d $DEST_DIR $DEST_DIR/$filename"
+ ssh -l $USERNAME $DEST_HOST "chmod -R 755 $DEST_DIR"
+ fi
+ fi
+fi
diff --git a/asterix-events/src/main/resources/events/hdfs/delete.sh b/asterix-events/src/main/resources/events/hdfs/delete.sh
new file mode 100755
index 0000000..6ff54ee
--- /dev/null
+++ b/asterix-events/src/main/resources/events/hdfs/delete.sh
@@ -0,0 +1,7 @@
+WORKING_DIR=$1
+HADOOP_VERSION=$2
+HDFS_URL=$3
+HDFS_PATH=$4
+export HADOOP_HOME=$WORKING_DIR/hadoop-$HADOOP_VERSION
+echo "$HADOOP_HOME/bin/hadoop fs -rmr $HDFS_URL/$HDFS_PATH"
+$HADOOP_HOME/bin/hadoop fs -rmr $HDFS_URL/$HDFS_PATH
diff --git a/asterix-events/src/main/resources/events/node_failure/nc_failure.sh b/asterix-events/src/main/resources/events/node_failure/nc_failure.sh
new file mode 100755
index 0000000..c562bf2
--- /dev/null
+++ b/asterix-events/src/main/resources/events/node_failure/nc_failure.sh
@@ -0,0 +1,15 @@
+NC_ID=$1
+
+INFO=`ps -ef | grep nc_join | grep -v grep | grep -v ssh| grep $NC_ID | head -n 1`
+PARENT_ID=`echo $INFO | cut -d " " -f2`
+PID_INFO=`ps -ef | grep asterix | grep -v grep | grep -v nc_join | grep $PARENT_ID`
+PID=`echo $PID_INFO | cut -d " " -f2`
+kill -15 $PID
+
+cmd_output=$(jps|grep $PID)
+while [ ${#cmd_output} -ne 0 ]
+do
+ sleep 1
+ kill -15 $PID
+ cmd_output=$(jps|grep $PID)
+done
diff --git a/asterix-events/src/main/resources/events/node_info/node_info.sh b/asterix-events/src/main/resources/events/node_info/node_info.sh
new file mode 100755
index 0000000..2179d5a
--- /dev/null
+++ b/asterix-events/src/main/resources/events/node_info/node_info.sh
@@ -0,0 +1,2 @@
+JAVA_VERSION=`java -version 2>&1 |awk 'NR==1{ gsub(/"/,""); print $3 }'`
+echo "java_version=$JAVA_VERSION" 1>&2
diff --git a/asterix-events/src/main/resources/events/node_join/nc_join.sh b/asterix-events/src/main/resources/events/node_join/nc_join.sh
new file mode 100755
index 0000000..6b5280b
--- /dev/null
+++ b/asterix-events/src/main/resources/events/node_join/nc_join.sh
@@ -0,0 +1,8 @@
+CC_HOST=$1
+NC_ID=$2
+IO_DEVICES=$3
+if [ ! -d $LOG_DIR ];
+then
+ mkdir -p $LOG_DIR
+fi
+$ASTERIX_HOME/bin/asterixnc -node-id $NC_ID -cc-host $CC_HOST -cc-port 1099 -cluster-net-ip-address $IP_LOCATION -data-ip-address $IP_LOCATION -iodevices $IO_DEVICES -result-ip-address $IP_LOCATION &> $LOG_DIR/${NC_ID}.log
diff --git a/asterix-events/src/main/resources/events/node_restart/nc_restart.sh b/asterix-events/src/main/resources/events/node_restart/nc_restart.sh
new file mode 100755
index 0000000..961ce8d
--- /dev/null
+++ b/asterix-events/src/main/resources/events/node_restart/nc_restart.sh
@@ -0,0 +1,21 @@
+CC_HOST=$1
+NC_ID=$2
+SLEEP_TIME=$3
+
+if [ $NC_ID == 'ANY' ]
+then
+ NC_ID="."
+ PARENT_ID=`ps -ej | tr -s " " | grep nc_join | grep -v grep | grep -v ssh | cut -d " " -f2 | head -n 1`
+ PARENT_PROCESS_ENTRY=`ps -ef | grep $PARENT_ID | grep -v grep | head -n 1`
+ NC_ID=`echo ${PARENT_PROCESS_ENTRY##* }`
+ echo "NCid is $NC_ID" >> ~/try.txt
+else
+ PARENT_ID=`ps -ej | tr -s " " | grep nc_join | grep -v grep | grep -v ssh | grep $NC_ID | cut -d " " -f2 | head -n 1`
+fi
+
+PID=`ps -ej | tr -s " " | grep hyracks | grep -v grep | grep -v nc_join | grep $PARENT_ID | cut -d " " -f2 | head -n 1`
+kill -9 $PID
+
+sleep $3
+
+$HYRACKS_HOME/hyracks-server/target/hyracks-server-0.2.2-SNAPSHOT-binary-assembly/bin/hyracksnc -node-id $NC_ID -cc-host $CC_HOST -cc-port 1099 -cluster-net-ip-address $IP_LOCATION -data-ip-address $IP_LOCATION
diff --git a/asterix-events/src/main/resources/events/restore/restore.sh b/asterix-events/src/main/resources/events/restore/restore.sh
new file mode 100755
index 0000000..6396eec
--- /dev/null
+++ b/asterix-events/src/main/resources/events/restore/restore.sh
@@ -0,0 +1,75 @@
+WORKING_DIR=$1
+ASTERIX_INSTANCE_NAME=$2
+ASTERIX_IODEVICES=$3
+NODE_STORE=$4
+ASTERIX_ROOT_METADATA_DIR=$5
+TXN_LOG_DIR_NAME=$6
+BACKUP_ID=$7
+BACKUP_DIR=$8
+BACKUP_TYPE=$9
+NODE_ID=${10}
+HDFS_URL=${11}
+HADOOP_VERSION=${12}
+HADOOP_HOME=$WORKING_DIR/hadoop-$HADOOP_VERSION
+
+iodevices=$(echo $ASTERIX_IODEVICES | tr "," "\n")
+
+index=1
+for iodevice in $iodevices
+do
+ NODE_BACKUP_DIR=$BACKUP_DIR/$ASTERIX_INSTANCE_NAME/$BACKUP_ID/$NODE_ID
+
+ # remove the existing store directory
+ STORE_DIR=$iodevice/$NODE_STORE
+
+ # if STORE_DIR ends with a /, remove it
+ if [ ${STORE_DIR:${#STORE_DIR}-1} == "/" ];
+ then
+ STORE_DIR=${STORE_DIR:0:${#STORE_DIR}-1}
+ fi
+
+ DEST_STORE_DIR=${STORE_DIR%/*}
+ SOURCE_STORE_DIR=${NODE_STORE##*/}
+ rm -rf $DEST_STORE_DIR/$SOURCE_STORE_DIR
+
+ # remove the existing log directory
+ DEST_LOG_DIR=$iodevice/$TXN_LOG_DIR_NAME/
+ rm -rf $DEST_LOG_DIR
+
+ # remove the existing asterix metadata directory
+ rm -rf $iodevice/$ASTERIX_ROOT_METADATA_DIR
+
+ if [ $BACKUP_TYPE == "hdfs" ];
+ then
+ # RESTORE FROM HDFS BACKUP
+
+ # copy store directory
+ $HADOOP_HOME/bin/hadoop fs -copyToLocal $HDFS_URL/$NODE_BACKUP_DIR/$SOURCE_STORE_DIR $DEST_STORE_DIR/
+
+ # copy asterix metadata root directory and txn log directory
+ if [ $index -eq 1 ];
+ then
+ $HADOOP_HOME/bin/hadoop fs -copyToLocal $HDFS_URL/$NODE_BACKUP_DIR/$ASTERIX_ROOT_METADATA_DIR $iodevice/
+
+ # copy transaction logs directory
+ $HADOOP_HOME/bin/hadoop fs -copyToLocal $HDFS_URL/$NODE_BACKUP_DIR/$TXN_LOG_DIR_NAME $iodevice/
+ fi
+
+ else
+
+ # RESTORE FROM LOCAL BACKUP
+ # copy store directory
+ cp -r $NODE_BACKUP_DIR/$SOURCE_STORE_DIR $DEST_STORE_DIR/
+
+ # copy asterix metadata root directory and txn log directory
+ if [ $index -eq 1 ];
+ then
+ cp -r $NODE_BACKUP_DIR/$ASTERIX_ROOT_METADATA_DIR $iodevice/
+
+ # copy transaction logs directory
+ cp -r $NODE_BACKUP_DIR/$TXN_LOG_DIR_NAME $iodevice/
+ fi
+
+ fi
+ index=`expr $index + 1`
+done
diff --git a/asterix-events/src/main/resources/schema/cluster.xsd b/asterix-events/src/main/resources/schema/cluster.xsd
new file mode 100644
index 0000000..0e1adce
--- /dev/null
+++ b/asterix-events/src/main/resources/schema/cluster.xsd
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:cl="cluster" targetNamespace="cluster" elementFormDefault="qualified">
+
+<!-- definition of simple types -->
+<xs:element name="name" type="xs:string"/>
+<xs:element name="java_opts" type="xs:string"/>
+<xs:element name="logdir" type="xs:string"/>
+<xs:element name="id" type="xs:string"/>
+<xs:element name="client-ip" type="xs:string"/>
+<xs:element name="cluster-ip" type="xs:string"/>
+<xs:element name="key" type="xs:string"/>
+<xs:element name="value" type="xs:string"/>
+<xs:element name="dir" type="xs:string"/>
+<xs:element name="NFS" type="xs:boolean"/>
+<xs:element name="store" type="xs:string"/>
+<xs:element name="iodevices" type="xs:string"/>
+<xs:element name="java_home" type="xs:string"/>
+<xs:element name="username" type="xs:string"/>
+<xs:element name="debug" type="xs:integer"/>
+<xs:element name="debugEnabled" type="xs:boolean"/>
+
+<!-- definition of complex elements -->
+<xs:element name="workingDir">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="cl:dir"/>
+ <xs:element ref="cl:NFS"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+<xs:element name="master-node">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="cl:id"/>
+ <xs:element ref="cl:client-ip"/>
+ <xs:element ref="cl:cluster-ip"/>
+ <xs:element ref="cl:java_home" minOccurs="0"/>
+ <xs:element ref="cl:java_opts" minOccurs="0"/>
+ <xs:element ref="cl:logdir" minOccurs="0"/>
+ <xs:element ref="cl:debug" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+<xs:element name="property">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="cl:key"/>
+ <xs:element ref="cl:value"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+<xs:element name="env">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="cl:property" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+<xs:element name="node">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="cl:id"/>
+ <xs:element ref="cl:cluster-ip"/>
+ <xs:element ref="cl:java_home" minOccurs="0"/>
+ <xs:element ref="cl:java_opts" minOccurs="0"/>
+ <xs:element ref="cl:logdir" minOccurs="0"/>
+ <xs:element ref="cl:store" minOccurs="0"/>
+ <xs:element ref="cl:iodevices" minOccurs="0"/>
+ <xs:element ref="cl:debug" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+<xs:element name="cluster">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="cl:name"/>
+ <xs:element ref="cl:username"/>
+ <xs:element ref="cl:env" minOccurs="0"/>
+ <xs:element ref="cl:java_home" minOccurs="0"/>
+ <xs:element ref="cl:java_opts" minOccurs="0"/>
+ <xs:element ref="cl:logdir" minOccurs="0"/>
+ <xs:element ref="cl:store" minOccurs="0"/>
+ <xs:element ref="cl:iodevices" minOccurs="0"/>
+ <xs:element ref="cl:workingDir"/>
+ <xs:element ref="cl:debugEnabled" minOccurs="0"/>
+ <xs:element ref="cl:debug" minOccurs="0"/>
+ <xs:element ref="cl:master-node"/>
+ <xs:element ref="cl:node" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+</xs:schema>
diff --git a/asterix-events/src/main/resources/schema/event.xsd b/asterix-events/src/main/resources/schema/event.xsd
new file mode 100644
index 0000000..a233c18
--- /dev/null
+++ b/asterix-events/src/main/resources/schema/event.xsd
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:es="events" targetNamespace="events" elementFormDefault="qualified">
+
+<!-- definition of simple types -->
+<xs:element name="script" type="xs:string"/>
+<xs:element name="type" type="xs:string"/>
+<xs:element name="description" type="xs:string"/>
+<xs:element name="args" type="xs:string"/>
+<xs:element name="daemon" type="xs:boolean"/>
+
+<!-- definition of complex elements -->
+
+<xs:element name="event">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="es:type"/>
+ <xs:element ref="es:script"/>
+ <xs:element ref="es:description"/>
+ <xs:element ref="es:args"/>
+ <xs:element ref="es:daemon"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+<xs:element name="events">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="es:event" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+</xs:schema>
diff --git a/asterix-events/src/main/resources/schema/jaxb-bindings.xjb b/asterix-events/src/main/resources/schema/jaxb-bindings.xjb
new file mode 100644
index 0000000..b5982e0
--- /dev/null
+++ b/asterix-events/src/main/resources/schema/jaxb-bindings.xjb
@@ -0,0 +1,9 @@
+<jxb:bindings version="1.0"
+xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
+xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+<jxb:globalBindings>
+ <jxb:serializable uid="1"/>
+</jxb:globalBindings>
+
+</jxb:bindings>
diff --git a/asterix-events/src/main/resources/schema/pattern.xsd b/asterix-events/src/main/resources/schema/pattern.xsd
new file mode 100644
index 0000000..4eee880
--- /dev/null
+++ b/asterix-events/src/main/resources/schema/pattern.xsd
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:eg="patterns" targetNamespace="patterns">
+
+
+<!-- definition of simple types -->
+<xs:element name="maxOccurs" type = "xs:int"/>
+<xs:element name="pargs" type="xs:string"/>
+<xs:element name="absvalue" type="xs:string"/>
+<xs:element name="unit" type="xs:string"/>
+<xs:element name="type" type="xs:string"/>
+<xs:element name="min" type="xs:string"/>
+<xs:element name="max" type="xs:string"/>
+<xs:element name="abs" type="xs:string"/>
+<xs:element name="set" type="xs:string"/>
+<xs:element name="exclude" type="xs:string"/>
+<xs:element name="reuse" type="xs:boolean"/>
+<!-- definition of attributes -->
+
+<!-- definition of complex elements -->
+
+<xs:element name="range">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="eg:set"/>
+ <xs:element ref="eg:exclude" minOccurs="0"/>
+ <xs:element ref="eg:reuse" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+<xs:element name="minmax">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="eg:min"/>
+ <xs:element ref="eg:max"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+
+<xs:element name="random">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="eg:minmax" minOccurs="0"/>
+ <xs:element ref="eg:range" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+<xs:element name="value">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="eg:random" minOccurs="0"/>
+ <xs:element ref="eg:absvalue" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+<xs:element name="nodeid">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="eg:value"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+<xs:element name="period">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="eg:absvalue"/>
+ <xs:element ref="eg:unit"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+<xs:element name="delay">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="eg:value"/>
+ <xs:element ref="eg:unit"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+<xs:element name="event">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="eg:type"/>
+ <xs:element ref="eg:nodeid"/>
+ <xs:element ref="eg:pargs"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+<xs:element name="pattern">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="eg:delay"/>
+ <xs:element ref="eg:maxOccurs" maxOccurs="1" minOccurs="0"/>
+ <xs:element ref="eg:period"/>
+ <xs:element ref="eg:event"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+<xs:element name="patterns">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="eg:pattern" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+</xs:element>
+
+</xs:schema>
diff --git a/asterix-events/src/main/resources/scripts/execute.sh b/asterix-events/src/main/resources/scripts/execute.sh
new file mode 100755
index 0000000..30f6c2f
--- /dev/null
+++ b/asterix-events/src/main/resources/scripts/execute.sh
@@ -0,0 +1,27 @@
+USERNAME=$1
+if [ ! -d $MANAGIX_HOME/logs ];
+then
+ mkdir -p $MANAGIX_HOME/logs
+fi
+LOGDIR=$MANAGIX_HOME/logs
+if [ $DAEMON == "false" ]; then
+ if [ -z $USERNAME ]
+ then
+ cmd_output=$(ssh $IP_LOCATION "$ENV $SCRIPT $ARGS" 2>&1 >/dev/null)
+ echo "ssh $IP_LOCATION $ENV $SCRIPT $ARGS" >> $LOGDIR/execute.log
+ echo "$cmd_output"
+ else
+ echo "ssh -l $USERNAME $IP_LOCATION $ENV $SCRIPT $ARGS" >> $LOGDIR/execute.log
+ cmd_output=$(ssh -l $USERNAME $IP_LOCATION "$ENV $SCRIPT $ARGS" 2>&1 >/dev/null)
+ echo "$cmd_output"
+ fi
+else
+ if [ -z $USERNAME ];
+ then
+ echo "ssh $IP_LOCATION $ENV $SCRIPT $ARGS &" >> $LOGDIR/execute.log
+ ssh $IP_LOCATION "$ENV $SCRIPT $ARGS" &
+ else
+ echo "ssh -l $USERNAME $IP_LOCATION $ENV $SCRIPT $ARGS &" >> $LOGDIR/execute.log
+ ssh -l $USERNAME $IP_LOCATION "$ENV $SCRIPT $ARGS" &
+ fi
+fi
diff --git a/asterix-events/src/main/resources/scripts/prepare.sh b/asterix-events/src/main/resources/scripts/prepare.sh
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/asterix-events/src/main/resources/scripts/prepare.sh