Added job logging. Added config for CC root folder. Removed logging.properties file.

git-svn-id: https://hyracks.googlecode.com/svn/branches/hyracks_dev_next@755 123451ca-8445-de46-9d55-352943316053
diff --git a/config/logging.properties b/config/logging.properties
deleted file mode 100644
index b637f7a..0000000
--- a/config/logging.properties
+++ /dev/null
@@ -1,42 +0,0 @@
-# "handlers" specifies a comma separated list of log Handler 
-# classes.  These handlers will be installed during VM startup.
-# Note that these classes must be on the system classpath.
-# By default we only configure a ConsoleHandler, which will only
-# show messages at the INFO and above levels.
-handlers= java.util.logging.ConsoleHandler
-
-# To also add the FileHandler, use the following line instead.
-#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
-
-# Default global logging level.
-# This specifies which kinds of events are logged across
-# all loggers.  For any given facility this global level
-# can be overriden by a facility specific level
-# Note that the ConsoleHandler also has a separate level
-# setting to limit messages printed to the console.
-.level= WARNING
-
-############################################################
-# Handler specific properties.
-# Describes specific configuration info for Handlers.
-############################################################
-
-# default file output is in user's home directory.
-java.util.logging.FileHandler.pattern = %h/java%u.log
-java.util.logging.FileHandler.limit = 50000
-java.util.logging.FileHandler.count = 1
-java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
-
-# Limit the message that are printed on the console to INFO and above.
-java.util.logging.ConsoleHandler.level = INFO
-java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
-
-
-############################################################
-# Facility specific properties.
-# Provides extra control for each logger.
-############################################################
-
-# For example, set the com.xyz.foo logger to only log SEVERE
-# messages:
-com.xyz.foo.level = SEVERE
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/ClusterControllerService.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/ClusterControllerService.java
index 7589509..bf66b74 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/ClusterControllerService.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/ClusterControllerService.java
@@ -70,6 +70,7 @@
 import edu.uci.ics.hyracks.control.common.job.PartitionRequest;
 import edu.uci.ics.hyracks.control.common.job.profiling.om.JobProfile;
 import edu.uci.ics.hyracks.control.common.job.profiling.om.TaskProfile;
+import edu.uci.ics.hyracks.control.common.logs.LogFile;
 import edu.uci.ics.hyracks.control.common.work.FutureValue;
 import edu.uci.ics.hyracks.control.common.work.WorkQueue;
 
@@ -77,10 +78,12 @@
         IHyracksClientInterface {
     private static final long serialVersionUID = 1L;
 
-    private CCConfig ccConfig;
+    private final CCConfig ccConfig;
 
     private static Logger LOGGER = Logger.getLogger(ClusterControllerService.class.getName());
 
+    private final LogFile jobLog;
+
     private final Map<String, NodeControllerState> nodeRegistry;
 
     private final Map<String, Set<String>> ipAddressNodeNameMap;
@@ -113,11 +116,12 @@
 
     public ClusterControllerService(final CCConfig ccConfig) throws Exception {
         this.ccConfig = ccConfig;
+        File jobLogFolder = new File(ccConfig.ccRoot, "logs/jobs");
+        jobLog = new LogFile(jobLogFolder);
         nodeRegistry = new LinkedHashMap<String, NodeControllerState>();
         ipAddressNodeNameMap = new HashMap<String, Set<String>>();
         applications = new Hashtable<String, CCApplicationContext>();
-        serverCtx = new ServerContext(ServerContext.ServerType.CLUSTER_CONTROLLER, new File(
-                ClusterControllerService.class.getName()));
+        serverCtx = new ServerContext(ServerContext.ServerType.CLUSTER_CONTROLLER, new File(ccConfig.ccRoot));
         taskExecutor = Executors.newCachedThreadPool();
         webServer = new WebServer(this);
         activeRunMap = new HashMap<JobId, JobRun>();
@@ -144,6 +148,7 @@
     @Override
     public void start() throws Exception {
         LOGGER.log(Level.INFO, "Starting ClusterControllerService");
+        jobLog.open();
         Registry registry = LocateRegistry.createRegistry(ccConfig.port);
         registry.rebind(IHyracksClientInterface.class.getName(), ccci);
         registry.rebind(IClusterController.class.getName(), this);
@@ -162,6 +167,7 @@
         webServer.stop();
         sweeper.cancel();
         workQueue.stop();
+        jobLog.close();
         LOGGER.log(Level.INFO, "Stopped ClusterControllerService");
     }
 
@@ -177,6 +183,10 @@
         return runMapArchive;
     }
 
+    public LogFile getJobLogFile() {
+        return jobLog;
+    }
+
     public WorkQueue getWorkQueue() {
         return workQueue;
     }
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/JobRun.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/JobRun.java
index 3b3a777..38ee720 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/JobRun.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/JobRun.java
@@ -334,6 +334,8 @@
         }
         result.put("activity-clusters", aClusters);
 
