/*************************************************************************** * Copyright (c) 2013 VMware, Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ***************************************************************************/ /*************************************************************************** * Copyright (c) 2012 VMware, Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ***************************************************************************/ package com.vmware.vhadoop.util; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import com.vmware.vhadoop.util.CompoundStatus.TaskStatus.TaskState; import com.vmware.vhadoop.vhm.EmbeddedVHM; /** * CompoundStatus is a class used to allow a method to register successes or failures in its operation * and then return the status to the caller which can then combine it with its own status. * In this way, an audit trail of statuses can be build up over a call stack and can then finally be * analyzed by the initial caller which decides what to do about the results * Note that the caller should not assume that every successful method in the stack above will * necessarily have called registerTaskSuccess(). This is why the final focus is on how many failures there were. * Each CompoundStatus has a name and each TaskStatus created within it gets tagged with that name * Hence when compoundStatus objects are combined with each other, it is clear which operation registered what. * "Fatal" here means that the entire operation should be subsequently aborted - there is no point continuing * * @author bcorrie * */ public class CompoundStatus { private static final ProgressLogger _pLog = ProgressLogger.getProgressLogger(EmbeddedVHM.class.getName()); private static final Logger _log = _pLog.getLogger(); public List<TaskStatus> _taskStatusList; /* TODO: Order by timestamp for audit */ public String _name; public static class TaskStatus { public enum TaskState{SUCCEEDED, INCOMPLETE, FAILED}; private String _compoundName; private final long _timeOccurred = System.currentTimeMillis(); private TaskState _taskState; private boolean _isFatal; private String _message; public TaskStatus(TaskState state, boolean isFatal, String message, String compoundName) { _taskState = state; _isFatal = isFatal; _message = message; _compoundName = compoundName; } public TaskState getTaskState() { return _taskState; } public boolean getIsFatal() { return _isFatal; } public String getMessage() { return _message; } public long getTimeOccurred() { return _timeOccurred; } public String getCompoundName() { return _compoundName; } } /* Create a new compound status. The name is typically the class/method name that created the status */ public CompoundStatus(String name) { _taskStatusList = new ArrayList<TaskStatus>(); _name = name; } /* Incorporate the input status into this status */ public void addStatus(CompoundStatus statusToAdd) { _taskStatusList.addAll(statusToAdd._taskStatusList); } /* If a task succeeds, provide a record of this */ public void registerTaskSucceeded() { _taskStatusList.add(new TaskStatus(TaskState.SUCCEEDED, false, null, _name)); } /* If a task fails, record the failure. It could be fatal or not */ public void registerTaskFailed(boolean isFatal, String errorMsg) { _taskStatusList.add(new TaskStatus(TaskState.FAILED, false, errorMsg, _name)); } /* If a task doesn't complete, this could be indication for a retry */ public void registerTaskIncomplete(boolean isFatal, String errorMsg) { _taskStatusList.add(new TaskStatus(TaskState.INCOMPLETE, false, errorMsg, _name)); } public int getTotalTaskCount() { return _taskStatusList.size(); } public int getFailedTaskCount() { int result = 0; for (TaskStatus status : _taskStatusList) { if (status.getTaskState().equals(TaskState.FAILED)) { result++; } } return result; } public int getIncompleteTaskCount() { int result = 0; for (TaskStatus status : _taskStatusList) { if (status.getTaskState().equals(TaskState.INCOMPLETE)) { result++; } } return result; } public int getFatalFailureCount() { int result = 0; for (TaskStatus status : _taskStatusList) { if (status.getIsFatal()) { result++; } } return result; } /* Utility method to look through the array of CompoundStatuses and find the failure with the earliest timestamp */ public static TaskStatus getFirstFailure(CompoundStatus[] statuses) { TaskStatus result = null; for (CompoundStatus compStatus : statuses) { if (compStatus == null) { continue; } for (TaskStatus taskStatus : compStatus._taskStatusList) { if (!taskStatus._taskState.equals(TaskState.SUCCEEDED) && (taskStatus._message != null)) { if (result == null) { result = taskStatus; } else if (taskStatus._timeOccurred < result._timeOccurred) { result = taskStatus; } } _log.log(Level.INFO, "TaskStatus: " + taskStatus.getCompoundName() + " " + taskStatus.getMessage() + " " + taskStatus.getTaskState()); } } return result; } /* Utility method to check if all the poweron/off operations succeeded */ public static boolean allPowerOpsSucceeded(CompoundStatus edpStatus) { boolean powerTestExists = false; if (edpStatus == null) { return false; } for (TaskStatus taskStatus : edpStatus._taskStatusList) { if (taskStatus.getCompoundName().equals("testForPowerState")) { powerTestExists = true; if ((!taskStatus._taskState.equals(TaskState.SUCCEEDED))) { return false; } } } return powerTestExists; } }