/** * Get a runnable node. * * @param requestedNode The request information. * @param maxLevel The maximum locality level that we can go to. * @param type The type of resource. * @param excluded The excluded nodes. * @return The runnable node that can be used. */ public ClusterNode getRunnableNode( RequestedNode requestedNode, LocalityLevel maxLevel, ResourceType type, Set<String> excluded) { ClusterNode node = null; RunnableIndices r = typeToIndices.get(type); // find host local node = r.getRunnableNodeForHost(requestedNode); if (maxLevel == LocalityLevel.NODE || node != null) { return node; } node = r.getRunnableNodeForRack(requestedNode, excluded); if (maxLevel == LocalityLevel.RACK || node != null) { return node; } // find any node node = r.getRunnableNodeForAny(excluded); return node; }
/** * Cancel grant on a node * * @param nodeName the node the grant is on * @param sessionId the session the grant was given to * @param requestId the request this grant satisfied */ public void cancelGrant(String nodeName, String sessionId, int requestId) { ClusterNode node = nameToNode.get(nodeName); if (node == null) { LOG.warn("Canceling grant for non-existent node: " + nodeName); return; } synchronized (node) { if (node.deleted) { LOG.warn("Canceling grant for deleted node: " + nodeName); return; } String hoststr = node.getClusterNodeInfo().getAddress().getHost(); if (!canAllowNode(hoststr)) { LOG.warn("Canceling grant for excluded node: " + hoststr); return; } ResourceRequestInfo req = node.getRequestForGrant(sessionId, requestId); if (req != null) { ResourceRequest unitReq = Utilities.getUnitResourceRequest(req.getType()); boolean previouslyRunnable = node.checkForGrant(unitReq, resourceLimit); node.cancelGrant(sessionId, requestId); loadManager.decrementLoad(req.getType()); if (!previouslyRunnable && node.checkForGrant(unitReq, resourceLimit)) { RunnableIndices r = typeToIndices.get(req.getType()); if (!faultManager.isBlacklisted(node.getName(), req.getType())) { r.addRunnable(node); } } } } }
/** * Refresh the includes/excludes information. * * @throws IOException */ public synchronized void refreshNodes() throws IOException { hostsReader.refresh(); LOG.info( "After refresh Included hosts: " + hostsReader.getHostNames().size() + " Excluded hosts: " + hostsReader.getExcludedHosts().size()); Set<String> newHosts = hostsReader.getHostNames(); Set<String> newExcludes = hostsReader.getExcludedHosts(); Set<ClusterNode> hostsToExclude = new HashSet<ClusterNode>(); for (ClusterNode tmpNode : nameToNode.values()) { String host = tmpNode.getHost(); // Check if not included or explicitly excluded. if (!newHosts.contains(host) || newExcludes.contains(host)) { hostsToExclude.add(tmpNode); } } for (ClusterNode node : hostsToExclude) { synchronized (node) { for (Map.Entry<ResourceType, RunnableIndices> entry : typeToIndices.entrySet()) { ResourceType type = entry.getKey(); RunnableIndices r = entry.getValue(); if (r.hasRunnable(node)) { LOG.info( "Node " + node.getName() + " is no longer " + type + " runnable because it is excluded"); r.deleteRunnable(node); } } } } }
/** * Find the best matching node for this host subject to the maxLevel constraint * * @param host the host of the request * @param maxLevel the max locality level to consider * @param type the type of resource needed on the node * @param excluded the list of nodes to exclude from consideration * @return the runnable node satisfying the constraints */ public ClusterNode getRunnableNode( String host, LocalityLevel maxLevel, ResourceType type, Set<String> excluded) { if (host == null) { RunnableIndices r = typeToIndices.get(type); return r.getRunnableNodeForAny(excluded); } RequestedNode node = resolve(host, type); return getRunnableNode(node, maxLevel, type, excluded); }
/** * Remove one application type from the node. Happens when the daemon responsible for handling * this application type on the node goes down * * @param node the node * @param type the type of the resource * @return the list of grants that belonged to the application on this node */ protected Set<ClusterNode.GrantId> deleteAppFromNode(ClusterNode node, ResourceType type) { synchronized (node) { if (node.deleted) { return null; } nameToApps.remove(node.getName()); RunnableIndices r = typeToIndices.get(type); r.deleteRunnable(node); return node.getGrants(type); } }
/** * Register a new application on the node * * @param node the node to register on * @param type the type of an application * @param appInfo the appInfo string for the application */ protected void addAppToNode(ClusterNode node, ResourceType type, String appInfo) { synchronized (node) { // Update primary index. Map<ResourceType, String> apps = nameToApps.get(node.getName()); apps.put(type, appInfo); // Update runnable indices. for (Map.Entry<ResourceType, RunnableIndices> entry : typeToIndices.entrySet()) { if (type.equals(entry.getKey())) { if (node.checkForGrant(Utilities.getUnitResourceRequest(type), resourceLimit)) { RunnableIndices r = entry.getValue(); r.addRunnable(node); } } } } }
/** * Update the runnable status of a node based on resources available. This checks both resources * and slot availability. * * @param node The node */ private void updateRunnability(ClusterNode node) { synchronized (node) { for (Map.Entry<ResourceType, RunnableIndices> entry : typeToIndices.entrySet()) { ResourceType type = entry.getKey(); RunnableIndices r = entry.getValue(); ResourceRequest unitReq = Utilities.getUnitResourceRequest(type); boolean currentlyRunnable = r.hasRunnable(node); boolean shouldBeRunnable = node.checkForGrant(unitReq, resourceLimit); if (currentlyRunnable && !shouldBeRunnable) { LOG.info("Node " + node.getName() + " is no longer " + type + " runnable"); r.deleteRunnable(node); } else if (!currentlyRunnable && shouldBeRunnable) { LOG.info("Node " + node.getName() + " is now " + type + " runnable"); r.addRunnable(node); } } } }
/** * Add a grant to a node * * @param node the node the grant is on * @param sessionId the session the grant is given to * @param req the request this grant satisfies * @return true if the grant can be added to the node, false otherwise */ public boolean addGrant(ClusterNode node, String sessionId, ResourceRequestInfo req) { synchronized (node) { if (node.deleted) { return false; } if (!node.checkForGrant(Utilities.getUnitResourceRequest(req.getType()), resourceLimit)) { return false; } node.addGrant(sessionId, req); loadManager.incrementLoad(req.getType()); hostsToSessions.get(node).add(sessionId); if (!node.checkForGrant(Utilities.getUnitResourceRequest(req.getType()), resourceLimit)) { RunnableIndices r = typeToIndices.get(req.getType()); r.deleteRunnable(node); } } return true; }
/** * Delete the node from the cluster. This happens when the node times out or is being * decommissioned. * * @param node the node to remove * @return the list of grants that are running on the node */ protected Set<ClusterNode.GrantId> deleteNode(ClusterNode node) { synchronized (node) { if (node.deleted) { return null; } node.deleted = true; // 1: primary nameToNode.remove(node.getName()); faultManager.deleteNode(node.getName()); nameToApps.remove(node.getName()); hostsToSessions.remove(node); setAliveDeadMetrics(); // 2: update runnable index for (RunnableIndices r : typeToIndices.values()) { r.deleteRunnable(node); } return node.getGrants(); } }
/** * Add a node to be managed. * * @param node Node to be managed * @param resourceInfos Mapping of the resource type to runnable indices */ protected void addNode(ClusterNode node, Map<ResourceType, String> resourceInfos) { synchronized (node) { // 1: primary nameToNode.put(node.getName(), node); faultManager.addNode(node.getName(), resourceInfos.keySet()); nameToApps.put(node.getName(), resourceInfos); hostsToSessions.put(node, new HashSet<String>()); setAliveDeadMetrics(); // 2: update runnable indices for (Map.Entry<ResourceType, RunnableIndices> entry : typeToIndices.entrySet()) { ResourceType type = entry.getKey(); if (resourceInfos.containsKey(type)) { if (node.checkForGrant(Utilities.getUnitResourceRequest(type), resourceLimit)) { RunnableIndices r = entry.getValue(); r.addRunnable(node); } } } } }
/** * See if there are any runnable nodes of a given type * * @param type the type to look for * @return true if there are runnable nodes for this type, false otherwise */ public boolean existRunnableNodes(ResourceType type) { RunnableIndices r = typeToIndices.get(type); return r.existRunnableNodes(); }
/** * Resolve a host name. * * @param host The host. * @param type The resource type. * @return The resolved form. */ public RequestedNode resolve(String host, ResourceType type) { RunnableIndices indices = typeToIndices.get(type); return indices.getOrCreateRequestedNode(host); }