+        result.put("profile", profile.toJSON());
+
         return result;
     }
 }
\ No newline at end of file
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/work/JobCleanupWork.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/work/JobCleanupWork.java
index 20ffc55..d792aa6 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/work/JobCleanupWork.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/work/JobCleanupWork.java
@@ -16,7 +16,11 @@
 
 import java.util.Set;
 
+import org.json.JSONException;
+import org.json.JSONObject;
+
 import edu.uci.ics.hyracks.api.exceptions.HyracksException;
+import edu.uci.ics.hyracks.api.job.JobActivityGraph;
 import edu.uci.ics.hyracks.api.job.JobId;
 import edu.uci.ics.hyracks.api.job.JobStatus;
 import edu.uci.ics.hyracks.control.cc.ClusterControllerService;
@@ -78,6 +82,24 @@
                         run.setStatus(status, exception);
                         ccs.getActiveRunMap().remove(jobId);
                         ccs.getRunMapArchive().put(jobId, run);
+                        try {
+                            ccs.getJobLogFile().log(createJobLogObject(run));
+                        } catch (Exception e) {
+                            throw new RuntimeException(e);
+                        }
+                    }
+
+                    private JSONObject createJobLogObject(final JobRun run) {
+                        JSONObject jobLogObject = new JSONObject();
+                        try {
+                            JobActivityGraph jag = run.getJobActivityGraph();
+                            jobLogObject.put("job-specification", jag.getJobSpecification().toJSON());
+                            jobLogObject.put("job-activity-graph", jag.toJSON());
+                            jobLogObject.put("job-run", run.toJSON());
+                        } catch (JSONException e) {
+                            throw new RuntimeException(e);
+                        }
+                        return jobLogObject;
                     }
                 });
             }
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/work/TaskCompleteWork.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/work/TaskCompleteWork.java
index c0af50b..2838ed4 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/work/TaskCompleteWork.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/work/TaskCompleteWork.java
@@ -14,6 +14,8 @@
  */
 package edu.uci.ics.hyracks.control.cc.work;
 
+import java.util.Map;
+
 import edu.uci.ics.hyracks.api.dataflow.TaskAttemptId;
 import edu.uci.ics.hyracks.api.exceptions.HyracksException;
 import edu.uci.ics.hyracks.api.job.JobId;
@@ -41,10 +43,13 @@
             JobRun run = ac.getJobRun();
             if (statistics != null) {
                 JobProfile jobProfile = run.getJobProfile();
-                JobletProfile jobletProfile = jobProfile.getJobletProfiles().get(nodeId);
-                if (jobletProfile != null) {
-                    jobletProfile.getTaskProfiles().put(taId, statistics);
+                Map<String, JobletProfile> jobletProfiles = jobProfile.getJobletProfiles();
+                JobletProfile jobletProfile = jobletProfiles.get(nodeId);
+                if (jobletProfile == null) {
+                    jobletProfile = new JobletProfile(nodeId);
+                    jobletProfiles.put(nodeId, jobletProfile);
                 }
+                jobletProfile.getTaskProfiles().put(taId, statistics);
             }
             ac.getJobRun().getScheduler().notifyTaskComplete(ta);
         } catch (HyracksException e) {
diff --git a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/controllers/CCConfig.java b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/controllers/CCConfig.java
index 916ef77..5091d12 100644
--- a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/controllers/CCConfig.java
+++ b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/controllers/CCConfig.java
@@ -40,6 +40,9 @@
     @Option(name = "-job-history-size", usage = "Limits the number of historical jobs remembered by the system to the specified value. (default: 10)")
     public int jobHistorySize = 10;
 
+    @Option(name = "-cc-root", usage = "Sets the root folder used for file operations. (default: ClusterControllerService)")
+    public String ccRoot = "ClusterControllerService";
+
     public void toCommandLine(List<String> cList) {
         cList.add("-port");
         cList.add(String.valueOf(port));
@@ -55,5 +58,7 @@
         cList.add(String.valueOf(defaultMaxJobAttempts));
         cList.add("-job-history-size");
         cList.add(String.valueOf(jobHistorySize));
+        cList.add("-cc-root");
+        cList.add(ccRoot);
     }
 }
