<%
  /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
  * distributed with this work for additional information
  * regarding copyright ownership. The ASF licenses this file
  * to you 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.
  */
%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ page import="java.util.*" %>
<%@ page import="org.apache.tajo.webapp.StaticHttpServer" %>
<%@ page import="org.apache.tajo.worker.*" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="org.apache.tajo.master.querymaster.QueryMasterTask" %>
<%@ page import="org.apache.tajo.master.querymaster.Query" %>

<%
  TajoWorker tajoWorker = (TajoWorker) StaticHttpServer.getInstance().getAttribute("tajo.info.server.object");

  List<QueryMasterTask> queryMasterTasks = JSPUtil.sortQueryMasterTask(tajoWorker.getWorkerContext()
          .getTajoWorkerManagerService().getQueryMaster().getQueryMasterTasks(), true);

  List<QueryMasterTask> finishedQueryMasterTasks = JSPUtil.sortQueryMasterTask(tajoWorker.getWorkerContext()
          .getTajoWorkerManagerService().getQueryMaster().getFinishedQueryMasterTasks(), true);

  List<TaskRunner> taskRunners = new ArrayList<TaskRunner>(tajoWorker.getWorkerContext().getTaskRunnerManager().getTaskRunners());

  JSPUtil.sortTaskRunner(taskRunners);

  SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
  <link rel="stylesheet" type = "text/css" href = "/static/style.css" />
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>tajo worker</title>
</head>
<body>
<%@ include file="header.jsp"%>
<div class='contents'>
  <h2>Tajo Worker: <%=tajoWorker.getWorkerContext().getWorkerName()%></h2>
  <hr/>
  <table border=0>
    <tr><td width='100'>MaxHeap: </td><td><%=Runtime.getRuntime().maxMemory()/1024/1024%> MB</td>
    <tr><td width='100'>TotalHeap: </td><td><%=Runtime.getRuntime().totalMemory()/1024/1024%> MB</td>
    <tr><td width='100'>FreeHeap: </td><td><%=Runtime.getRuntime().freeMemory()/1024/1024%> MB</td>
    <tr><td width="100">Configuration:</td><td><a href='conf.jsp'>detail...</a></td></tr>
    <tr><td width="100">Environment:</td><td><a href='env.jsp'>detail...</a></td></tr>
    <tr><td width="100">Threads:</td><td><a href='thread.jsp'>thread dump...</a></tr>
  </table>
  <hr/>

  <h3>Running QueryMaster</h3>
<%
  if(queryMasterTasks.isEmpty()) {
    out.write("No running query master");
  } else {
%>
  <table width="100%" border="1" class="border_table">
    <tr><th>QueryId</th><th>StartTime</th><th>FinishTime</th><th>Progress</th><th>RunTime</th></tr>
<%
    for(QueryMasterTask eachQueryMasterTask: queryMasterTasks) {
      Query query = eachQueryMasterTask.getQuery();
%>
    <tr>
      <td align='center'><a href='querydetail.jsp?queryId=<%=query.getId()%>'><%=query.getId()%></a></td>
      <td align='center'><%=df.format(query.getStartTime())%></td>
      <td align='center'><%=query.getFinishTime() == 0 ? "-" : df.format(query.getFinishTime())%></td>
      <td align='center'><%=(int)(query.getProgress()*100.0f)%>%</td>
      <td align='right'><%=JSPUtil.getElapsedTime(query.getStartTime(), query.getFinishTime())%></td>
    </tr>
<%
    } //end of for
  } //end of if
%>
  </table>
  <p/>
  <hr/>
  <h3>Finished QueryMaster</h3>
  <%
    if(finishedQueryMasterTasks.isEmpty()) {
      out.write("No finished query master");
    } else {
  %>
  <table width="100%" border="1" class="border_table">
    <tr><th>QueryId</th><th>StartTime</th><th>FinishTime</th><th>Progress</th><th>RunTime</th></tr>
<%
    for(QueryMasterTask eachQueryMasterTask: finishedQueryMasterTasks) {
      Query query = eachQueryMasterTask.getQuery();
%>
    <tr>
      <td align='center'><a href='querydetail.jsp?queryId=<%=query.getId()%>'><%=query.getId()%></a></td>
      <td align='center'><%=df.format(query.getStartTime())%></td>
      <td align='center'><%=query.getFinishTime() == 0 ? "-" : df.format(query.getFinishTime())%></td>
      <td align='center'><%=(int)(query.getProgress()*100.0f)%>%</td>
      <td align='right'><%=JSPUtil.getElapsedTime(query.getStartTime(), query.getFinishTime())%></td>
    </tr>
<%
    } //end of for
  } //end of if
%>
  </table>
  <p/>
  <hr/>
  <h3>Running Tasks</h3>
  <a href='tasks.jsp'>[All Tasks]</a>
  <table width="100%" border="1" class="border_table">
    <tr><th>TaskId</th><th>StartTime</th><th>FinishTime</th><th>RunTime</th><th>Status</th></tr>
    <%
      for(TaskRunner eachTaskRunner: taskRunners) {
    %>
    <tr>
      <td><%=eachTaskRunner.getId()%></td>
      <td><%=df.format(eachTaskRunner.getStartTime())%></td>
      <td><%=eachTaskRunner.getFinishTime() == 0 ? "-" : df.format(eachTaskRunner.getFinishTime())%></td>
      <td><%=JSPUtil.getElapsedTime(eachTaskRunner.getStartTime(), eachTaskRunner.getFinishTime())%></td>
      <td><%=eachTaskRunner.getServiceState()%></td>
        <%
  }
%>
  </table>
</div>
</body>
</html>