/** * 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.hdfs.notifier.server; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Queue; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import junit.framework.Assert; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hdfs.MiniDFSCluster; import org.apache.hadoop.hdfs.notifier.InvalidServerIdException; import org.apache.hadoop.hdfs.notifier.NamespaceNotification; import org.apache.thrift.TException; import org.junit.BeforeClass; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TestServerClientTracker { static private Logger LOG = LoggerFactory.getLogger(TestServerClientTracker.class); static Configuration conf; @BeforeClass public static void initConf() { conf = NotifierTestUtil.initGenericConf(); } @Test public void testClientTimeoutBasic1() throws Exception { DummyServerCore core = new DummyServerCore(); ServerDispatcher clientTracker = new ServerDispatcher(core); DummyClientHandler clientHandler = new DummyClientHandler(); long clientId = 1000; core.init(clientTracker); // Make the client fail so it doesen't respond to heartbeats clientHandler.failingClient = true; core.clients.put(clientId, new ClientData(clientId, clientHandler, "host", 3000)); core.clientLocks.put(clientId, new ReentrantLock()); clientTracker.setClientTimeout(100); clientTracker.setHeartbeatTimeout(1000); clientTracker.loopSleepTime = 10; clientTracker.assignClient(clientId); new Thread(clientTracker).start(); Thread.sleep(200); core.shutdown(); Assert.assertFalse(core.removedClients.contains(clientId)); } @Test public void testClientTimeoutBasic2() throws Exception { DummyServerCore core = new DummyServerCore(); ServerDispatcher clientTracker = new ServerDispatcher(core); DummyClientHandler clientHandler = new DummyClientHandler(); long clientId = 1000; core.init(clientTracker); // Make the client fail so it doesen't respond to heartbeats clientHandler.failingClient = true; core.clients.put(clientId, new ClientData(clientId, clientHandler, "host", 3000)); core.clientLocks.put(clientId, new ReentrantLock()); clientTracker.setClientTimeout(100); clientTracker.setHeartbeatTimeout(1000); clientTracker.loopSleepTime = 10; clientTracker.assignClient(clientId); clientTracker.handleFailedDispatch(clientId, System.currentTimeMillis()); new Thread(clientTracker).start(); Thread.sleep(300); core.shutdown(); Assert.assertTrue(core.removedClients.contains(clientId)); } @Test public void testClientTimeoutBasic3() throws Exception { DummyServerCore core = new DummyServerCore(); ServerDispatcher clientTracker = new ServerDispatcher(core); DummyClientHandler clientHandler = new DummyClientHandler(); long clientId = 1000; core.init(clientTracker); clientHandler.failingClient = true; core.clients.put(clientId, new ClientData(clientId, clientHandler, "host", 3000)); core.clientLocks.put(clientId, new ReentrantLock()); clientTracker.setClientTimeout(100); clientTracker.setHeartbeatTimeout(1000); clientTracker.loopSleepTime = 10; clientTracker.assignClient(clientId); clientTracker.handleFailedDispatch(clientId, System.currentTimeMillis()); clientTracker.handleSuccessfulDispatch(clientId, System.currentTimeMillis()); new Thread(clientTracker).start(); Thread.sleep(300); core.shutdown(); Assert.assertFalse(core.removedClients.contains(clientId)); } @Test public void testClientHeartbeatBasic1() throws Exception { DummyServerCore core = new DummyServerCore(); ServerDispatcher clientTracker = new ServerDispatcher(core); DummyClientHandler clientHandler = new DummyClientHandler(); long clientId = 1000; core.init(clientTracker); core.clients.put(clientId, new ClientData(clientId, clientHandler, "host", 3000)); core.clientLocks.put(clientId, new ReentrantLock()); clientTracker.setClientTimeout(10000); // to avoid removing it clientTracker.setHeartbeatTimeout(100); clientTracker.loopSleepTime = 10; clientTracker.assignClient(clientId); new Thread(clientTracker).start(); Thread.sleep(350); core.shutdown(); Assert.assertEquals(3, clientHandler.receivedHeartbeats.size()); } @Test public void testClientHeartbeatBasic2() throws Exception { DummyServerCore core = new DummyServerCore(); ServerDispatcher clientTracker = new ServerDispatcher(core); DummyClientHandler clientHandler = new DummyClientHandler(); long clientId = 1000; core.init(clientTracker); core.clients.put(clientId, new ClientData(clientId, clientHandler, "host", 3000)); core.clientLocks.put(clientId, new ReentrantLock()); clientTracker.setClientTimeout(10000); // to avoid removing it clientTracker.setHeartbeatTimeout(200); clientTracker.loopSleepTime = 10; clientTracker.assignClient(clientId); new Thread(clientTracker).start(); Thread.sleep(80); clientTracker.handleFailedDispatch(clientId, System.currentTimeMillis()); Thread.sleep(80); clientTracker.handleSuccessfulDispatch(clientId, System.currentTimeMillis()); Thread.sleep(540); core.shutdown(); Assert.assertEquals(2, clientHandler.receivedHeartbeats.size()); } @Test public void testClientHeartbeatBasic3() throws Exception { DummyServerCore core = new DummyServerCore(); ServerDispatcher clientTracker = new ServerDispatcher(core); DummyClientHandler clientHandler = new DummyClientHandler(); long clientId = 1000; core.init(clientTracker); core.clients.put(clientId, new ClientData(clientId, clientHandler, "host", 3000)); core.clientLocks.put(clientId, new ReentrantLock()); clientTracker.setClientTimeout(10000); // to avoid removing it clientTracker.setHeartbeatTimeout(200); clientTracker.loopSleepTime = 10; clientTracker.assignClient(clientId); new Thread(clientTracker).start(); Thread.sleep(40); clientTracker.handleSuccessfulDispatch(clientId, System.currentTimeMillis()); Thread.sleep(40); clientTracker.handleFailedDispatch(clientId, System.currentTimeMillis()); Thread.sleep(200); core.shutdown(); Assert.assertEquals(0, clientHandler.receivedHeartbeats.size()); } class DummyServerCore extends EmptyServerCore { ConcurrentMap<Long, ClientData> clients = new ConcurrentHashMap<Long, ClientData>(); ConcurrentMap<Long, Lock> clientLocks = new ConcurrentHashMap<Long, Lock>(); Set<Long> removedClients = new HashSet<Long>(); ServerDispatcher clientTracker; public void init(ServerDispatcher clientTracker) { this.clientTracker = clientTracker; } @Override public ClientData getClientData(long clientId) { return clients.get(clientId); } @Override public Queue<NamespaceNotification> getClientNotificationQueue(long clientId) { return clients.get(clientId).queue; } @Override public boolean removeClient(long clientId) { synchronized (removedClients) { removedClients.add(clientId); } clients.remove(clientId); clientTracker.removeClient(clientId); return true; } @Override public Configuration getConfiguration() { return conf; } } private class DummyClientHandler extends EmptyClientHandler { public boolean failingClient = false; public boolean clientRemovedUs = false; // A sorted list with the timestamp when the heartbeats were received List<Long> receivedHeartbeats = new ArrayList<Long>(); @Override public void heartbeat(String serverId) throws InvalidServerIdException, TException { if (failingClient) throw new TException(); if (clientRemovedUs) throw new InvalidServerIdException(); receivedHeartbeats.add(new Date().getTime()); } } }