/* * Copyright 2009 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.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import voldemort.cluster.Node; import voldemort.utils.Time; import com.google.common.collect.Iterables; public class TimedUnavailabilityTest extends FailureDetectorPerformanceTest { private final long unavailabilityMillis; private TimedUnavailabilityTest(String[] args, long unavailabilityMillis) { super(args); this.unavailabilityMillis = unavailabilityMillis; } public static void main(String[] args) throws Throwable { FailureDetectorPerformanceTest test = new TimedUnavailabilityTest(args, 2522); test.test(); } @Override protected String getTestHeaders() { return "FailureDetector Type, Delta"; } @Override public String test(FailureDetector failureDetector) throws Exception { Node node = Iterables.get(failureDetectorConfig.getCluster().getNodes(), 0); CountDownLatch countDownLatch = new CountDownLatch(1); Listener listener = new Listener(failureDetectorConfig.getTime()); failureDetector.addFailureDetectorListener(listener); ExecutorService threadPool = Executors.newFixedThreadPool(11); for(int i = 0; i < 10; i++) threadPool.submit(new NodeAccessorRunnable(failureDetector, node, countDownLatch, null, null, null, 0, 10)); threadPool.submit(new TimedUnavailability(failureDetector, node, countDownLatch)); threadPool.shutdown(); // If we get stuck, we should give the user the opportunity to get a // thread dump. if(!threadPool.awaitTermination(60, TimeUnit.SECONDS)) { System.out.println("Threads appear to be stuck"); threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); } return Class.forName(failureDetectorConfig.getImplementationClassName()).getSimpleName() + ", " + listener.getDelta(); } private class TimedUnavailability implements Runnable { private final FailureDetector failureDetector; private final Node node; private final CountDownLatch countDownLatch; public TimedUnavailability(FailureDetector failureDetector, Node node, CountDownLatch countDownLatch) { this.failureDetector = failureDetector; this.node = node; this.countDownLatch = countDownLatch; } public void run() { FailureDetectorConfig failureDetectorConfig = failureDetector.getConfig(); try { updateNodeStoreAvailability(failureDetectorConfig, node, false); failureDetectorConfig.getTime().sleep(unavailabilityMillis); updateNodeStoreAvailability(failureDetectorConfig, node, true); failureDetector.waitForAvailability(node); countDownLatch.countDown(); } catch(Exception e) { e.printStackTrace(); } } } private static class Listener implements FailureDetectorListener { private final Time time; private long markedAvailable; private long markedUnavailable; public Listener(Time time) { this.time = time; } public void nodeAvailable(Node node) { markedAvailable = time.getMilliseconds(); } public void nodeUnavailable(Node node) { markedUnavailable = time.getMilliseconds(); } public long getDelta() { return markedAvailable - markedUnavailable; } } }