/** * 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. */ package org.apache.hadoop.hive.ql; import com.google.common.collect.ImmutableMap; import org.apache.hadoop.hive.ql.exec.Task; import org.apache.hadoop.hive.ql.exec.TaskResult; import org.apache.hadoop.hive.ql.plan.api.StageType; import java.io.Serializable; import java.util.*; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonWriteNullProperties; import org.codehaus.jackson.annotate.JsonIgnore; /** * Some limited query information to save for WebUI. * * The class is synchronized, as WebUI may access information about a running query. */ public class QueryDisplay { // Member variables private String queryStr; private String explainPlan; private String errorMessage; private String queryId; private final Map<Phase, Map<String, Long>> hmsTimingMap = new HashMap<Phase, Map<String, Long>>(); private final Map<Phase, Map<String, Long>> perfLogStartMap = new HashMap<Phase, Map<String, Long>>(); private final Map<Phase, Map<String, Long>> perfLogEndMap = new HashMap<Phase, Map<String, Long>>(); private final LinkedHashMap<String, TaskDisplay> tasks = new LinkedHashMap<String, TaskDisplay>(); public synchronized <T extends Serializable> void updateTaskStatus(Task<T> tTask) { if (!tasks.containsKey(tTask.getId())) { tasks.put(tTask.getId(), new TaskDisplay(tTask)); } tasks.get(tTask.getId()).updateStatus(tTask); } //Inner classes public enum Phase { COMPILATION, EXECUTION, } @JsonWriteNullProperties(false) @JsonIgnoreProperties(ignoreUnknown = true) public static class TaskDisplay { private Integer returnValue; //if set, determines that task is complete. private String errorMsg; private Long beginTime; private Long endTime; private String taskId; private String externalHandle; public Task.TaskState taskState; private StageType taskType; private String name; private boolean requireLock; private boolean retryIfFail; private String statusMessage; // required for jackson public TaskDisplay() { } public TaskDisplay(Task task) { taskId = task.getId(); externalHandle = task.getExternalHandle(); taskType = task.getType(); name = task.getName(); requireLock = task.requireLock(); retryIfFail = task.ifRetryCmdWhenFail(); } @JsonIgnore public synchronized String getStatus() { if (returnValue == null) { return "Running"; } else if (returnValue == 0) { return "Success, ReturnVal 0"; } else { return "Failure, ReturnVal " + String.valueOf(returnValue); } } public synchronized Long getElapsedTime() { if (endTime == null) { if (beginTime == null) { return null; } return System.currentTimeMillis() - beginTime; } else { return endTime - beginTime; } } public synchronized Integer getReturnValue() { return returnValue; } public synchronized String getErrorMsg() { return errorMsg; } public synchronized Long getBeginTime() { return beginTime; } public synchronized Long getEndTime() { return endTime; } public synchronized String getTaskId() { return taskId; } public synchronized StageType getTaskType() { return taskType; } public synchronized String getName() { return name; } @JsonIgnore public synchronized boolean isRequireLock() { return requireLock; } @JsonIgnore public synchronized boolean isRetryIfFail() { return retryIfFail; } public synchronized String getExternalHandle() { return externalHandle; } public synchronized <T extends Serializable> void updateStatus(Task<T> tTask) { this.taskState = tTask.getTaskState(); if (externalHandle == null && tTask.getExternalHandle() != null) { this.externalHandle = tTask.getExternalHandle(); } setStatusMessage(tTask.getStatusMessage()); switch (taskState) { case RUNNING: if (beginTime == null) { beginTime = System.currentTimeMillis(); } break; case FINISHED: if (endTime == null) { endTime = System.currentTimeMillis(); } break; } } public synchronized String getStatusMessage() { return statusMessage; } public synchronized void setStatusMessage(String statusMessage) { this.statusMessage = statusMessage; } } public synchronized void setTaskResult(String taskId, TaskResult result) { TaskDisplay taskDisplay = tasks.get(taskId); if (taskDisplay != null) { taskDisplay.returnValue = result.getExitVal(); if (result.getTaskError() != null) { taskDisplay.errorMsg = result.getTaskError().toString(); } } } public synchronized List<TaskDisplay> getTaskDisplays() { List<TaskDisplay> taskDisplays = new ArrayList<TaskDisplay>(); taskDisplays.addAll(tasks.values()); return taskDisplays; } public synchronized void setQueryStr(String queryStr) { this.queryStr = queryStr; } public synchronized String getQueryString() { return returnStringOrUnknown(queryStr); } public synchronized String getExplainPlan() { return returnStringOrUnknown(explainPlan); } public synchronized void setExplainPlan(String explainPlan) { this.explainPlan = explainPlan; } /** * @param phase phase of query * @return map of HMS Client method-calls and duration in miliseconds, during given phase. */ public synchronized Map<String, Long> getHmsTimings(Phase phase) { return hmsTimingMap.get(phase); } /** * @param phase phase of query * @param hmsTimings map of HMS Client method-calls and duration in miliseconds, during given phase. */ public synchronized void setHmsTimings(Phase phase, ImmutableMap<String, Long> hmsTimings) { hmsTimingMap.put(phase, hmsTimings); } /** * @param phase phase of query * @return map of PerfLogger call-trace name and start time in miliseconds, during given phase. */ public synchronized Map<String, Long> getPerfLogStarts(Phase phase) { return perfLogStartMap.get(phase); } /** * @param phase phase of query * @param perfLogStarts map of PerfLogger call-trace name and start time in miliseconds, during given phase. */ public synchronized void setPerfLogStarts(Phase phase, ImmutableMap<String, Long> perfLogStarts) { perfLogStartMap.put(phase, perfLogStarts); } /** * @param phase phase of query * @return map of PerfLogger call-trace name and end time in miliseconds, during given phase. */ public synchronized Map<String, Long> getPerfLogEnds(Phase phase) { return perfLogEndMap.get(phase); } /** * @param phase phase of query * @param perfLogEnds map of PerfLogger call-trace name and end time in miliseconds, during given phase. */ public synchronized void setPerfLogEnds(Phase phase, ImmutableMap<String, Long> perfLogEnds) { perfLogEndMap.put(phase, perfLogEnds); } /** * @param phase phase of query * @return map of PerfLogger call-trace name and duration in miliseconds, during given phase. */ public synchronized Map<String, Long> getPerfLogTimes(Phase phase) { Map<String, Long> times = new HashMap<>(); Map<String, Long> startTimes = perfLogStartMap.get(phase); Map<String, Long> endTimes = perfLogEndMap.get(phase); if (endTimes != null && startTimes != null) { for (String timeKey : endTimes.keySet()) { Long endTime = endTimes.get(timeKey); Long startTime = startTimes.get(timeKey); if (startTime != null) { times.put(timeKey, endTime - startTime); } } } return times; } public synchronized String getErrorMessage() { return errorMessage; } public synchronized void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; } public synchronized String getQueryId() { return returnStringOrUnknown(queryId); } public synchronized void setQueryId(String queryId) { this.queryId = queryId; } private String returnStringOrUnknown(String s) { return s == null ? "UNKNOWN" : s; } }