/* * Copyright 2009 Mustard Grain, Inc., 2009-2010 LinkedIn, Inc. * * 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 voldemort.cluster.failuredetector; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.StringUtils; import voldemort.annotations.jmx.JmxGetter; import voldemort.annotations.jmx.JmxManaged; import voldemort.client.ClientConfig; import voldemort.cluster.Node; import voldemort.server.VoldemortConfig; import voldemort.store.UnreachableStoreException; /** * BannagePeriodFailureDetector relies on external callers to notify it of * failed attempts to access a node's store via recordException. When * recordException is invoked, the node is marked offline for a period of time * as defined by the client or server configuration. Once that period has * passed, the node is considered <em>available</em>. However, * BannagePeriodFailureDetector's definition of available uses a fairly loose * sense of the word. Rather than considering the node to be available for * access, it is available for <i>attempting</i> to access. In actuality the * node may still be down. However, the intent is simply to mark it down for N * seconds and then attempt to try again and repeat. If the node is truly * available for access, the caller will then invoke recordSuccess and the node * will be marked available in the truest sense of the word. * * * @see VoldemortConfig#getFailureDetectorBannagePeriod * @see ClientConfig#getFailureDetectorBannagePeriod * @see FailureDetectorConfig#getBannagePeriod */ @JmxManaged(description = "Detects the availability of the nodes on which a Voldemort cluster runs") @Deprecated public class BannagePeriodFailureDetector extends AbstractFailureDetector { public BannagePeriodFailureDetector(FailureDetectorConfig failureDetectorConfig) { super(failureDetectorConfig); } public boolean isAvailable(Node node) { checkNodeArg(node); long bannagePeriod = failureDetectorConfig.getBannagePeriod(); long currentTime = failureDetectorConfig.getTime().getMilliseconds(); NodeStatus nodeStatus = getNodeStatus(node); synchronized(nodeStatus) { // The node can be available in one of two ways: a) it's actually // available, or... if(nodeStatus.isAvailable()) return true; // ...b) it was unavailable but our "bannage" period has expired so // we're free to consider it as available. If we're now considered // available but our actual status is *not* available, this means // we've become available via a timeout. We act like we're fully // available in that we send out the availability event. if(nodeStatus.getLastChecked() + bannagePeriod < currentTime) { setAvailable(node); return true; } else { return false; } } } public void recordException(Node node, long requestTime, UnreachableStoreException e) { checkArgs(node, requestTime); setUnavailable(node, e); } public void recordSuccess(Node node, long requestTime) { checkArgs(node, requestTime); setAvailable(node); } @JmxGetter(name = "unavailableNodesBannageExpiration", description = "List of unavailable nodes and their respective bannage expiration") public String getUnavailableNodesBannageExpiration() { List<String> list = new ArrayList<String>(); long bannagePeriod = failureDetectorConfig.getBannagePeriod(); long currentTime = failureDetectorConfig.getTime().getMilliseconds(); for(Node node: getConfig().getCluster().getNodes()) { if(!isAvailable(node)) { NodeStatus nodeStatus = getNodeStatus(node); long millis = 0; synchronized(nodeStatus) { millis = (nodeStatus.getLastChecked() + bannagePeriod) - currentTime; } list.add(node.getId() + "=" + millis); } } return StringUtils.join(list, ","); } }