eu.stratosphere.nephele.instance.local.LocalInstanceManager Maven / Gradle / Ivy
/***********************************************************************************************************************
* Copyright (C) 2010-2013 by the Stratosphere project (http://stratosphere.eu)
*
* 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 eu.stratosphere.nephele.instance.local;
import java.io.File;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import eu.stratosphere.configuration.ConfigConstants;
import eu.stratosphere.configuration.Configuration;
import eu.stratosphere.configuration.GlobalConfiguration;
import eu.stratosphere.nephele.instance.AbstractInstance;
import eu.stratosphere.nephele.instance.AllocatedResource;
import eu.stratosphere.nephele.instance.AllocationID;
import eu.stratosphere.nephele.instance.HardwareDescription;
import eu.stratosphere.nephele.instance.HardwareDescriptionFactory;
import eu.stratosphere.nephele.instance.InstanceConnectionInfo;
import eu.stratosphere.nephele.instance.InstanceException;
import eu.stratosphere.nephele.instance.InstanceListener;
import eu.stratosphere.nephele.instance.InstanceManager;
import eu.stratosphere.nephele.instance.InstanceRequestMap;
import eu.stratosphere.nephele.instance.InstanceType;
import eu.stratosphere.nephele.instance.InstanceTypeDescription;
import eu.stratosphere.nephele.instance.InstanceTypeDescriptionFactory;
import eu.stratosphere.nephele.instance.InstanceTypeFactory;
import eu.stratosphere.nephele.jobgraph.JobID;
import eu.stratosphere.nephele.taskmanager.TaskManager;
import eu.stratosphere.nephele.topology.NetworkTopology;
import eu.stratosphere.nephele.util.SerializableHashMap;
/**
* The local instance manager is designed to manage instance allocation/deallocation for a single-node setup. It spans a
* task manager which is executed within the same process as the job manager. Moreover, it determines the hardware
* characteristics of the machine it runs on and generates a default instance type with the identifier "default". If
* desired this default instance type can also be overwritten.
*/
public class LocalInstanceManager implements InstanceManager {
/**
* The log object used to report events and errors.
*/
private static final Log LOG = LogFactory.getLog(LocalInstanceManager.class);
/**
* The key for the configuration parameter defining the instance type to be used by the local instance manager. If
* the parameter is not set, a default instance type with the identifier "default" is generated from the machine's
* hardware characteristics.
*/
private static final String LOCALINSTANCE_TYPE_KEY = "instancemanager.local.type";
private static final int SLEEP_TIME = 50;
private static final int START_STOP_TIMEOUT = 2000;
/**
* The instance listener registered with this instance manager.
*/
private InstanceListener instanceListener;
/**
* The default instance type which is either generated from the hardware characteristics of the machine the local
* instance manager runs on or read from the configuration.
*/
private final InstanceType defaultInstanceType;
/**
* A synchronization object to protect critical sections.
*/
private final Object synchronizationObject = new Object();
/**
* Stores which task manager is currently occupied by a job.
*/
private Map allocatedResources = new HashMap();
/**
* The local instances encapsulating the task managers
*/
private Map localInstances = new HashMap();
/**
* The threads running the local task managers.
*/
private final List taskManagers = new ArrayList();
/**
* The network topology the local instance is part of.
*/
private final NetworkTopology networkTopology;
/**
* The map of instance type descriptions.
*/
private final Map instanceTypeDescriptionMap;
/**
* Number of task managers
*/
private final int numTaskManagers;
/**
* Constructs a new local instance manager.
*
*/
public LocalInstanceManager() throws Exception {
final Configuration config = GlobalConfiguration.getConfiguration();
// get the default instance type
InstanceType type = null;
final String descr = config.getString(LOCALINSTANCE_TYPE_KEY, null);
if (descr != null) {
LOG.info("Attempting to parse default instance type from string " + descr);
type = InstanceTypeFactory.constructFromDescription(descr);
if (type == null) {
LOG.warn("Unable to parse default instance type from configuration, using hardware profile instead");
}
}
this.defaultInstanceType = (type != null) ? type : createDefaultInstanceType();
LOG.info("Default instance type is " + this.defaultInstanceType.getIdentifier());
this.networkTopology = NetworkTopology.createEmptyTopology();
this.instanceTypeDescriptionMap = new SerializableHashMap();
numTaskManagers = GlobalConfiguration.getInteger(ConfigConstants
.LOCAL_INSTANCE_MANAGER_NUMBER_TASK_MANAGER, 1);
for(int i=0; i< numTaskManagers; i++){
Configuration tm = new Configuration();
int ipcPort = GlobalConfiguration.getInteger(ConfigConstants.TASK_MANAGER_IPC_PORT_KEY,
ConfigConstants.DEFAULT_TASK_MANAGER_IPC_PORT);
int dataPort = GlobalConfiguration.getInteger(ConfigConstants.TASK_MANAGER_DATA_PORT_KEY,
ConfigConstants.DEFAULT_TASK_MANAGER_DATA_PORT);
tm.setInteger(ConfigConstants.TASK_MANAGER_IPC_PORT_KEY, ipcPort + i);
tm.setInteger(ConfigConstants.TASK_MANAGER_DATA_PORT_KEY, dataPort + i);
GlobalConfiguration.includeConfiguration(tm);
TaskManager t = new TaskManager();
taskManagers.add(t);
}
}
@Override
public InstanceType getDefaultInstanceType() {
return this.defaultInstanceType;
}
@Override
public InstanceType getInstanceTypeByName(String instanceTypeName) {
if (this.defaultInstanceType.getIdentifier().equals(instanceTypeName)) {
return this.defaultInstanceType;
}
return null;
}
@Override
public InstanceType getSuitableInstanceType(int minNumComputeUnits, int minNumCPUCores,
int minMemorySize, int minDiskCapacity, int maxPricePerHour) {
if (minNumComputeUnits > this.defaultInstanceType.getNumberOfComputeUnits()) {
return null;
}
if (minNumCPUCores > this.defaultInstanceType.getNumberOfCores()) {
return null;
}
if (minMemorySize > this.defaultInstanceType.getMemorySize()) {
return null;
}
if (minDiskCapacity > this.defaultInstanceType.getDiskCapacity()) {
return null;
}
if (maxPricePerHour > this.defaultInstanceType.getPricePerHour()) {
return null;
}
return this.defaultInstanceType;
}
@Override
public void releaseAllocatedResource(final JobID jobID, final Configuration conf,
final AllocatedResource allocatedResource)
throws InstanceException {
LocalInstance instance = (LocalInstance) allocatedResource.getInstance();
synchronized (this.synchronizationObject) {
if(allocatedResources.containsKey(allocatedResource.getInstance())){
if(allocatedResources.get(instance).equals(allocatedResource)){
allocatedResources.remove(instance);
return;
}
}
throw new InstanceException("Resource with allocation ID " + allocatedResource.getAllocationID()
+ " has not been allocated to job with ID " + jobID
+ " according to the local instance manager's internal bookkeeping");
}
}
@Override
public void reportHeartBeat(final InstanceConnectionInfo instanceConnectionInfo,
final HardwareDescription hardwareDescription) {
synchronized (this.synchronizationObject) {
if(!localInstances.containsKey(instanceConnectionInfo)){
LocalInstance localInstance = new LocalInstance(this.defaultInstanceType, instanceConnectionInfo,
this.networkTopology.getRootNode(), this.networkTopology, hardwareDescription);
localInstances.put(instanceConnectionInfo, localInstance);
this.instanceTypeDescriptionMap.put(this.defaultInstanceType, InstanceTypeDescriptionFactory
.construct(this.defaultInstanceType, hardwareDescription, localInstances.size()));
}
}
}
@Override
public void shutdown() {
// Stop the task managers
for(TaskManager t : taskManagers){
t.shutdown();
}
boolean areAllTaskManagerShutdown = false;
int timeout = START_STOP_TIMEOUT * this.taskManagers.size();
for(int sleep = 0; sleep < timeout; sleep += SLEEP_TIME){
areAllTaskManagerShutdown = true;
for(TaskManager t: taskManagers){
if(!t.isShutDown()){
areAllTaskManagerShutdown = false;
break;
}
}
if(areAllTaskManagerShutdown){
break;
}
try {
Thread.sleep(SLEEP_TIME);
}catch(InterruptedException e){
break;
}
}
if(!areAllTaskManagerShutdown){
throw new RuntimeException(String.format("TaskManager shut down timed out (%d ms).", timeout));
}
instanceTypeDescriptionMap.clear();
synchronized(this.synchronizationObject){
for(LocalInstance instance: this.localInstances.values()){
instance.destroyProxies();
}
localInstances.clear();
}
}
@Override
public NetworkTopology getNetworkTopology(final JobID jobID) {
return this.networkTopology;
}
@Override
public void setInstanceListener(final InstanceListener instanceListener) {
this.instanceListener = instanceListener;
}
/**
* Creates a default instance type based on the hardware characteristics of the machine that calls this method. The
* default instance type contains the machine's number of CPU cores and size of physical memory. The disc capacity
* is calculated from the free space in the directory for temporary files.
*
* @return the default instance type used for the local machine
*/
public static final InstanceType createDefaultInstanceType() {
final HardwareDescription hardwareDescription = HardwareDescriptionFactory.extractFromSystem();
int diskCapacityInGB = 0;
final String[] tempDirs = GlobalConfiguration.getString(ConfigConstants.TASK_MANAGER_TMP_DIR_KEY,
ConfigConstants.DEFAULT_TASK_MANAGER_TMP_PATH).split(File.pathSeparator);
for (final String tempDir : tempDirs) {
if (tempDir != null) {
File f = new File(tempDir);
diskCapacityInGB = Math.max(diskCapacityInGB, (int) (f.getFreeSpace() / (1024L * 1024L * 1024L)));
}
}
final int physicalMemory = (int) (hardwareDescription.getSizeOfPhysicalMemory() / (1024L * 1024L));
return InstanceTypeFactory.construct("default", hardwareDescription.getNumberOfCPUCores(),
hardwareDescription.getNumberOfCPUCores(), physicalMemory, diskCapacityInGB, 0);
}
@Override
public Map getMapOfAvailableInstanceTypes() {
return this.instanceTypeDescriptionMap;
}
@Override
public void requestInstance(final JobID jobID, final Configuration conf,
final InstanceRequestMap instanceRequestMap,
final List splitAffinityList) throws InstanceException {
// TODO: This can be implemented way simpler...
// Iterate over all instance types
final Iterator> it = instanceRequestMap.getMinimumIterator();
final List assignedResources = new ArrayList();
boolean assignmentSuccessful = true;
while (it.hasNext()) {
// Iterate over all requested instances of a specific type
final Map.Entry entry = it.next();
for (int i = 0; i < entry.getValue().intValue(); i++) {
synchronized (this.synchronizationObject) {
boolean instanceFound = false;
for(LocalInstance instance: localInstances.values()){
if(!allocatedResources.containsKey(instance)){
AllocatedResource assignedResource = new AllocatedResource(instance, entry.getKey(),
new AllocationID());
allocatedResources.put(instance, assignedResource);
assignedResources.add(assignedResource);
instanceFound = true;
break;
}
}
assignmentSuccessful &= instanceFound;
}
}
}
if(assignmentSuccessful){
new LocalInstanceNotifier(this.instanceListener, jobID, assignedResources).start();
}else{
throw new InstanceException("Could not satisfy instance request.");
}
}
@Override
public AbstractInstance getInstanceByName(final String name) {
if (name == null) {
throw new IllegalArgumentException("Argument name must not be null");
}
synchronized (this.synchronizationObject) {
for(LocalInstance instance :localInstances.values()){
if(name.equals(instance.getName())){
return instance;
}
}
}
return null;
}
@Override
public void cancelPendingRequests(final JobID jobID) {
// The local instance manager does not support pending requests, so nothing to do here
}
@Override
public int getNumberOfTaskTrackers() {
return localInstances.size();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy