package org.apache.hadoop.corona;
import java.io.IOException;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import junit.framework.TestCase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.thrift.TException;
public class TestResourceCheck extends TestCase {
final static Log LOG = LogFactory.getLog(TestResourceCheck.class);
public final static String sessionHost = "localhost";
public static int getSessionPort(int i) {
return (7000 + i);
}
private Configuration conf;
private ClusterManagerTestable cm;
private ClusterNodeInfo nodes [];
private int numNodes;
private SessionInfo sessionInfo;
protected TopologyCache topologyCache;
protected void setUp(int reservedMemoryMB, int reservedDiskGB)
throws IOException {
conf = new Configuration();
conf.setClass("topology.node.switch.mapping.impl",
org.apache.hadoop.net.IPv4AddressTruncationMapping.class,
org.apache.hadoop.net.DNSToSwitchMapping.class);
conf.set(CoronaConf.CPU_TO_RESOURCE_PARTITIONING, TstUtils.std_cpu_to_resource_partitioning);
conf.setInt(CoronaConf.NODE_RESERVED_MEMORY_MB, reservedMemoryMB);
conf.setInt(CoronaConf.NODE_RESERVED_DISK_GB, reservedDiskGB);
topologyCache = new TopologyCache(conf);
cm = new ClusterManagerTestable(conf);
numNodes = 10;
nodes = new ClusterNodeInfo[numNodes];
Map<ResourceType, String> resourceInfos =
new EnumMap<ResourceType, String>(ResourceType.class);
resourceInfos.put(ResourceType.MAP, "");
resourceInfos.put(ResourceType.REDUCE, "");
for (int i = 0; i < numNodes; ++i) {
nodes[i] = new ClusterNodeInfo(TstUtils.getNodeHost(i),
new InetAddress(TstUtils.getNodeHost(i),
TstUtils.getNodePort(i)),
TstUtils.std_spec);
nodes[i].setFree(TstUtils.std_spec);
nodes[i].setResourceInfos(resourceInfos);
}
sessionInfo = new SessionInfo(
new InetAddress(sessionHost, getSessionPort(0)), "s", "hadoop");
sessionInfo.setPriority(SessionPriority.NORMAL);
sessionInfo.setPoolInfoStrings(
PoolInfo.createPoolInfoStrings(PoolGroupManager.DEFAULT_POOL_INFO));
}
public void testMemoryCheck() throws Exception {
// Set a high memory limit
setUp(TstUtils.std_spec.memoryMB + 1, 0);
String handle = TstUtils.startSession(cm, sessionInfo);
Session session = cm.getSessionManager().getSession(handle);
int maps = 800;
int reduces = 100;
submitRequests(handle, maps, reduces);
verifySession(session, ResourceType.MAP, maps, 0);
verifySession(session, ResourceType.REDUCE, reduces, 0);
addAllNodes();
TstUtils.reliableSleep(100);
// Nothing granted because of the memory limit
verifySession(session, ResourceType.MAP, maps, 0);
verifySession(session, ResourceType.REDUCE, reduces, 0);
cm.getNodeManager().getResourceLimit().setNodeReservedMemoryMB(
TstUtils.std_spec.memoryMB - 1);
// Perform heartbeats.
addAllNodes();
TstUtils.reliableSleep(500);
int maxMaps = cm.getNodeManager().getMaxCpuForType(ResourceType.MAP);
int maxReduces = cm.getNodeManager().getMaxCpuForType(ResourceType.REDUCE);
// Granted after changing the limit
verifySession(session, ResourceType.MAP, maps, maxMaps);
verifySession(session, ResourceType.REDUCE, reduces, maxReduces);
cm.sessionEnd(handle, SessionStatus.SUCCESSFUL);
}
public void testDiskCheck() throws Exception {
// Set a high memory limit
setUp(0, TstUtils.std_spec.diskGB + 1);
String handle = TstUtils.startSession(cm, sessionInfo);
Session session = cm.getSessionManager().getSession(handle);
int maps = 800;
int reduces = 100;
submitRequests(handle, maps, reduces);
verifySession(session, ResourceType.MAP, maps, 0);
verifySession(session, ResourceType.REDUCE, reduces, 0);
addAllNodes();
TstUtils.reliableSleep(100);
// Nothing granted because of the memory limit
verifySession(session, ResourceType.MAP, maps, 0);
verifySession(session, ResourceType.REDUCE, reduces, 0);
cm.getNodeManager().getResourceLimit().setNodeReservedDiskGB(
TstUtils.std_spec.diskGB - 1);
// Perform heartbeats.
addAllNodes();
TstUtils.reliableSleep(500);
int maxMaps = cm.getNodeManager().getMaxCpuForType(ResourceType.MAP);
int maxReduces = cm.getNodeManager().getMaxCpuForType(ResourceType.REDUCE);
// Granted after changing the limit
verifySession(session, ResourceType.MAP, maps, maxMaps);
verifySession(session, ResourceType.REDUCE, reduces, maxReduces);
cm.sessionEnd(handle, SessionStatus.SUCCESSFUL);
}
public void testResourceUpdate() throws Exception {
setUp(1, 0);
addSomeNodes(1);
ClusterNodeInfo newInfo = new ClusterNodeInfo(nodes[0]);
// Fully used.
newInfo.setFree(TstUtils.nothing_free_spec);
cm.nodeHeartbeat(newInfo);
String handle = TstUtils.startSession(cm, sessionInfo);
Session session = cm.getSessionManager().getSession(handle);
int maps = 80;
int reduces = 10;
submitRequests(handle, maps, reduces);
TstUtils.reliableSleep(100);
// Nothing granted.
verifySession(session, ResourceType.MAP, maps, 0);
verifySession(session, ResourceType.REDUCE, reduces, 0);
// Node is free
newInfo = new ClusterNodeInfo(newInfo);
newInfo.setFree(TstUtils.std_spec);
cm.nodeHeartbeat(newInfo);
TstUtils.reliableSleep(500);
int maxMaps = cm.getNodeManager().getMaxCpuForType(ResourceType.MAP);
int maxReduces = cm.getNodeManager().getMaxCpuForType(ResourceType.REDUCE);
verifySession(session, ResourceType.MAP, maps, maxMaps);
verifySession(session, ResourceType.REDUCE, reduces, maxReduces);
}
private void submitRequests(String handle, int maps, int reduces)
throws TException, InvalidSessionHandle, SafeModeException {
List<ResourceRequest> requests =
TstUtils.createRequests(this.numNodes, maps, reduces);
cm.requestResource(handle, requests);
}
private void verifySession(Session session, ResourceType type,
int request, int grant) {
synchronized (session) {
assertEquals(grant, session.getGrantCountForType(type));
assertEquals(request, session.getRequestCountForType(type));
assertEquals(request - grant,
session.getPendingRequestForType(type).size());
}
}
private void addSomeNodes(int count) throws TException {
for (int i=0; i<count; i++) {
try {
cm.nodeHeartbeat(nodes[i]);
} catch (DisallowedNode e) {
throw new TException(e);
} catch (SafeModeException e) {
LOG.info("Cluster Manager is in Safe Mode");
}
}
}
private void addAllNodes() throws TException {
addSomeNodes(this.numNodes);
}
}