\ No newline at end of file
diff --git a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/logs/LogFile.java b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/logs/LogFile.java
new file mode 100644
index 0000000..1521aa0
--- /dev/null
+++ b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/logs/LogFile.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2009-2010 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.hyracks.control.common.logs;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+
+import org.json.JSONObject;
+
+public class LogFile {
+    private final File root;
+
+    private PrintWriter out;
+
+    public LogFile(File root) {
+        this.root = root;
+    }
+
+    public void open() throws Exception {
+        root.mkdirs();
+        out = new PrintWriter(new FileOutputStream(new File(root, String.valueOf(System.currentTimeMillis()) + ".log"),
+                true));
+    }
+
+    public void log(JSONObject object) throws Exception {
+        out.println(object.toString(1));
+        out.flush();
+    }
+
+    public void close() {
+        out.flush();
+        out.close();
+    }
+}
\ No newline at end of file
diff --git a/hyracks-examples/hyracks-integration-tests/src/test/java/edu/uci/ics/hyracks/tests/integration/AbstractIntegrationTest.java b/hyracks-examples/hyracks-integration-tests/src/test/java/edu/uci/ics/hyracks/tests/integration/AbstractIntegrationTest.java
index 71c781d..9acb46a 100644
--- a/hyracks-examples/hyracks-integration-tests/src/test/java/edu/uci/ics/hyracks/tests/integration/AbstractIntegrationTest.java
+++ b/hyracks-examples/hyracks-integration-tests/src/test/java/edu/uci/ics/hyracks/tests/integration/AbstractIntegrationTest.java
@@ -54,6 +54,12 @@
         CCConfig ccConfig = new CCConfig();
         ccConfig.port = 39001;
         ccConfig.profileDumpPeriod = 10000;
+        File outDir = new File("target/ClusterController");
+        outDir.mkdirs();
+        File ccRoot = File.createTempFile(AbstractIntegrationTest.class.getName(), ".data", outDir);
+        ccRoot.delete();
+        ccRoot.mkdir();
+        ccConfig.ccRoot = ccRoot.getAbsolutePath();
         cc = new ClusterControllerService(ccConfig);
         cc.start();
 
@@ -75,6 +81,9 @@
 
         hcc = new HyracksLocalConnection(cc);
         hcc.createApplication("test", null);
+        if (LOGGER.isLoggable(Level.INFO)) {
+            LOGGER.info("Starting CC in " + ccRoot.getAbsolutePath());
+        }
     }
 
     @AfterClass
@@ -95,7 +104,7 @@
         }
         cc.waitForCompletion(jobId);
     }
-    
+
     protected File createTempFile() throws IOException {
         return File.createTempFile(getClass().getName(), ".tmp", outputFolder.getRoot());
     }
diff --git a/pom.xml b/pom.xml
index 0320e7d..d190af3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,7 +25,7 @@
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
             <forkMode>pertest</forkMode>
-            <argLine>-enableassertions -Djava.util.logging.config.file=${basedir}/config/logging.properties</argLine>
+            <argLine>-enableassertions -Djava.util.logging.config.file=${user.home}/logging.properties</argLine>
         </configuration>
       </plugin>
     </plugins>