YARN-99. Modify private distributed cache to localize files such that no local directory hits unix file count limits and thus prevent job failures. Contributed by Omkar Vinit Joshi.
svn merge --ignore-ancestry -c 1465853 ../../trunk/ git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1465854 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b287d8de6d
commit
335e02124b
|
@ -146,6 +146,10 @@ Release 2.0.5-beta - UNRELEASED
|
||||||
to implement closeable so that they can be stopped when needed via
|
to implement closeable so that they can be stopped when needed via
|
||||||
RPC.stopProxy(). (Siddharth Seth via vinodkv)
|
RPC.stopProxy(). (Siddharth Seth via vinodkv)
|
||||||
|
|
||||||
|
YARN-99. Modify private distributed cache to localize files such that no
|
||||||
|
local directory hits unix file count limits and thus prevent job failures.
|
||||||
|
(Omkar Vinit Joshi via vinodkv)
|
||||||
|
|
||||||
Release 2.0.4-alpha - UNRELEASED
|
Release 2.0.4-alpha - UNRELEASED
|
||||||
|
|
||||||
INCOMPATIBLE CHANGES
|
INCOMPATIBLE CHANGES
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* 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.yarn.server.nodemanager.api;
|
||||||
|
|
||||||
|
import org.apache.hadoop.classification.InterfaceAudience.Private;
|
||||||
|
import org.apache.hadoop.yarn.api.records.LocalResource;
|
||||||
|
import org.apache.hadoop.yarn.api.records.URL;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
|
||||||
|
@Private
|
||||||
|
@VisibleForTesting
|
||||||
|
public interface ResourceLocalizationSpec {
|
||||||
|
|
||||||
|
public void setResource(LocalResource rsrc);
|
||||||
|
|
||||||
|
public LocalResource getResource();
|
||||||
|
|
||||||
|
public void setDestinationDirectory(URL destinationDirectory);
|
||||||
|
|
||||||
|
public URL getDestinationDirectory();
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
/**
|
||||||
|
* 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.yarn.server.nodemanager.api.impl.pb;
|
||||||
|
|
||||||
|
import org.apache.hadoop.yarn.api.records.LocalResource;
|
||||||
|
import org.apache.hadoop.yarn.api.records.ProtoBase;
|
||||||
|
import org.apache.hadoop.yarn.api.records.URL;
|
||||||
|
import org.apache.hadoop.yarn.api.records.impl.pb.LocalResourcePBImpl;
|
||||||
|
import org.apache.hadoop.yarn.api.records.impl.pb.URLPBImpl;
|
||||||
|
import org.apache.hadoop.yarn.proto.YarnServerNodemanagerServiceProtos.ResourceLocalizationSpecProto;
|
||||||
|
import org.apache.hadoop.yarn.proto.YarnServerNodemanagerServiceProtos.ResourceLocalizationSpecProtoOrBuilder;
|
||||||
|
import org.apache.hadoop.yarn.server.nodemanager.api.ResourceLocalizationSpec;
|
||||||
|
|
||||||
|
public class ResourceLocalizationSpecPBImpl extends
|
||||||
|
ProtoBase<ResourceLocalizationSpecProto> implements
|
||||||
|
ResourceLocalizationSpec {
|
||||||
|
|
||||||
|
private ResourceLocalizationSpecProto proto = ResourceLocalizationSpecProto
|
||||||
|
.getDefaultInstance();
|
||||||
|
private ResourceLocalizationSpecProto.Builder builder = null;
|
||||||
|
private boolean viaProto;
|
||||||
|
private LocalResource resource = null;
|
||||||
|
private URL destinationDirectory = null;
|
||||||
|
|
||||||
|
public ResourceLocalizationSpecPBImpl() {
|
||||||
|
builder = ResourceLocalizationSpecProto.newBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceLocalizationSpecPBImpl(ResourceLocalizationSpecProto proto) {
|
||||||
|
this.proto = proto;
|
||||||
|
viaProto = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalResource getResource() {
|
||||||
|
ResourceLocalizationSpecProtoOrBuilder p = viaProto ? proto : builder;
|
||||||
|
if (resource != null) {
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
if (!p.hasResource()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
resource = new LocalResourcePBImpl(p.getResource());
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setResource(LocalResource rsrc) {
|
||||||
|
maybeInitBuilder();
|
||||||
|
resource = rsrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URL getDestinationDirectory() {
|
||||||
|
ResourceLocalizationSpecProtoOrBuilder p = viaProto ? proto : builder;
|
||||||
|
if (destinationDirectory != null) {
|
||||||
|
return destinationDirectory;
|
||||||
|
}
|
||||||
|
if (!p.hasDestinationDirectory()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
destinationDirectory = new URLPBImpl(p.getDestinationDirectory());
|
||||||
|
return destinationDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDestinationDirectory(URL destinationDirectory) {
|
||||||
|
maybeInitBuilder();
|
||||||
|
this.destinationDirectory = destinationDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceLocalizationSpecProto getProto() {
|
||||||
|
mergeLocalToBuilder();
|
||||||
|
proto = viaProto ? proto : builder.build();
|
||||||
|
viaProto = true;
|
||||||
|
return proto;
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void maybeInitBuilder() {
|
||||||
|
if (builder == null || viaProto) {
|
||||||
|
builder = ResourceLocalizationSpecProto.newBuilder(proto);
|
||||||
|
}
|
||||||
|
viaProto = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mergeLocalToBuilder() {
|
||||||
|
ResourceLocalizationSpecProtoOrBuilder l = viaProto ? proto : builder;
|
||||||
|
if (this.resource != null
|
||||||
|
&& !(l.getResource()
|
||||||
|
.equals(((LocalResourcePBImpl) resource).getProto()))) {
|
||||||
|
maybeInitBuilder();
|
||||||
|
builder.setResource(((LocalResourcePBImpl) resource).getProto());
|
||||||
|
}
|
||||||
|
if (this.destinationDirectory != null
|
||||||
|
&& !(l.getDestinationDirectory()
|
||||||
|
.equals(((URLPBImpl) destinationDirectory).getProto()))) {
|
||||||
|
maybeInitBuilder();
|
||||||
|
builder.setDestinationDirectory(((URLPBImpl) destinationDirectory)
|
||||||
|
.getProto());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,18 +18,13 @@
|
||||||
package org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords;
|
package org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.apache.hadoop.yarn.server.nodemanager.api.*;
|
||||||
import org.apache.hadoop.yarn.api.records.LocalResource;
|
|
||||||
|
|
||||||
public interface LocalizerHeartbeatResponse {
|
public interface LocalizerHeartbeatResponse {
|
||||||
public LocalizerAction getLocalizerAction();
|
|
||||||
public List<LocalResource> getAllResources();
|
|
||||||
public LocalResource getLocalResource(int i);
|
|
||||||
|
|
||||||
|
public LocalizerAction getLocalizerAction();
|
||||||
public void setLocalizerAction(LocalizerAction action);
|
public void setLocalizerAction(LocalizerAction action);
|
||||||
|
|
||||||
public void addAllResources(List<LocalResource> resources);
|
public List<ResourceLocalizationSpec> getResourceSpecs();
|
||||||
public void addResource(LocalResource resource);
|
public void setResourceSpecs(List<ResourceLocalizationSpec> rsrcs);
|
||||||
public void removeResource(int index);
|
|
||||||
public void clearResources();
|
|
||||||
}
|
}
|
|
@ -21,13 +21,14 @@ import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.hadoop.yarn.api.records.LocalResource;
|
|
||||||
import org.apache.hadoop.yarn.api.records.ProtoBase;
|
import org.apache.hadoop.yarn.api.records.ProtoBase;
|
||||||
import org.apache.hadoop.yarn.api.records.impl.pb.LocalResourcePBImpl;
|
|
||||||
import org.apache.hadoop.yarn.proto.YarnProtos.LocalResourceProto;
|
|
||||||
import org.apache.hadoop.yarn.proto.YarnServerNodemanagerServiceProtos.LocalizerActionProto;
|
import org.apache.hadoop.yarn.proto.YarnServerNodemanagerServiceProtos.LocalizerActionProto;
|
||||||
import org.apache.hadoop.yarn.proto.YarnServerNodemanagerServiceProtos.LocalizerHeartbeatResponseProto;
|
import org.apache.hadoop.yarn.proto.YarnServerNodemanagerServiceProtos.LocalizerHeartbeatResponseProto;
|
||||||
import org.apache.hadoop.yarn.proto.YarnServerNodemanagerServiceProtos.LocalizerHeartbeatResponseProtoOrBuilder;
|
import org.apache.hadoop.yarn.proto.YarnServerNodemanagerServiceProtos.LocalizerHeartbeatResponseProtoOrBuilder;
|
||||||
|
import org.apache.hadoop.yarn.proto.YarnServerNodemanagerServiceProtos.ResourceLocalizationSpecProto;
|
||||||
|
import org.apache.hadoop.yarn.server.nodemanager.api.ResourceLocalizationSpec;
|
||||||
|
import org.apache.hadoop.yarn.server.nodemanager.api.impl.pb.ResourceLocalizationSpecPBImpl;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerAction;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerAction;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerHeartbeatResponse;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerHeartbeatResponse;
|
||||||
|
|
||||||
|
@ -40,13 +41,14 @@ public class LocalizerHeartbeatResponsePBImpl
|
||||||
LocalizerHeartbeatResponseProto.Builder builder = null;
|
LocalizerHeartbeatResponseProto.Builder builder = null;
|
||||||
boolean viaProto = false;
|
boolean viaProto = false;
|
||||||
|
|
||||||
private List<LocalResource> resources;
|
private List<ResourceLocalizationSpec> resourceSpecs;
|
||||||
|
|
||||||
public LocalizerHeartbeatResponsePBImpl() {
|
public LocalizerHeartbeatResponsePBImpl() {
|
||||||
builder = LocalizerHeartbeatResponseProto.newBuilder();
|
builder = LocalizerHeartbeatResponseProto.newBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalizerHeartbeatResponsePBImpl(LocalizerHeartbeatResponseProto proto) {
|
public LocalizerHeartbeatResponsePBImpl(
|
||||||
|
LocalizerHeartbeatResponseProto proto) {
|
||||||
this.proto = proto;
|
this.proto = proto;
|
||||||
viaProto = true;
|
viaProto = true;
|
||||||
}
|
}
|
||||||
|
@ -59,7 +61,7 @@ public class LocalizerHeartbeatResponsePBImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mergeLocalToBuilder() {
|
private void mergeLocalToBuilder() {
|
||||||
if (resources != null) {
|
if (resourceSpecs != null) {
|
||||||
addResourcesToProto();
|
addResourcesToProto();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,6 +81,7 @@ public class LocalizerHeartbeatResponsePBImpl
|
||||||
viaProto = false;
|
viaProto = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public LocalizerAction getLocalizerAction() {
|
public LocalizerAction getLocalizerAction() {
|
||||||
LocalizerHeartbeatResponseProtoOrBuilder p = viaProto ? proto : builder;
|
LocalizerHeartbeatResponseProtoOrBuilder p = viaProto ? proto : builder;
|
||||||
if (!p.hasAction()) {
|
if (!p.hasAction()) {
|
||||||
|
@ -87,14 +90,10 @@ public class LocalizerHeartbeatResponsePBImpl
|
||||||
return convertFromProtoFormat(p.getAction());
|
return convertFromProtoFormat(p.getAction());
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<LocalResource> getAllResources() {
|
@Override
|
||||||
|
public List<ResourceLocalizationSpec> getResourceSpecs() {
|
||||||
initResources();
|
initResources();
|
||||||
return this.resources;
|
return this.resourceSpecs;
|
||||||
}
|
|
||||||
|
|
||||||
public LocalResource getLocalResource(int i) {
|
|
||||||
initResources();
|
|
||||||
return this.resources.get(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLocalizerAction(LocalizerAction action) {
|
public void setLocalizerAction(LocalizerAction action) {
|
||||||
|
@ -106,31 +105,39 @@ public class LocalizerHeartbeatResponsePBImpl
|
||||||
builder.setAction(convertToProtoFormat(action));
|
builder.setAction(convertToProtoFormat(action));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setResourceSpecs(List<ResourceLocalizationSpec> rsrcs) {
|
||||||
|
maybeInitBuilder();
|
||||||
|
if (rsrcs == null) {
|
||||||
|
builder.clearResources();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.resourceSpecs = rsrcs;
|
||||||
|
}
|
||||||
|
|
||||||
private void initResources() {
|
private void initResources() {
|
||||||
if (this.resources != null) {
|
if (this.resourceSpecs != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LocalizerHeartbeatResponseProtoOrBuilder p = viaProto ? proto : builder;
|
LocalizerHeartbeatResponseProtoOrBuilder p = viaProto ? proto : builder;
|
||||||
List<LocalResourceProto> list = p.getResourcesList();
|
List<ResourceLocalizationSpecProto> list = p.getResourcesList();
|
||||||
this.resources = new ArrayList<LocalResource>();
|
this.resourceSpecs = new ArrayList<ResourceLocalizationSpec>();
|
||||||
|
for (ResourceLocalizationSpecProto c : list) {
|
||||||
for (LocalResourceProto c : list) {
|
this.resourceSpecs.add(convertFromProtoFormat(c));
|
||||||
this.resources.add(convertFromProtoFormat(c));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addResourcesToProto() {
|
private void addResourcesToProto() {
|
||||||
maybeInitBuilder();
|
maybeInitBuilder();
|
||||||
builder.clearResources();
|
builder.clearResources();
|
||||||
if (this.resources == null)
|
if (this.resourceSpecs == null)
|
||||||
return;
|
return;
|
||||||
Iterable<LocalResourceProto> iterable =
|
Iterable<ResourceLocalizationSpecProto> iterable =
|
||||||
new Iterable<LocalResourceProto>() {
|
new Iterable<ResourceLocalizationSpecProto>() {
|
||||||
@Override
|
@Override
|
||||||
public Iterator<LocalResourceProto> iterator() {
|
public Iterator<ResourceLocalizationSpecProto> iterator() {
|
||||||
return new Iterator<LocalResourceProto>() {
|
return new Iterator<ResourceLocalizationSpecProto>() {
|
||||||
|
|
||||||
Iterator<LocalResource> iter = resources.iterator();
|
Iterator<ResourceLocalizationSpec> iter = resourceSpecs.iterator();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
|
@ -138,8 +145,10 @@ public class LocalizerHeartbeatResponsePBImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocalResourceProto next() {
|
public ResourceLocalizationSpecProto next() {
|
||||||
return convertToProtoFormat(iter.next());
|
ResourceLocalizationSpec resource = iter.next();
|
||||||
|
|
||||||
|
return ((ResourceLocalizationSpecPBImpl)resource).getProto();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -154,34 +163,10 @@ public class LocalizerHeartbeatResponsePBImpl
|
||||||
builder.addAllResources(iterable);
|
builder.addAllResources(iterable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAllResources(List<LocalResource> resources) {
|
|
||||||
if (resources == null)
|
|
||||||
return;
|
|
||||||
initResources();
|
|
||||||
this.resources.addAll(resources);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addResource(LocalResource resource) {
|
private ResourceLocalizationSpec convertFromProtoFormat(
|
||||||
initResources();
|
ResourceLocalizationSpecProto p) {
|
||||||
this.resources.add(resource);
|
return new ResourceLocalizationSpecPBImpl(p);
|
||||||
}
|
|
||||||
|
|
||||||
public void removeResource(int index) {
|
|
||||||
initResources();
|
|
||||||
this.resources.remove(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearResources() {
|
|
||||||
initResources();
|
|
||||||
this.resources.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private LocalResource convertFromProtoFormat(LocalResourceProto p) {
|
|
||||||
return new LocalResourcePBImpl(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
private LocalResourceProto convertToProtoFormat(LocalResource s) {
|
|
||||||
return ((LocalResourcePBImpl)s).getProto();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalizerActionProto convertToProtoFormat(LocalizerAction a) {
|
private LocalizerActionProto convertToProtoFormat(LocalizerAction a) {
|
||||||
|
@ -191,5 +176,4 @@ public class LocalizerHeartbeatResponsePBImpl
|
||||||
private LocalizerAction convertFromProtoFormat(LocalizerActionProto a) {
|
private LocalizerAction convertFromProtoFormat(LocalizerActionProto a) {
|
||||||
return LocalizerAction.valueOf(a.name());
|
return LocalizerAction.valueOf(a.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -51,6 +51,7 @@ import org.apache.hadoop.security.Credentials;
|
||||||
import org.apache.hadoop.security.UserGroupInformation;
|
import org.apache.hadoop.security.UserGroupInformation;
|
||||||
import org.apache.hadoop.security.token.Token;
|
import org.apache.hadoop.security.token.Token;
|
||||||
import org.apache.hadoop.security.token.TokenIdentifier;
|
import org.apache.hadoop.security.token.TokenIdentifier;
|
||||||
|
import org.apache.hadoop.util.DiskChecker;
|
||||||
import org.apache.hadoop.yarn.YarnUncaughtExceptionHandler;
|
import org.apache.hadoop.yarn.YarnUncaughtExceptionHandler;
|
||||||
import org.apache.hadoop.yarn.api.records.LocalResource;
|
import org.apache.hadoop.yarn.api.records.LocalResource;
|
||||||
import org.apache.hadoop.yarn.exceptions.YarnRemoteException;
|
import org.apache.hadoop.yarn.exceptions.YarnRemoteException;
|
||||||
|
@ -59,6 +60,7 @@ import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
|
||||||
import org.apache.hadoop.yarn.ipc.RPCUtil;
|
import org.apache.hadoop.yarn.ipc.RPCUtil;
|
||||||
import org.apache.hadoop.yarn.ipc.YarnRPC;
|
import org.apache.hadoop.yarn.ipc.YarnRPC;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.LocalizationProtocol;
|
import org.apache.hadoop.yarn.server.nodemanager.api.LocalizationProtocol;
|
||||||
|
import org.apache.hadoop.yarn.server.nodemanager.api.ResourceLocalizationSpec;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalResourceStatus;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalResourceStatus;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerHeartbeatResponse;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerHeartbeatResponse;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerStatus;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerStatus;
|
||||||
|
@ -89,8 +91,6 @@ public class ContainerLocalizer {
|
||||||
private final String localizerId;
|
private final String localizerId;
|
||||||
private final FileContext lfs;
|
private final FileContext lfs;
|
||||||
private final Configuration conf;
|
private final Configuration conf;
|
||||||
private final LocalDirAllocator appDirs;
|
|
||||||
private final LocalDirAllocator userDirs;
|
|
||||||
private final RecordFactory recordFactory;
|
private final RecordFactory recordFactory;
|
||||||
private final Map<LocalResource,Future<Path>> pendingResources;
|
private final Map<LocalResource,Future<Path>> pendingResources;
|
||||||
private final String appCacheDirContextName;
|
private final String appCacheDirContextName;
|
||||||
|
@ -112,8 +112,6 @@ public class ContainerLocalizer {
|
||||||
this.recordFactory = recordFactory;
|
this.recordFactory = recordFactory;
|
||||||
this.conf = new Configuration();
|
this.conf = new Configuration();
|
||||||
this.appCacheDirContextName = String.format(APPCACHE_CTXT_FMT, appId);
|
this.appCacheDirContextName = String.format(APPCACHE_CTXT_FMT, appId);
|
||||||
this.appDirs = new LocalDirAllocator(appCacheDirContextName);
|
|
||||||
this.userDirs = new LocalDirAllocator(String.format(USERCACHE_CTXT_FMT, user));
|
|
||||||
this.pendingResources = new HashMap<LocalResource,Future<Path>>();
|
this.pendingResources = new HashMap<LocalResource,Future<Path>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,10 +195,10 @@ public class ContainerLocalizer {
|
||||||
return new ExecutorCompletionService<Path>(exec);
|
return new ExecutorCompletionService<Path>(exec);
|
||||||
}
|
}
|
||||||
|
|
||||||
Callable<Path> download(LocalDirAllocator lda, LocalResource rsrc,
|
Callable<Path> download(Path path, LocalResource rsrc,
|
||||||
UserGroupInformation ugi) throws IOException {
|
UserGroupInformation ugi) throws IOException {
|
||||||
Path destPath = lda.getLocalPathForWrite(".", getEstimatedSize(rsrc), conf);
|
DiskChecker.checkDir(new File(path.toUri().getRawPath()));
|
||||||
return new FSDownload(lfs, ugi, conf, destPath, rsrc, new Random());
|
return new FSDownload(lfs, ugi, conf, path, rsrc, new Random());
|
||||||
}
|
}
|
||||||
|
|
||||||
static long getEstimatedSize(LocalResource rsrc) {
|
static long getEstimatedSize(LocalResource rsrc) {
|
||||||
|
@ -238,25 +236,12 @@ public class ContainerLocalizer {
|
||||||
LocalizerHeartbeatResponse response = nodemanager.heartbeat(status);
|
LocalizerHeartbeatResponse response = nodemanager.heartbeat(status);
|
||||||
switch (response.getLocalizerAction()) {
|
switch (response.getLocalizerAction()) {
|
||||||
case LIVE:
|
case LIVE:
|
||||||
List<LocalResource> newResources = response.getAllResources();
|
List<ResourceLocalizationSpec> newRsrcs = response.getResourceSpecs();
|
||||||
for (LocalResource r : newResources) {
|
for (ResourceLocalizationSpec newRsrc : newRsrcs) {
|
||||||
if (!pendingResources.containsKey(r)) {
|
if (!pendingResources.containsKey(newRsrc.getResource())) {
|
||||||
final LocalDirAllocator lda;
|
pendingResources.put(newRsrc.getResource(), cs.submit(download(
|
||||||
switch (r.getVisibility()) {
|
new Path(newRsrc.getDestinationDirectory().getFile()),
|
||||||
default:
|
newRsrc.getResource(), ugi)));
|
||||||
LOG.warn("Unknown visibility: " + r.getVisibility()
|
|
||||||
+ ", Using userDirs");
|
|
||||||
//Falling back to userDirs for unknown visibility.
|
|
||||||
case PUBLIC:
|
|
||||||
case PRIVATE:
|
|
||||||
lda = userDirs;
|
|
||||||
break;
|
|
||||||
case APPLICATION:
|
|
||||||
lda = appDirs;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// TODO: Synchronization??
|
|
||||||
pendingResources.put(r, cs.submit(download(lda, r, ugi)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -22,8 +22,6 @@ import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.fs.Path;
|
import org.apache.hadoop.fs.Path;
|
||||||
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
||||||
|
|
|
@ -80,10 +80,12 @@ import org.apache.hadoop.yarn.server.nodemanager.ContainerExecutor;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.DeletionService;
|
import org.apache.hadoop.yarn.server.nodemanager.DeletionService;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.LocalDirsHandlerService;
|
import org.apache.hadoop.yarn.server.nodemanager.LocalDirsHandlerService;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.LocalizationProtocol;
|
import org.apache.hadoop.yarn.server.nodemanager.api.LocalizationProtocol;
|
||||||
|
import org.apache.hadoop.yarn.server.nodemanager.api.ResourceLocalizationSpec;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalResourceStatus;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalResourceStatus;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerAction;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerAction;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerHeartbeatResponse;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerHeartbeatResponse;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerStatus;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerStatus;
|
||||||
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.ResourceStatusType;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.Application;
|
import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.Application;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.ApplicationEvent;
|
import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.ApplicationEvent;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.ApplicationEventType;
|
import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.ApplicationEventType;
|
||||||
|
@ -105,6 +107,7 @@ import org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.even
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.event.ResourceRequestEvent;
|
import org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.event.ResourceRequestEvent;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.security.LocalizerTokenSecretManager;
|
import org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.security.LocalizerTokenSecretManager;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.security.authorize.NMPolicyProvider;
|
import org.apache.hadoop.yarn.server.nodemanager.security.authorize.NMPolicyProvider;
|
||||||
|
import org.apache.hadoop.yarn.server.nodemanager.util.NodeManagerBuilderUtils;
|
||||||
import org.apache.hadoop.yarn.service.AbstractService;
|
import org.apache.hadoop.yarn.service.AbstractService;
|
||||||
import org.apache.hadoop.yarn.service.CompositeService;
|
import org.apache.hadoop.yarn.service.CompositeService;
|
||||||
import org.apache.hadoop.yarn.util.ConverterUtils;
|
import org.apache.hadoop.yarn.util.ConverterUtils;
|
||||||
|
@ -326,7 +329,7 @@ public class ResourceLocalizationService extends CompositeService
|
||||||
// 0) Create application tracking structs
|
// 0) Create application tracking structs
|
||||||
String userName = app.getUser();
|
String userName = app.getUser();
|
||||||
privateRsrc.putIfAbsent(userName, new LocalResourcesTrackerImpl(userName,
|
privateRsrc.putIfAbsent(userName, new LocalResourcesTrackerImpl(userName,
|
||||||
dispatcher, false, super.getConfig()));
|
dispatcher, true, super.getConfig()));
|
||||||
if (null != appRsrc.putIfAbsent(
|
if (null != appRsrc.putIfAbsent(
|
||||||
ConverterUtils.toString(app.getAppId()),
|
ConverterUtils.toString(app.getAppId()),
|
||||||
new LocalResourcesTrackerImpl(app.getUser(), dispatcher, false, super
|
new LocalResourcesTrackerImpl(app.getUser(), dispatcher, false, super
|
||||||
|
@ -476,6 +479,21 @@ public class ResourceLocalizationService extends CompositeService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getUserFileCachePath(String user) {
|
||||||
|
String path =
|
||||||
|
"." + Path.SEPARATOR + ContainerLocalizer.USERCACHE + Path.SEPARATOR
|
||||||
|
+ user + Path.SEPARATOR + ContainerLocalizer.FILECACHE;
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getUserAppCachePath(String user, String appId) {
|
||||||
|
String path =
|
||||||
|
"." + Path.SEPARATOR + ContainerLocalizer.USERCACHE + Path.SEPARATOR
|
||||||
|
+ user + Path.SEPARATOR + ContainerLocalizer.APPCACHE
|
||||||
|
+ Path.SEPARATOR + appId;
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sub-component handling the spawning of {@link ContainerLocalizer}s
|
* Sub-component handling the spawning of {@link ContainerLocalizer}s
|
||||||
*/
|
*/
|
||||||
|
@ -803,7 +821,20 @@ public class ResourceLocalizationService extends CompositeService
|
||||||
LocalResource next = findNextResource();
|
LocalResource next = findNextResource();
|
||||||
if (next != null) {
|
if (next != null) {
|
||||||
response.setLocalizerAction(LocalizerAction.LIVE);
|
response.setLocalizerAction(LocalizerAction.LIVE);
|
||||||
response.addResource(next);
|
try {
|
||||||
|
ArrayList<ResourceLocalizationSpec> rsrcs =
|
||||||
|
new ArrayList<ResourceLocalizationSpec>();
|
||||||
|
ResourceLocalizationSpec rsrc =
|
||||||
|
NodeManagerBuilderUtils.newResourceLocalizationSpec(next,
|
||||||
|
getPathForLocalization(next));
|
||||||
|
rsrcs.add(rsrc);
|
||||||
|
response.setResourceSpecs(rsrcs);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.error("local path for PRIVATE localization could not be found."
|
||||||
|
+ "Disks might have failed.", e);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
// TODO fail? Already translated several times...
|
||||||
|
}
|
||||||
} else if (pending.isEmpty()) {
|
} else if (pending.isEmpty()) {
|
||||||
// TODO: Synchronization
|
// TODO: Synchronization
|
||||||
response.setLocalizerAction(LocalizerAction.DIE);
|
response.setLocalizerAction(LocalizerAction.DIE);
|
||||||
|
@ -812,7 +843,8 @@ public class ResourceLocalizationService extends CompositeService
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
ArrayList<ResourceLocalizationSpec> rsrcs =
|
||||||
|
new ArrayList<ResourceLocalizationSpec>();
|
||||||
for (LocalResourceStatus stat : remoteResourceStatuses) {
|
for (LocalResourceStatus stat : remoteResourceStatuses) {
|
||||||
LocalResource rsrc = stat.getResource();
|
LocalResource rsrc = stat.getResource();
|
||||||
LocalResourceRequest req = null;
|
LocalResourceRequest req = null;
|
||||||
|
@ -835,6 +867,7 @@ public class ResourceLocalizationService extends CompositeService
|
||||||
new ResourceLocalizedEvent(req,
|
new ResourceLocalizedEvent(req,
|
||||||
ConverterUtils.getPathFromYarnURL(stat.getLocalPath()),
|
ConverterUtils.getPathFromYarnURL(stat.getLocalPath()),
|
||||||
stat.getLocalSize()));
|
stat.getLocalSize()));
|
||||||
|
localizationCompleted(stat);
|
||||||
} catch (URISyntaxException e) { }
|
} catch (URISyntaxException e) { }
|
||||||
if (pending.isEmpty()) {
|
if (pending.isEmpty()) {
|
||||||
// TODO: Synchronization
|
// TODO: Synchronization
|
||||||
|
@ -844,7 +877,17 @@ public class ResourceLocalizationService extends CompositeService
|
||||||
response.setLocalizerAction(LocalizerAction.LIVE);
|
response.setLocalizerAction(LocalizerAction.LIVE);
|
||||||
LocalResource next = findNextResource();
|
LocalResource next = findNextResource();
|
||||||
if (next != null) {
|
if (next != null) {
|
||||||
response.addResource(next);
|
try {
|
||||||
|
ResourceLocalizationSpec resource =
|
||||||
|
NodeManagerBuilderUtils.newResourceLocalizationSpec(next,
|
||||||
|
getPathForLocalization(next));
|
||||||
|
rsrcs.add(resource);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.error("local path for PRIVATE localization could not be " +
|
||||||
|
"found. Disks might have failed.", e);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
//TODO fail? Already translated several times...
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FETCH_PENDING:
|
case FETCH_PENDING:
|
||||||
|
@ -854,6 +897,7 @@ public class ResourceLocalizationService extends CompositeService
|
||||||
LOG.info("DEBUG: FAILED " + req, stat.getException());
|
LOG.info("DEBUG: FAILED " + req, stat.getException());
|
||||||
assoc.getResource().unlock();
|
assoc.getResource().unlock();
|
||||||
response.setLocalizerAction(LocalizerAction.DIE);
|
response.setLocalizerAction(LocalizerAction.DIE);
|
||||||
|
localizationCompleted(stat);
|
||||||
// TODO: Why is this event going directly to the container. Why not
|
// TODO: Why is this event going directly to the container. Why not
|
||||||
// the resource itself? What happens to the resource? Is it removed?
|
// the resource itself? What happens to the resource? Is it removed?
|
||||||
dispatcher.getEventHandler().handle(
|
dispatcher.getEventHandler().handle(
|
||||||
|
@ -869,9 +913,53 @@ public class ResourceLocalizationService extends CompositeService
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
response.setResourceSpecs(rsrcs);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void localizationCompleted(LocalResourceStatus stat) {
|
||||||
|
try {
|
||||||
|
LocalResource rsrc = stat.getResource();
|
||||||
|
LocalResourceRequest key = new LocalResourceRequest(rsrc);
|
||||||
|
String user = context.getUser();
|
||||||
|
ApplicationId appId =
|
||||||
|
context.getContainerId().getApplicationAttemptId()
|
||||||
|
.getApplicationId();
|
||||||
|
LocalResourceVisibility vis = rsrc.getVisibility();
|
||||||
|
LocalResourcesTracker tracker =
|
||||||
|
getLocalResourcesTracker(vis, user, appId);
|
||||||
|
if (stat.getStatus() == ResourceStatusType.FETCH_SUCCESS) {
|
||||||
|
tracker.localizationCompleted(key, true);
|
||||||
|
} else {
|
||||||
|
tracker.localizationCompleted(key, false);
|
||||||
|
}
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
LOG.error("Invalid resource URL specified", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path getPathForLocalization(LocalResource rsrc) throws IOException,
|
||||||
|
URISyntaxException {
|
||||||
|
String user = context.getUser();
|
||||||
|
ApplicationId appId =
|
||||||
|
context.getContainerId().getApplicationAttemptId().getApplicationId();
|
||||||
|
LocalResourceVisibility vis = rsrc.getVisibility();
|
||||||
|
LocalResourcesTracker tracker =
|
||||||
|
getLocalResourcesTracker(vis, user, appId);
|
||||||
|
String cacheDirectory = null;
|
||||||
|
if (vis == LocalResourceVisibility.PRIVATE) {// PRIVATE Only
|
||||||
|
cacheDirectory = getUserFileCachePath(user);
|
||||||
|
} else {// APPLICATION ONLY
|
||||||
|
cacheDirectory = getUserAppCachePath(user, appId.toString());
|
||||||
|
}
|
||||||
|
Path dirPath =
|
||||||
|
dirsHandler.getLocalPathForWrite(cacheDirectory,
|
||||||
|
ContainerLocalizer.getEstimatedSize(rsrc), false);
|
||||||
|
return tracker.getPathForLocalization(new LocalResourceRequest(rsrc),
|
||||||
|
dirPath);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked") // dispatcher not typed
|
@SuppressWarnings("unchecked") // dispatcher not typed
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/**
|
||||||
|
* 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.yarn.server.nodemanager.util;
|
||||||
|
|
||||||
|
import org.apache.hadoop.fs.Path;
|
||||||
|
import org.apache.hadoop.yarn.api.records.LocalResource;
|
||||||
|
import org.apache.hadoop.yarn.api.records.URL;
|
||||||
|
import org.apache.hadoop.yarn.server.nodemanager.api.ResourceLocalizationSpec;
|
||||||
|
import org.apache.hadoop.yarn.util.ConverterUtils;
|
||||||
|
import org.apache.hadoop.yarn.util.Records;
|
||||||
|
|
||||||
|
public class NodeManagerBuilderUtils {
|
||||||
|
|
||||||
|
public static ResourceLocalizationSpec newResourceLocalizationSpec(
|
||||||
|
LocalResource rsrc, Path path) {
|
||||||
|
URL local = ConverterUtils.getYarnUrlFromPath(path);
|
||||||
|
ResourceLocalizationSpec resourceLocalizationSpec =
|
||||||
|
Records.newRecord(ResourceLocalizationSpec.class);
|
||||||
|
resourceLocalizationSpec.setDestinationDirectory(local);
|
||||||
|
resourceLocalizationSpec.setResource(rsrc);
|
||||||
|
return resourceLocalizationSpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -47,7 +47,12 @@ enum LocalizerActionProto {
|
||||||
DIE = 2;
|
DIE = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ResourceLocalizationSpecProto {
|
||||||
|
optional LocalResourceProto resource = 1;
|
||||||
|
optional URLProto destination_directory = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message LocalizerHeartbeatResponseProto {
|
message LocalizerHeartbeatResponseProto {
|
||||||
optional LocalizerActionProto action = 1;
|
optional LocalizerActionProto action = 1;
|
||||||
repeated LocalResourceProto resources = 2;
|
repeated ResourceLocalizationSpecProto resources = 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,13 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.impl.pb;
|
package org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.impl.pb;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.fs.Path;
|
import org.apache.hadoop.fs.Path;
|
||||||
import org.apache.hadoop.io.DataInputBuffer;
|
import org.apache.hadoop.io.DataInputBuffer;
|
||||||
|
@ -31,15 +38,14 @@ import org.apache.hadoop.yarn.ipc.RPCUtil;
|
||||||
import org.apache.hadoop.yarn.proto.YarnServerNodemanagerServiceProtos.LocalResourceStatusProto;
|
import org.apache.hadoop.yarn.proto.YarnServerNodemanagerServiceProtos.LocalResourceStatusProto;
|
||||||
import org.apache.hadoop.yarn.proto.YarnServerNodemanagerServiceProtos.LocalizerHeartbeatResponseProto;
|
import org.apache.hadoop.yarn.proto.YarnServerNodemanagerServiceProtos.LocalizerHeartbeatResponseProto;
|
||||||
import org.apache.hadoop.yarn.proto.YarnServerNodemanagerServiceProtos.LocalizerStatusProto;
|
import org.apache.hadoop.yarn.proto.YarnServerNodemanagerServiceProtos.LocalizerStatusProto;
|
||||||
|
import org.apache.hadoop.yarn.server.nodemanager.api.ResourceLocalizationSpec;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalResourceStatus;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalResourceStatus;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerAction;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerAction;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerHeartbeatResponse;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerHeartbeatResponse;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerStatus;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerStatus;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.ResourceStatusType;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.ResourceStatusType;
|
||||||
import org.apache.hadoop.yarn.util.ConverterUtils;
|
import org.apache.hadoop.yarn.util.ConverterUtils;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
public class TestPBRecordImpl {
|
public class TestPBRecordImpl {
|
||||||
|
|
||||||
|
@ -54,9 +60,8 @@ public class TestPBRecordImpl {
|
||||||
static LocalResource createResource() {
|
static LocalResource createResource() {
|
||||||
LocalResource ret = recordFactory.newRecordInstance(LocalResource.class);
|
LocalResource ret = recordFactory.newRecordInstance(LocalResource.class);
|
||||||
assertTrue(ret instanceof LocalResourcePBImpl);
|
assertTrue(ret instanceof LocalResourcePBImpl);
|
||||||
ret.setResource(
|
ret.setResource(ConverterUtils.getYarnUrlFromPath(new Path(
|
||||||
ConverterUtils.getYarnUrlFromPath(
|
"hdfs://y.ak:8020/foo/bar")));
|
||||||
new Path("hdfs://y.ak:8020/foo/bar")));
|
|
||||||
ret.setSize(4344L);
|
ret.setSize(4344L);
|
||||||
ret.setTimestamp(3141592653589793L);
|
ret.setTimestamp(3141592653589793L);
|
||||||
ret.setVisibility(LocalResourceVisibility.PUBLIC);
|
ret.setVisibility(LocalResourceVisibility.PUBLIC);
|
||||||
|
@ -90,16 +95,27 @@ public class TestPBRecordImpl {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LocalizerHeartbeatResponse createLocalizerHeartbeatResponse() {
|
static LocalizerHeartbeatResponse createLocalizerHeartbeatResponse()
|
||||||
|
throws URISyntaxException {
|
||||||
LocalizerHeartbeatResponse ret =
|
LocalizerHeartbeatResponse ret =
|
||||||
recordFactory.newRecordInstance(LocalizerHeartbeatResponse.class);
|
recordFactory.newRecordInstance(LocalizerHeartbeatResponse.class);
|
||||||
assertTrue(ret instanceof LocalizerHeartbeatResponsePBImpl);
|
assertTrue(ret instanceof LocalizerHeartbeatResponsePBImpl);
|
||||||
ret.setLocalizerAction(LocalizerAction.LIVE);
|
ret.setLocalizerAction(LocalizerAction.LIVE);
|
||||||
ret.addResource(createResource());
|
LocalResource rsrc = createResource();
|
||||||
|
ArrayList<ResourceLocalizationSpec> rsrcs =
|
||||||
|
new ArrayList<ResourceLocalizationSpec>();
|
||||||
|
ResourceLocalizationSpec resource =
|
||||||
|
recordFactory.newRecordInstance(ResourceLocalizationSpec.class);
|
||||||
|
resource.setResource(rsrc);
|
||||||
|
resource.setDestinationDirectory(ConverterUtils
|
||||||
|
.getYarnUrlFromPath(new Path("/tmp" + System.currentTimeMillis())));
|
||||||
|
rsrcs.add(resource);
|
||||||
|
ret.setResourceSpecs(rsrcs);
|
||||||
|
System.out.println(resource);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(timeout=10000)
|
||||||
public void testLocalResourceStatusSerDe() throws Exception {
|
public void testLocalResourceStatusSerDe() throws Exception {
|
||||||
LocalResourceStatus rsrcS = createLocalResourceStatus();
|
LocalResourceStatus rsrcS = createLocalResourceStatus();
|
||||||
assertTrue(rsrcS instanceof LocalResourceStatusPBImpl);
|
assertTrue(rsrcS instanceof LocalResourceStatusPBImpl);
|
||||||
|
@ -119,7 +135,7 @@ public class TestPBRecordImpl {
|
||||||
assertEquals(createResource(), rsrcD.getResource());
|
assertEquals(createResource(), rsrcD.getResource());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(timeout=10000)
|
||||||
public void testLocalizerStatusSerDe() throws Exception {
|
public void testLocalizerStatusSerDe() throws Exception {
|
||||||
LocalizerStatus rsrcS = createLocalizerStatus();
|
LocalizerStatus rsrcS = createLocalizerStatus();
|
||||||
assertTrue(rsrcS instanceof LocalizerStatusPBImpl);
|
assertTrue(rsrcS instanceof LocalizerStatusPBImpl);
|
||||||
|
@ -141,7 +157,7 @@ public class TestPBRecordImpl {
|
||||||
assertEquals(createLocalResourceStatus(), rsrcD.getResourceStatus(0));
|
assertEquals(createLocalResourceStatus(), rsrcD.getResourceStatus(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(timeout=10000)
|
||||||
public void testLocalizerHeartbeatResponseSerDe() throws Exception {
|
public void testLocalizerHeartbeatResponseSerDe() throws Exception {
|
||||||
LocalizerHeartbeatResponse rsrcS = createLocalizerHeartbeatResponse();
|
LocalizerHeartbeatResponse rsrcS = createLocalizerHeartbeatResponse();
|
||||||
assertTrue(rsrcS instanceof LocalizerHeartbeatResponsePBImpl);
|
assertTrue(rsrcS instanceof LocalizerHeartbeatResponsePBImpl);
|
||||||
|
@ -158,8 +174,8 @@ public class TestPBRecordImpl {
|
||||||
new LocalizerHeartbeatResponsePBImpl(rsrcPbD);
|
new LocalizerHeartbeatResponsePBImpl(rsrcPbD);
|
||||||
|
|
||||||
assertEquals(rsrcS, rsrcD);
|
assertEquals(rsrcS, rsrcD);
|
||||||
assertEquals(createResource(), rsrcS.getLocalResource(0));
|
assertEquals(createResource(), rsrcS.getResourceSpecs().get(0).getResource());
|
||||||
assertEquals(createResource(), rsrcD.getLocalResource(0));
|
assertEquals(createResource(), rsrcD.getResourceSpecs().get(0).getResource());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ package org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.hadoop.yarn.api.records.LocalResource;
|
import org.apache.hadoop.yarn.server.nodemanager.api.ResourceLocalizationSpec;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerAction;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerAction;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerHeartbeatResponse;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerHeartbeatResponse;
|
||||||
|
|
||||||
|
@ -28,28 +28,30 @@ public class MockLocalizerHeartbeatResponse
|
||||||
implements LocalizerHeartbeatResponse {
|
implements LocalizerHeartbeatResponse {
|
||||||
|
|
||||||
LocalizerAction action;
|
LocalizerAction action;
|
||||||
List<LocalResource> rsrc;
|
List<ResourceLocalizationSpec> resourceSpecs;
|
||||||
|
|
||||||
MockLocalizerHeartbeatResponse() {
|
MockLocalizerHeartbeatResponse() {
|
||||||
rsrc = new ArrayList<LocalResource>();
|
resourceSpecs = new ArrayList<ResourceLocalizationSpec>();
|
||||||
}
|
}
|
||||||
|
|
||||||
MockLocalizerHeartbeatResponse(
|
MockLocalizerHeartbeatResponse(
|
||||||
LocalizerAction action, List<LocalResource> rsrc) {
|
LocalizerAction action, List<ResourceLocalizationSpec> resources) {
|
||||||
this.action = action;
|
this.action = action;
|
||||||
this.rsrc = rsrc;
|
this.resourceSpecs = resources;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalizerAction getLocalizerAction() { return action; }
|
public LocalizerAction getLocalizerAction() { return action; }
|
||||||
public List<LocalResource> getAllResources() { return rsrc; }
|
|
||||||
public LocalResource getLocalResource(int i) { return rsrc.get(i); }
|
|
||||||
public void setLocalizerAction(LocalizerAction action) {
|
public void setLocalizerAction(LocalizerAction action) {
|
||||||
this.action = action;
|
this.action = action;
|
||||||
}
|
}
|
||||||
public void addAllResources(List<LocalResource> resources) {
|
|
||||||
rsrc.addAll(resources);
|
@Override
|
||||||
|
public List<ResourceLocalizationSpec> getResourceSpecs() {
|
||||||
|
return resourceSpecs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setResourceSpecs(List<ResourceLocalizationSpec> resourceSpecs) {
|
||||||
|
this.resourceSpecs = resourceSpecs;
|
||||||
}
|
}
|
||||||
public void addResource(LocalResource resource) { rsrc.add(resource); }
|
|
||||||
public void removeResource(int index) { rsrc.remove(index); }
|
|
||||||
public void clearResources() { rsrc.clear(); }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,6 @@ import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.fs.AbstractFileSystem;
|
import org.apache.hadoop.fs.AbstractFileSystem;
|
||||||
import org.apache.hadoop.fs.FSDataInputStream;
|
import org.apache.hadoop.fs.FSDataInputStream;
|
||||||
import org.apache.hadoop.fs.FileContext;
|
import org.apache.hadoop.fs.FileContext;
|
||||||
import org.apache.hadoop.fs.LocalDirAllocator;
|
|
||||||
import org.apache.hadoop.fs.Path;
|
import org.apache.hadoop.fs.Path;
|
||||||
import org.apache.hadoop.fs.permission.FsPermission;
|
import org.apache.hadoop.fs.permission.FsPermission;
|
||||||
import org.apache.hadoop.io.DataInputBuffer;
|
import org.apache.hadoop.io.DataInputBuffer;
|
||||||
|
@ -66,9 +65,11 @@ import org.apache.hadoop.yarn.api.records.LocalResourceVisibility;
|
||||||
import org.apache.hadoop.yarn.api.records.URL;
|
import org.apache.hadoop.yarn.api.records.URL;
|
||||||
import org.apache.hadoop.yarn.factories.RecordFactory;
|
import org.apache.hadoop.yarn.factories.RecordFactory;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.LocalizationProtocol;
|
import org.apache.hadoop.yarn.server.nodemanager.api.LocalizationProtocol;
|
||||||
|
import org.apache.hadoop.yarn.server.nodemanager.api.ResourceLocalizationSpec;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalResourceStatus;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalResourceStatus;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerAction;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerAction;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerStatus;
|
import org.apache.hadoop.yarn.server.nodemanager.api.protocolrecords.LocalizerStatus;
|
||||||
|
import org.apache.hadoop.yarn.util.ConverterUtils;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.ArgumentMatcher;
|
import org.mockito.ArgumentMatcher;
|
||||||
import org.mockito.invocation.InvocationOnMock;
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
|
@ -95,12 +96,33 @@ public class TestContainerLocalizer {
|
||||||
public void testContainerLocalizerMain() throws Exception {
|
public void testContainerLocalizerMain() throws Exception {
|
||||||
ContainerLocalizer localizer = setupContainerLocalizerForTest();
|
ContainerLocalizer localizer = setupContainerLocalizerForTest();
|
||||||
|
|
||||||
|
// verify created cache
|
||||||
|
List<Path> privCacheList = new ArrayList<Path>();
|
||||||
|
List<Path> appCacheList = new ArrayList<Path>();
|
||||||
|
for (Path p : localDirs) {
|
||||||
|
Path base = new Path(new Path(p, ContainerLocalizer.USERCACHE), appUser);
|
||||||
|
Path privcache = new Path(base, ContainerLocalizer.FILECACHE);
|
||||||
|
privCacheList.add(privcache);
|
||||||
|
Path appDir =
|
||||||
|
new Path(base, new Path(ContainerLocalizer.APPCACHE, appId));
|
||||||
|
Path appcache = new Path(appDir, ContainerLocalizer.FILECACHE);
|
||||||
|
appCacheList.add(appcache);
|
||||||
|
}
|
||||||
|
|
||||||
// mock heartbeat responses from NM
|
// mock heartbeat responses from NM
|
||||||
LocalResource rsrcA = getMockRsrc(random, LocalResourceVisibility.PRIVATE);
|
ResourceLocalizationSpec rsrcA =
|
||||||
LocalResource rsrcB = getMockRsrc(random, LocalResourceVisibility.PRIVATE);
|
getMockRsrc(random, LocalResourceVisibility.PRIVATE,
|
||||||
LocalResource rsrcC = getMockRsrc(random,
|
privCacheList.get(0));
|
||||||
LocalResourceVisibility.APPLICATION);
|
ResourceLocalizationSpec rsrcB =
|
||||||
LocalResource rsrcD = getMockRsrc(random, LocalResourceVisibility.PRIVATE);
|
getMockRsrc(random, LocalResourceVisibility.PRIVATE,
|
||||||
|
privCacheList.get(0));
|
||||||
|
ResourceLocalizationSpec rsrcC =
|
||||||
|
getMockRsrc(random, LocalResourceVisibility.APPLICATION,
|
||||||
|
appCacheList.get(0));
|
||||||
|
ResourceLocalizationSpec rsrcD =
|
||||||
|
getMockRsrc(random, LocalResourceVisibility.PRIVATE,
|
||||||
|
privCacheList.get(0));
|
||||||
|
|
||||||
when(nmProxy.heartbeat(isA(LocalizerStatus.class)))
|
when(nmProxy.heartbeat(isA(LocalizerStatus.class)))
|
||||||
.thenReturn(new MockLocalizerHeartbeatResponse(LocalizerAction.LIVE,
|
.thenReturn(new MockLocalizerHeartbeatResponse(LocalizerAction.LIVE,
|
||||||
Collections.singletonList(rsrcA)))
|
Collections.singletonList(rsrcA)))
|
||||||
|
@ -111,27 +133,33 @@ public class TestContainerLocalizer {
|
||||||
.thenReturn(new MockLocalizerHeartbeatResponse(LocalizerAction.LIVE,
|
.thenReturn(new MockLocalizerHeartbeatResponse(LocalizerAction.LIVE,
|
||||||
Collections.singletonList(rsrcD)))
|
Collections.singletonList(rsrcD)))
|
||||||
.thenReturn(new MockLocalizerHeartbeatResponse(LocalizerAction.LIVE,
|
.thenReturn(new MockLocalizerHeartbeatResponse(LocalizerAction.LIVE,
|
||||||
Collections.<LocalResource>emptyList()))
|
Collections.<ResourceLocalizationSpec>emptyList()))
|
||||||
.thenReturn(new MockLocalizerHeartbeatResponse(LocalizerAction.DIE,
|
.thenReturn(new MockLocalizerHeartbeatResponse(LocalizerAction.DIE,
|
||||||
null));
|
null));
|
||||||
|
|
||||||
doReturn(new FakeDownload(rsrcA.getResource().getFile(), true)).when(
|
LocalResource tRsrcA = rsrcA.getResource();
|
||||||
localizer).download(isA(LocalDirAllocator.class), eq(rsrcA),
|
LocalResource tRsrcB = rsrcB.getResource();
|
||||||
|
LocalResource tRsrcC = rsrcC.getResource();
|
||||||
|
LocalResource tRsrcD = rsrcD.getResource();
|
||||||
|
doReturn(
|
||||||
|
new FakeDownload(rsrcA.getResource().getResource().getFile(), true))
|
||||||
|
.when(localizer).download(isA(Path.class), eq(tRsrcA),
|
||||||
isA(UserGroupInformation.class));
|
isA(UserGroupInformation.class));
|
||||||
doReturn(new FakeDownload(rsrcB.getResource().getFile(), true)).when(
|
doReturn(
|
||||||
localizer).download(isA(LocalDirAllocator.class), eq(rsrcB),
|
new FakeDownload(rsrcB.getResource().getResource().getFile(), true))
|
||||||
|
.when(localizer).download(isA(Path.class), eq(tRsrcB),
|
||||||
isA(UserGroupInformation.class));
|
isA(UserGroupInformation.class));
|
||||||
doReturn(new FakeDownload(rsrcC.getResource().getFile(), true)).when(
|
doReturn(
|
||||||
localizer).download(isA(LocalDirAllocator.class), eq(rsrcC),
|
new FakeDownload(rsrcC.getResource().getResource().getFile(), true))
|
||||||
|
.when(localizer).download(isA(Path.class), eq(tRsrcC),
|
||||||
isA(UserGroupInformation.class));
|
isA(UserGroupInformation.class));
|
||||||
doReturn(new FakeDownload(rsrcD.getResource().getFile(), true)).when(
|
doReturn(
|
||||||
localizer).download(isA(LocalDirAllocator.class), eq(rsrcD),
|
new FakeDownload(rsrcD.getResource().getResource().getFile(), true))
|
||||||
|
.when(localizer).download(isA(Path.class), eq(tRsrcD),
|
||||||
isA(UserGroupInformation.class));
|
isA(UserGroupInformation.class));
|
||||||
|
|
||||||
// run localization
|
// run localization
|
||||||
assertEquals(0, localizer.runLocalization(nmAddr));
|
assertEquals(0, localizer.runLocalization(nmAddr));
|
||||||
|
|
||||||
// verify created cache
|
|
||||||
for (Path p : localDirs) {
|
for (Path p : localDirs) {
|
||||||
Path base = new Path(new Path(p, ContainerLocalizer.USERCACHE), appUser);
|
Path base = new Path(new Path(p, ContainerLocalizer.USERCACHE), appUser);
|
||||||
Path privcache = new Path(base, ContainerLocalizer.FILECACHE);
|
Path privcache = new Path(base, ContainerLocalizer.FILECACHE);
|
||||||
|
@ -147,15 +175,14 @@ public class TestContainerLocalizer {
|
||||||
Path appcacheAfsPath = new Path(appcache.toUri().getPath());
|
Path appcacheAfsPath = new Path(appcache.toUri().getPath());
|
||||||
verify(spylfs).mkdir(eq(appcacheAfsPath), isA(FsPermission.class), eq(false));
|
verify(spylfs).mkdir(eq(appcacheAfsPath), isA(FsPermission.class), eq(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify tokens read at expected location
|
// verify tokens read at expected location
|
||||||
verify(spylfs).open(tokenPath);
|
verify(spylfs).open(tokenPath);
|
||||||
|
|
||||||
// verify downloaded resources reported to NM
|
// verify downloaded resources reported to NM
|
||||||
verify(nmProxy).heartbeat(argThat(new HBMatches(rsrcA)));
|
verify(nmProxy).heartbeat(argThat(new HBMatches(rsrcA.getResource())));
|
||||||
verify(nmProxy).heartbeat(argThat(new HBMatches(rsrcB)));
|
verify(nmProxy).heartbeat(argThat(new HBMatches(rsrcB.getResource())));
|
||||||
verify(nmProxy).heartbeat(argThat(new HBMatches(rsrcC)));
|
verify(nmProxy).heartbeat(argThat(new HBMatches(rsrcC.getResource())));
|
||||||
verify(nmProxy).heartbeat(argThat(new HBMatches(rsrcD)));
|
verify(nmProxy).heartbeat(argThat(new HBMatches(rsrcD.getResource())));
|
||||||
|
|
||||||
// verify all HB use localizerID provided
|
// verify all HB use localizerID provided
|
||||||
verify(nmProxy, never()).heartbeat(argThat(
|
verify(nmProxy, never()).heartbeat(argThat(
|
||||||
|
@ -310,10 +337,12 @@ public class TestContainerLocalizer {
|
||||||
return mockRF;
|
return mockRF;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LocalResource getMockRsrc(Random r,
|
static ResourceLocalizationSpec getMockRsrc(Random r,
|
||||||
LocalResourceVisibility vis) {
|
LocalResourceVisibility vis, Path p) {
|
||||||
LocalResource rsrc = mock(LocalResource.class);
|
ResourceLocalizationSpec resourceLocalizationSpec =
|
||||||
|
mock(ResourceLocalizationSpec.class);
|
||||||
|
|
||||||
|
LocalResource rsrc = mock(LocalResource.class);
|
||||||
String name = Long.toHexString(r.nextLong());
|
String name = Long.toHexString(r.nextLong());
|
||||||
URL uri = mock(org.apache.hadoop.yarn.api.records.URL.class);
|
URL uri = mock(org.apache.hadoop.yarn.api.records.URL.class);
|
||||||
when(uri.getScheme()).thenReturn("file");
|
when(uri.getScheme()).thenReturn("file");
|
||||||
|
@ -326,7 +355,10 @@ public class TestContainerLocalizer {
|
||||||
when(rsrc.getType()).thenReturn(LocalResourceType.FILE);
|
when(rsrc.getType()).thenReturn(LocalResourceType.FILE);
|
||||||
when(rsrc.getVisibility()).thenReturn(vis);
|
when(rsrc.getVisibility()).thenReturn(vis);
|
||||||
|
|
||||||
return rsrc;
|
when(resourceLocalizationSpec.getResource()).thenReturn(rsrc);
|
||||||
|
when(resourceLocalizationSpec.getDestinationDirectory()).
|
||||||
|
thenReturn(ConverterUtils.getYarnUrlFromPath(p));
|
||||||
|
return resourceLocalizationSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
package org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer;
|
package org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Matchers.anyBoolean;
|
import static org.mockito.Matchers.anyBoolean;
|
||||||
import static org.mockito.Matchers.anyInt;
|
import static org.mockito.Matchers.anyInt;
|
||||||
import static org.mockito.Matchers.anyLong;
|
import static org.mockito.Matchers.anyLong;
|
||||||
|
@ -35,6 +36,7 @@ import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.timeout;
|
import static org.mockito.Mockito.timeout;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
@ -375,7 +377,7 @@ public class TestResourceLocalizationService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test( timeout = 10000)
|
||||||
@SuppressWarnings("unchecked") // mocked generics
|
@SuppressWarnings("unchecked") // mocked generics
|
||||||
public void testLocalizationHeartbeat() throws Exception {
|
public void testLocalizationHeartbeat() throws Exception {
|
||||||
Configuration conf = new YarnConfiguration();
|
Configuration conf = new YarnConfiguration();
|
||||||
|
@ -386,12 +388,17 @@ public class TestResourceLocalizationService {
|
||||||
isA(Path.class), isA(FsPermission.class), anyBoolean());
|
isA(Path.class), isA(FsPermission.class), anyBoolean());
|
||||||
|
|
||||||
List<Path> localDirs = new ArrayList<Path>();
|
List<Path> localDirs = new ArrayList<Path>();
|
||||||
String[] sDirs = new String[4];
|
String[] sDirs = new String[1];
|
||||||
for (int i = 0; i < 4; ++i) {
|
// Making sure that we have only one local disk so that it will only be
|
||||||
localDirs.add(lfs.makeQualified(new Path(basedir, i + "")));
|
// selected for consecutive resource localization calls. This is required
|
||||||
sDirs[i] = localDirs.get(i).toString();
|
// to test LocalCacheDirectoryManager.
|
||||||
}
|
localDirs.add(lfs.makeQualified(new Path(basedir, 0 + "")));
|
||||||
|
sDirs[0] = localDirs.get(0).toString();
|
||||||
|
|
||||||
conf.setStrings(YarnConfiguration.NM_LOCAL_DIRS, sDirs);
|
conf.setStrings(YarnConfiguration.NM_LOCAL_DIRS, sDirs);
|
||||||
|
// Adding configuration to make sure there is only one file per
|
||||||
|
// directory
|
||||||
|
conf.set(YarnConfiguration.NM_LOCAL_CACHE_MAX_FILES_PER_DIRECTORY, "37");
|
||||||
String logDir = lfs.makeQualified(new Path(basedir, "logdir " )).toString();
|
String logDir = lfs.makeQualified(new Path(basedir, "logdir " )).toString();
|
||||||
conf.set(YarnConfiguration.NM_LOG_DIRS, logDir);
|
conf.set(YarnConfiguration.NM_LOG_DIRS, logDir);
|
||||||
DrainDispatcher dispatcher = new DrainDispatcher();
|
DrainDispatcher dispatcher = new DrainDispatcher();
|
||||||
|
@ -452,12 +459,23 @@ public class TestResourceLocalizationService {
|
||||||
doReturn(out).when(spylfs).createInternal(isA(Path.class),
|
doReturn(out).when(spylfs).createInternal(isA(Path.class),
|
||||||
isA(EnumSet.class), isA(FsPermission.class), anyInt(), anyShort(),
|
isA(EnumSet.class), isA(FsPermission.class), anyInt(), anyShort(),
|
||||||
anyLong(), isA(Progressable.class), isA(ChecksumOpt.class), anyBoolean());
|
anyLong(), isA(Progressable.class), isA(ChecksumOpt.class), anyBoolean());
|
||||||
final LocalResource resource = getPrivateMockedResource(r);
|
final LocalResource resource1 = getPrivateMockedResource(r);
|
||||||
final LocalResourceRequest req = new LocalResourceRequest(resource);
|
LocalResource resource2 = null;
|
||||||
|
do {
|
||||||
|
resource2 = getPrivateMockedResource(r);
|
||||||
|
} while (resource2 == null || resource2.equals(resource1));
|
||||||
|
// above call to make sure we don't get identical resources.
|
||||||
|
|
||||||
|
final LocalResourceRequest req1 = new LocalResourceRequest(resource1);
|
||||||
|
final LocalResourceRequest req2 = new LocalResourceRequest(resource2);
|
||||||
Map<LocalResourceVisibility, Collection<LocalResourceRequest>> rsrcs =
|
Map<LocalResourceVisibility, Collection<LocalResourceRequest>> rsrcs =
|
||||||
new HashMap<LocalResourceVisibility,
|
new HashMap<LocalResourceVisibility,
|
||||||
Collection<LocalResourceRequest>>();
|
Collection<LocalResourceRequest>>();
|
||||||
rsrcs.put(LocalResourceVisibility.PRIVATE, Collections.singletonList(req));
|
List<LocalResourceRequest> privateResourceList =
|
||||||
|
new ArrayList<LocalResourceRequest>();
|
||||||
|
privateResourceList.add(req1);
|
||||||
|
privateResourceList.add(req2);
|
||||||
|
rsrcs.put(LocalResourceVisibility.PRIVATE, privateResourceList);
|
||||||
spyService.handle(new ContainerLocalizationRequestEvent(c, rsrcs));
|
spyService.handle(new ContainerLocalizationRequestEvent(c, rsrcs));
|
||||||
// Sigh. Thread init of private localizer not accessible
|
// Sigh. Thread init of private localizer not accessible
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
|
@ -471,33 +489,64 @@ public class TestResourceLocalizationService {
|
||||||
Path localizationTokenPath = tokenPathCaptor.getValue();
|
Path localizationTokenPath = tokenPathCaptor.getValue();
|
||||||
|
|
||||||
// heartbeat from localizer
|
// heartbeat from localizer
|
||||||
LocalResourceStatus rsrcStat = mock(LocalResourceStatus.class);
|
LocalResourceStatus rsrcStat1 = mock(LocalResourceStatus.class);
|
||||||
|
LocalResourceStatus rsrcStat2 = mock(LocalResourceStatus.class);
|
||||||
LocalizerStatus stat = mock(LocalizerStatus.class);
|
LocalizerStatus stat = mock(LocalizerStatus.class);
|
||||||
when(stat.getLocalizerId()).thenReturn(ctnrStr);
|
when(stat.getLocalizerId()).thenReturn(ctnrStr);
|
||||||
when(rsrcStat.getResource()).thenReturn(resource);
|
when(rsrcStat1.getResource()).thenReturn(resource1);
|
||||||
when(rsrcStat.getLocalSize()).thenReturn(4344L);
|
when(rsrcStat2.getResource()).thenReturn(resource2);
|
||||||
|
when(rsrcStat1.getLocalSize()).thenReturn(4344L);
|
||||||
|
when(rsrcStat2.getLocalSize()).thenReturn(2342L);
|
||||||
URL locPath = getPath("/cache/private/blah");
|
URL locPath = getPath("/cache/private/blah");
|
||||||
when(rsrcStat.getLocalPath()).thenReturn(locPath);
|
when(rsrcStat1.getLocalPath()).thenReturn(locPath);
|
||||||
when(rsrcStat.getStatus()).thenReturn(ResourceStatusType.FETCH_SUCCESS);
|
when(rsrcStat2.getLocalPath()).thenReturn(locPath);
|
||||||
|
when(rsrcStat1.getStatus()).thenReturn(ResourceStatusType.FETCH_SUCCESS);
|
||||||
|
when(rsrcStat2.getStatus()).thenReturn(ResourceStatusType.FETCH_SUCCESS);
|
||||||
when(stat.getResources())
|
when(stat.getResources())
|
||||||
.thenReturn(Collections.<LocalResourceStatus>emptyList())
|
.thenReturn(Collections.<LocalResourceStatus>emptyList())
|
||||||
.thenReturn(Collections.singletonList(rsrcStat))
|
.thenReturn(Collections.singletonList(rsrcStat1))
|
||||||
|
.thenReturn(Collections.singletonList(rsrcStat2))
|
||||||
.thenReturn(Collections.<LocalResourceStatus>emptyList());
|
.thenReturn(Collections.<LocalResourceStatus>emptyList());
|
||||||
|
|
||||||
// get rsrc
|
String localPath = Path.SEPARATOR + ContainerLocalizer.USERCACHE +
|
||||||
|
Path.SEPARATOR + "user0" + Path.SEPARATOR +
|
||||||
|
ContainerLocalizer.FILECACHE;
|
||||||
|
|
||||||
|
// get first resource
|
||||||
LocalizerHeartbeatResponse response = spyService.heartbeat(stat);
|
LocalizerHeartbeatResponse response = spyService.heartbeat(stat);
|
||||||
assertEquals(LocalizerAction.LIVE, response.getLocalizerAction());
|
assertEquals(LocalizerAction.LIVE, response.getLocalizerAction());
|
||||||
assertEquals(req, new LocalResourceRequest(response.getLocalResource(0)));
|
assertEquals(1, response.getResourceSpecs().size());
|
||||||
|
assertEquals(req1,
|
||||||
|
new LocalResourceRequest(response.getResourceSpecs().get(0).getResource()));
|
||||||
|
URL localizedPath =
|
||||||
|
response.getResourceSpecs().get(0).getDestinationDirectory();
|
||||||
|
assertTrue(localizedPath.getFile().endsWith(localPath));
|
||||||
|
|
||||||
|
// get second resource
|
||||||
|
response = spyService.heartbeat(stat);
|
||||||
|
assertEquals(LocalizerAction.LIVE, response.getLocalizerAction());
|
||||||
|
assertEquals(1, response.getResourceSpecs().size());
|
||||||
|
assertEquals(req2, new LocalResourceRequest(response.getResourceSpecs()
|
||||||
|
.get(0).getResource()));
|
||||||
|
localizedPath =
|
||||||
|
response.getResourceSpecs().get(0).getDestinationDirectory();
|
||||||
|
// Resource's destination path should be now inside sub directory 0 as
|
||||||
|
// LocalCacheDirectoryManager will be used and we have restricted number
|
||||||
|
// of files per directory to 1.
|
||||||
|
assertTrue(localizedPath.getFile().endsWith(
|
||||||
|
localPath + Path.SEPARATOR + "0"));
|
||||||
|
|
||||||
// empty rsrc
|
// empty rsrc
|
||||||
response = spyService.heartbeat(stat);
|
response = spyService.heartbeat(stat);
|
||||||
assertEquals(LocalizerAction.LIVE, response.getLocalizerAction());
|
assertEquals(LocalizerAction.LIVE, response.getLocalizerAction());
|
||||||
assertEquals(0, response.getAllResources().size());
|
assertEquals(0, response.getResourceSpecs().size());
|
||||||
|
|
||||||
// get shutdown
|
// get shutdown
|
||||||
response = spyService.heartbeat(stat);
|
response = spyService.heartbeat(stat);
|
||||||
assertEquals(LocalizerAction.DIE, response.getLocalizerAction());
|
assertEquals(LocalizerAction.DIE, response.getLocalizerAction());
|
||||||
|
|
||||||
|
|
||||||
|
dispatcher.await();
|
||||||
// verify container notification
|
// verify container notification
|
||||||
ArgumentMatcher<ContainerEvent> matchesContainerLoc =
|
ArgumentMatcher<ContainerEvent> matchesContainerLoc =
|
||||||
new ArgumentMatcher<ContainerEvent>() {
|
new ArgumentMatcher<ContainerEvent>() {
|
||||||
|
@ -508,8 +557,8 @@ public class TestResourceLocalizationService {
|
||||||
&& c.getContainerID() == evt.getContainerID();
|
&& c.getContainerID() == evt.getContainerID();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
dispatcher.await();
|
// total 2 resource localzation calls. one for each resource.
|
||||||
verify(containerBus).handle(argThat(matchesContainerLoc));
|
verify(containerBus, times(2)).handle(argThat(matchesContainerLoc));
|
||||||
|
|
||||||
// Verify deletion of localization token.
|
// Verify deletion of localization token.
|
||||||
verify(delService).delete((String)isNull(), eq(localizationTokenPath));
|
verify(delService).delete((String)isNull(), eq(localizationTokenPath));
|
||||||
|
|
Loading…
Reference in New Issue