You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@slider.apache.org by st...@apache.org on 2014/11/02 15:25:49 UTC
[37/50] git commit: SLIDER-587 test for dynamic role replacement
passing
SLIDER-587 test for dynamic role replacement passing
Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/0b06d631
Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/0b06d631
Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/0b06d631
Branch: refs/heads/feature/SLIDER-531-registry-enhancements
Commit: 0b06d631598097ea4d867252a2864d3ce374b768
Parents: 34f78ad
Author: Steve Loughran <st...@apache.org>
Authored: Fri Oct 31 21:24:24 2014 +0000
Committer: Steve Loughran <st...@apache.org>
Committed: Fri Oct 31 21:24:24 2014 +0000
----------------------------------------------------------------------
.../slider/server/appmaster/state/AppState.java | 2 -
.../server/appmaster/state/NodeEntry.java | 12 ++---
.../server/appmaster/state/NodeInstance.java | 4 +-
.../server/appmaster/state/RoleHistory.java | 44 +++++++++------
.../TestMockAppStateDynamicHistory.groovy | 57 ++++++++++++++------
.../appmaster/model/mock/MockAppState.groovy | 11 ++++
6 files changed, 86 insertions(+), 44 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/0b06d631/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
index 2b5d0ee..0848173 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
@@ -708,8 +708,6 @@ public class AppState {
log.info("New role {}", roleStatus);
roleHistory.addNewProviderRole(dynamicRole);
newRoles.add(dynamicRole);
- } else {
- log.debug("known role: {}", name);
}
}
return newRoles;
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/0b06d631/slider-core/src/main/java/org/apache/slider/server/appmaster/state/NodeEntry.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/NodeEntry.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/NodeEntry.java
index 83c590b..ebddaf9 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/NodeEntry.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/NodeEntry.java
@@ -37,10 +37,10 @@ package org.apache.slider.server.appmaster.state;
*/
public class NodeEntry {
- public final int index;
+ public final int rolePriority;
- public NodeEntry(int index) {
- this.index = index;
+ public NodeEntry(int rolePriority) {
+ this.rolePriority = rolePriority;
}
/**
@@ -132,8 +132,7 @@ public class NodeEntry {
public synchronized boolean onStartFailed() {
decStarting();
++startFailed;
- ++failed;
- return isAvailable();
+ return containerCompleted(false);
}
/**
@@ -211,7 +210,8 @@ public class NodeEntry {
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("NodeEntry{");
- sb.append("requested=").append(requested);
+ sb.append("priority=").append(rolePriority);
+ sb.append(", requested=").append(requested);
sb.append(", starting=").append(starting);
sb.append(", live=").append(live);
sb.append(", failed=").append(failed);
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/0b06d631/slider-core/src/main/java/org/apache/slider/server/appmaster/state/NodeInstance.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/NodeInstance.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/NodeInstance.java
index 1ba2282..bc79b71 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/NodeInstance.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/NodeInstance.java
@@ -52,7 +52,7 @@ public class NodeInstance {
*/
public synchronized NodeEntry get(int role) {
for (NodeEntry nodeEntry : nodeEntries) {
- if (nodeEntry.index == role) {
+ if (nodeEntry.rolePriority == role) {
return nodeEntry;
}
}
@@ -146,7 +146,7 @@ public class NodeInstance {
new StringBuilder(toString());
int i = 0;
for (NodeEntry entry : nodeEntries) {
- sb.append(String.format("\n [%02d] ", i++));
+ sb.append(String.format("\n [%02d] ", entry.rolePriority));
sb.append(entry.toString());
}
return sb.toString();
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/0b06d631/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleHistory.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleHistory.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleHistory.java
index 33c3442..f1c0af5 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleHistory.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleHistory.java
@@ -63,8 +63,6 @@ public class RoleHistory {
protected static final Logger log =
LoggerFactory.getLogger(RoleHistory.class);
private final List<ProviderRole> providerRoles;
- private final Map<String, ProviderRole> providerRoleMap =
- new HashMap<String, ProviderRole>();
private long startTime;
/**
* Time when saved
@@ -97,6 +95,7 @@ public class RoleHistory {
* ask with/without locality. Has other potential uses as well.
*/
private Set<String> failedNodes = new HashSet<String>();
+
// dummy to be used in maps for faster lookup where we don't care about values
private final Object DUMMY_VALUE = new Object();
@@ -104,9 +103,6 @@ public class RoleHistory {
BadConfigException {
this.providerRoles = providerRoles;
roleSize = providerRoles.size();
- for (ProviderRole providerRole : providerRoles) {
- providerRoleMap.put(providerRole.name, providerRole);
- }
reset();
}
@@ -120,18 +116,24 @@ public class RoleHistory {
resetAvailableNodeLists();
outstandingRequests = new OutstandingRequestTracker();
+
Map<Integer, RoleStatus> roleStats = new HashMap<Integer, RoleStatus>();
-
-
for (ProviderRole providerRole : providerRoles) {
- addProviderRole(roleStats, providerRole);
+ checkProviderRole(roleStats, providerRole);
}
}
-
- private void addProviderRole(Map<Integer, RoleStatus> roleStats,
- ProviderRole providerRole)
- throws ArrayIndexOutOfBoundsException, BadConfigException {
+ /**
+ * safety check: make sure the provider role is unique amongst
+ * the role stats...which is extended with the new role
+ * @param roleStats role stats
+ * @param providerRole role
+ * @throws ArrayIndexOutOfBoundsException
+ * @throws BadConfigException
+ */
+ private void checkProviderRole(Map<Integer, RoleStatus> roleStats,
+ ProviderRole providerRole)
+ throws BadConfigException {
int index = providerRole.id;
if (index < 0) {
throw new BadConfigException("Provider " + providerRole
@@ -154,12 +156,12 @@ public class RoleHistory {
throws BadConfigException {
Map<Integer, RoleStatus> roleStats = new HashMap<Integer, RoleStatus>();
-
for (ProviderRole role : providerRoles) {
roleStats.put(role.id, new RoleStatus(role));
}
- addProviderRole(roleStats, providerRole);
+ checkProviderRole(roleStats, providerRole);
+ this.providerRoles.add(providerRole);
}
/**
@@ -432,7 +434,8 @@ public class RoleHistory {
* @param id role ID
* @return potenially null list
*/
- private List<NodeInstance> getNodesForRoleId(int id) {
+ @VisibleForTesting
+ public List<NodeInstance> getNodesForRoleId(int id) {
return availableNodes.get(id);
}
@@ -610,6 +613,8 @@ public class RoleHistory {
public synchronized boolean onContainerAllocated(Container container, int desiredCount, int actualCount) {
int role = ContainerPriority.extractRole(container);
String hostname = RoleHistoryUtils.hostnameOf(container);
+ LinkedList<NodeInstance> nodeInstances =
+ getOrCreateNodesForRoleId(role);
boolean requestFound =
outstandingRequests.onContainerAllocated(role, hostname);
if (desiredCount <= actualCount) {
@@ -619,7 +624,7 @@ public class RoleHistory {
if (!hosts.isEmpty()) {
//add the list
log.debug("Adding {} hosts for role {}", hosts.size(), role);
- getOrCreateNodesForRoleId(role).addAll(hosts);
+ nodeInstances.addAll(hosts);
sortAvailableNodeList(role);
}
}
@@ -734,6 +739,8 @@ public class RoleHistory {
boolean wasReleased,
boolean shortLived) {
NodeEntry nodeEntry = getOrCreateNodeEntry(container);
+ log.debug("Finished container for node {}, released={}, shortlived={}",
+ nodeEntry.rolePriority, wasReleased, shortLived);
boolean available;
if (shortLived) {
nodeEntry.onStartFailed();
@@ -781,13 +788,16 @@ public class RoleHistory {
List<NodeInstance> instances =
getOrCreateNodesForRoleId(role.id);
log.info(" available: " + instances.size()
- + " " + SliderUtils.joinWithInnerSeparator(", ", instances));
+ + " " + SliderUtils.joinWithInnerSeparator(" ", instances));
}
log.info("Nodes in Cluster: {}", getClusterSize());
for (NodeInstance node : nodemap.values()) {
log.info(node.toFullString());
}
+
+ log.info("Failed nodes: {}",
+ SliderUtils.joinWithInnerSeparator(" ", failedNodes));
}
/**
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/0b06d631/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/appstate/TestMockAppStateDynamicHistory.groovy
----------------------------------------------------------------------
diff --git a/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/appstate/TestMockAppStateDynamicHistory.groovy b/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/appstate/TestMockAppStateDynamicHistory.groovy
index 9a9ad23..7d41012 100644
--- a/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/appstate/TestMockAppStateDynamicHistory.groovy
+++ b/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/appstate/TestMockAppStateDynamicHistory.groovy
@@ -24,7 +24,6 @@ import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.yarn.api.records.ContainerId
import org.apache.slider.api.ResourceKeys
import org.apache.slider.core.conf.ConfTreeOperations
-import org.apache.slider.providers.PlacementPolicy
import org.apache.slider.providers.ProviderRole
import org.apache.slider.server.appmaster.model.mock.BaseMockAppStateTest
import org.apache.slider.server.appmaster.model.mock.MockAppState
@@ -84,7 +83,7 @@ class TestMockAppStateDynamicHistory extends BaseMockAppStateTest
public void testDynamicRoleHistory() throws Throwable {
def dynamic = "dynamicRole"
- int priority_num_8 = 8
+ int role_priority_8 = 8
int desired = 1
int placementPolicy = 0
// snapshot and patch existing spec
@@ -92,7 +91,7 @@ class TestMockAppStateDynamicHistory extends BaseMockAppStateTest
appState.resourcesSnapshot.confTree)
def opts = [
(ResourceKeys.COMPONENT_INSTANCES): ""+desired,
- (ResourceKeys.COMPONENT_PRIORITY) : "" +priority_num_8,
+ (ResourceKeys.COMPONENT_PRIORITY) : "" +role_priority_8,
(ResourceKeys.COMPONENT_PLACEMENT_POLICY): "" + placementPolicy
]
@@ -109,21 +108,21 @@ class TestMockAppStateDynamicHistory extends BaseMockAppStateTest
def snapshotDefinition = appState.resourcesSnapshot.getMandatoryComponent(
dynamic)
assert snapshotDefinition.getMandatoryOptionInt(
- ResourceKeys.COMPONENT_PRIORITY) == priority_num_8
+ ResourceKeys.COMPONENT_PRIORITY) == role_priority_8
// now look at the role map
assert appState.roleMap[dynamic] != null
def mappedRole = appState.roleMap[dynamic]
- assert mappedRole.id == priority_num_8
+ assert mappedRole.id == role_priority_8
def priorityMap = appState.rolePriorityMap
assert priorityMap.size() == 4
ProviderRole dynamicProviderRole
- assert (dynamicProviderRole = priorityMap[priority_num_8]) != null
- assert dynamicProviderRole.id == priority_num_8
+ assert (dynamicProviderRole = priorityMap[role_priority_8]) != null
+ assert dynamicProviderRole.id == role_priority_8
- assert null != appState.roleStatusMap[priority_num_8]
- def dynamicRoleStatus = appState.roleStatusMap[priority_num_8]
+ assert null != appState.roleStatusMap[role_priority_8]
+ def dynamicRoleStatus = appState.roleStatusMap[role_priority_8]
assert dynamicRoleStatus.desired == desired
@@ -135,6 +134,9 @@ class TestMockAppStateDynamicHistory extends BaseMockAppStateTest
assert targetNode == engine.allocator.nextIndex()
def targetHostname = engine.cluster.nodeAt(targetNode).hostname
+ // clock is set to a small value
+ appState.time = 100000
+
// allocate the nodes
def actions = appState.reviewRequestAndReleaseNodes()
assert actions.size() == 1
@@ -150,31 +152,52 @@ class TestMockAppStateDynamicHistory extends BaseMockAppStateTest
RoleInstance ri = allocations[0]
assert ri.role == dynamic
- assert ri.roleId == priority_num_8
+ assert ri.roleId == role_priority_8
assert ri.host.host == targetHostname
// now look at the role history
def roleHistory = appState.roleHistory
- def activeNodes = roleHistory.listActiveNodes(priority_num_8)
+ def activeNodes = roleHistory.listActiveNodes(role_priority_8)
assert activeNodes.size() == 1
NodeInstance activeNode = activeNodes[0]
+ assert activeNode.get(role_priority_8)
+ def entry8 = activeNode.get(role_priority_8)
+ assert entry8.active == 1
assert activeNode.hostname == targetHostname
-
- // now trigger a termination event on that role
+
+ def activeNodeInstance = roleHistory.getOrCreateNodeInstance(ri.container)
+
+ assert activeNode == activeNodeInstance
+ def entry
+ assert (entry = activeNodeInstance.get(role_priority_8)) != null
+ assert entry.active
+ assert entry.live
+ // now trigger a termination event on that role
+
+ // increment time for a long-lived failure event
+ appState.time = appState.time + 100000
+
+ log.debug("Triggering failure")
def cid = ri.id
- // failure
AppState.NodeCompletionResult result = appState.onCompletedNode(
containerStatus(cid, 1))
assert result.roleInstance == ri
assert result.containerFailed
+
+ roleHistory.dump();
+ // values should have changed
+ assert entry.failed == 1
+ assert !entry.startFailed
+ assert !entry.active
+ assert !entry.live
+
- def nodeForNewInstance = roleHistory.findNodeForNewInstance(
- dynamicRoleStatus)
- assert nodeForNewInstance
+ def nodesForRoleId = roleHistory.getNodesForRoleId(role_priority_8)
+ assert nodesForRoleId
// make sure new nodes will default to a different host in the engine
assert targetNode < engine.allocator.nextIndex()
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/0b06d631/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/mock/MockAppState.groovy
----------------------------------------------------------------------
diff --git a/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/mock/MockAppState.groovy b/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/mock/MockAppState.groovy
index ad85b89..e683587 100644
--- a/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/mock/MockAppState.groovy
+++ b/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/mock/MockAppState.groovy
@@ -30,6 +30,8 @@ class MockAppState extends AppState {
super(recordFactory);
}
+ long time = 0;
+
/**
* Instance with a mock record factory
*/
@@ -40,4 +42,13 @@ class MockAppState extends AppState {
public Map<String, ProviderRole> getRoleMap() {
return super.roleMap;
}
+
+ /**
+ * Current time. if the <code>time</code> field
+ * is set, that value is returned
+ * @return the current time.
+ */
+ protected long now() {
+ return time ?: System.currentTimeMillis();
+ }
}