/*
* 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.ignite.internal.processors.hadoop.impl.igfs;
import java.net.URI;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.ignite.Ignition;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.hadoop.fs.v1.IgniteHadoopFileSystem;
import org.apache.ignite.internal.IgniteInternalFuture;
import org.apache.ignite.internal.IgnitionEx;
import org.apache.ignite.internal.processors.resource.GridSpringResourceContext;
import org.apache.ignite.internal.util.typedef.X;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.lang.IgniteBiTuple;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
/**
* IGFS Hadoop file system Ignite client -based self test for PROXY mode.
*/
public class IgniteHadoopFileSystemClientBasedOpenTest extends GridCommonAbstractTest {
/** Config root path. */
private static final String [] CONFIGS = {
"modules/hadoop/src/test/config/hadoop-fs-open-test/grid-0.xml",
"modules/hadoop/src/test/config/hadoop-fs-open-test/grid-1.xml",
"modules/hadoop/src/test/config/hadoop-fs-open-test/grid-2.xml"
};
/** Nodes types. */
private static NodeType[][] nodesTypes = new NodeType[][] {
{NodeType.REMOTE, NodeType.REMOTE, NodeType.REMOTE},
{NodeType.LOCAL, NodeType.REMOTE, NodeType.REMOTE},
{NodeType.REMOTE, NodeType.LOCAL, NodeType.REMOTE},
{NodeType.LOCAL, NodeType.LOCAL, NodeType.REMOTE},
{NodeType.REMOTE, NodeType.REMOTE, NodeType.LOCAL},
{NodeType.LOCAL, NodeType.REMOTE, NodeType.LOCAL},
{NodeType.REMOTE, NodeType.LOCAL, NodeType.LOCAL},
{NodeType.LOCAL, NodeType.LOCAL, NodeType.LOCAL},
{NodeType.LOCAL_SAME_NAME, NodeType.REMOTE, NodeType.REMOTE},
{NodeType.REMOTE, NodeType.LOCAL_SAME_NAME, NodeType.REMOTE},
{NodeType.LOCAL_SAME_NAME, NodeType.LOCAL_SAME_NAME, NodeType.REMOTE},
{NodeType.REMOTE, NodeType.REMOTE, NodeType.LOCAL_SAME_NAME},
{NodeType.LOCAL_SAME_NAME, NodeType.REMOTE, NodeType.LOCAL_SAME_NAME},
{NodeType.REMOTE, NodeType.LOCAL_SAME_NAME, NodeType.LOCAL_SAME_NAME},
{NodeType.LOCAL_SAME_NAME, NodeType.LOCAL_SAME_NAME, NodeType.LOCAL_SAME_NAME},
};
/** Test threads count. */
private static final int THREADS_COUNT = 20;
/** Iterations count. */
private static final int ITERATIONS = 10;
/** Iterations count. */
private static boolean skipInProc;
/**
* @param idx Grid index.
* @return Path to Ignite config file.
*/
private static String cfgPath(int idx) {
return CONFIGS[idx];
}
/**
* @param idx Grid index.
* @return Path to Ignite config file.
*/
private static String uri(int idx) {
return "igfs://" + authority(idx) + '/';
}
/** {@inheritDoc} */
@Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
IgniteBiTuple<IgniteConfiguration, GridSpringResourceContext> cfgPair =
IgnitionEx.loadConfiguration(cfgPath(getTestIgniteInstanceIndex(gridName)));
IgniteConfiguration cfg = cfgPair.get1();
cfg.setIgniteInstanceName(gridName);
return cfg;
}
/** {@inheritDoc} */
@Override protected void afterTestsStopped() throws Exception {
stopAllGrids();
super.afterTestsStopped();
}
/** {@inheritDoc} */
@Override protected long getTestTimeout() {
return 15 * 60_000;
}
/**
* Create configuration for test.
*
* @param idx Grid index.
* @return Configuration.
*/
protected Configuration configuration(int idx) {
Configuration cfg = new Configuration();
cfg.set("fs.defaultFS", "igfs://" + authority(idx) + '/');
cfg.set("fs.igfs.impl", IgniteHadoopFileSystem.class.getName());
cfg.set("fs.AbstractFileSystem.igfs.impl",
org.apache.ignite.hadoop.fs.v2.IgniteHadoopFileSystem.class.getName());
cfg.setBoolean("fs.igfs.impl.disable.cache", true);
cfg.setStrings(String.format(HadoopIgfsUtils.PARAM_IGFS_ENDPOINT_IGNITE_CFG_PATH, authority(idx)),
cfgPath(idx));
if (skipInProc)
cfg.setBoolean(String.format(HadoopIgfsUtils.PARAM_IGFS_ENDPOINT_NO_EMBED, authority(idx)), true);
return cfg;
}
/**
* Create configuration for test.
*
* @return Configuration.
*/
protected Configuration configurationWrongIgfs() {
Configuration cfg = new Configuration();
cfg.set("fs.defaultFS", "igfs://igfs-wrong-name@/");
cfg.set("fs.igfs.impl", IgniteHadoopFileSystem.class.getName());
cfg.set("fs.AbstractFileSystem.igfs.impl",
org.apache.ignite.hadoop.fs.v2.IgniteHadoopFileSystem.class.getName());
cfg.setBoolean("fs.igfs.impl.disable.cache", true);
cfg.setStrings(String.format(HadoopIgfsUtils.PARAM_IGFS_ENDPOINT_IGNITE_CFG_PATH, "igfs-wrong-name@"),
cfgPath(0));
return cfg;
}
/**
* @param idx Grid index.
* @return IGFS authority.
*/
private static String authority(int idx) {
return "igfs-" + idx + "@";
}
/**
* @throws Exception If failed.
*/
public void testFsOpenMultithreaded() throws Exception {
skipInProc = false;
checkFsOpenWithAllNodesTypes();
}
/**
* @throws Exception If failed.
*/
private void checkFsOpenWithAllNodesTypes() throws Exception {
for (int i = 0; i < nodesTypes.length; ++i) {
log.info("Begin test case for nodes: " + S.arrayToString(NodeType.class, nodesTypes[i]));
startNodes(nodesTypes[i]);
// Await clusters start
Thread.sleep(10_000);
try {
checkFsOpenMultithreaded();
} finally {
stopAllGrids();
}
}
}
/**
* @throws Exception If failed.
*/
public void testFsOpenMultithreadedSkipInProc() throws Exception {
skipInProc = true;
checkFsOpenWithAllNodesTypes();
}
/**
* @throws Exception If failed.
*/
public void testIgniteClientWithIgfsMisconfigure() throws Exception {
startNodes(new NodeType[] {NodeType.REMOTE, NodeType.REMOTE, NodeType.REMOTE});
// Await clusters start
Thread.sleep(10_000);
try {
try (FileSystem fs = FileSystem.get(new URI("igfs://igfs-wrong-name@"), configurationWrongIgfs())) {
FSDataOutputStream out = fs.create(new Path("igfs://igfs-wrong-name@/file"), true);
assert false : "Exception must be thrown";
}
catch (Exception e) {
assertTrue(e.getMessage().contains(
"Ignite client node doesn't have IGFS with the given name: igfs-wrong-name"));
}
} finally {
stopAllGrids();
}
}
/**
* @param nodeTypes Types of server nodes.
* @throws Exception If failed.
*/
public void startNodes(NodeType[] nodeTypes) throws Exception {
assert nodeTypes.length == CONFIGS.length;
for (int i = 0; i < CONFIGS.length; i++) {
String name = getTestIgniteInstanceName(i);
switch (nodeTypes[i]) {
case REMOTE:
startRemoteGrid(name, getConfiguration(name),
null, null, false);
break;
case LOCAL:
startGrid(name, getConfiguration(name));
break;
case LOCAL_SAME_NAME:
startGrid("IGFS-cli-" + i, getConfiguration(name));
break;
}
}
}
/**
* @throws Exception If failed.
*/
public void checkFsOpenMultithreaded() throws Exception {
X.println("Start hadoop client file system open test");
final AtomicInteger fileIdx = new AtomicInteger();
IgniteInternalFuture fut = multithreadedAsync(new Runnable() {
@Override public void run() {
for (int iter = 0; iter < ITERATIONS; iter++) {
for (int i = 0; i < CONFIGS.length; i++) {
try (FileSystem fs = FileSystem.get(new URI(uri(i)), configuration(i))) {
FSDataOutputStream out = fs.create(new Path(uri(i) + "file" +
fileIdx.getAndIncrement()), true);
out.close();
}
catch (Exception e) {
e.printStackTrace();
assert false : "Unexpected exception";
}
}
}
}
}, THREADS_COUNT);
fut.get();
}
/**
* Node type.
*/
enum NodeType {
/** Remote node. */
REMOTE,
/** Node in the test VM. */
LOCAL,
/** Node in the test VM with the name equals to client node config. */
LOCAL_SAME_NAME
}
}