/*
* 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.igfs;
import org.apache.commons.io.IOUtils;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteException;
import org.apache.ignite.IgniteFileSystem;
import org.apache.ignite.cache.CacheWriteSynchronizationMode;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.FileSystemConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.igfs.IgfsDirectoryNotEmptyException;
import org.apache.ignite.igfs.IgfsException;
import org.apache.ignite.igfs.IgfsFile;
import org.apache.ignite.igfs.IgfsGroupDataBlocksKeyMapper;
import org.apache.ignite.igfs.IgfsInputStream;
import org.apache.ignite.igfs.IgfsOutputStream;
import org.apache.ignite.igfs.IgfsPath;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.IgniteKernal;
import org.apache.ignite.internal.processors.cache.GridCacheAdapter;
import org.apache.ignite.internal.util.lang.GridAbsPredicate;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteBiTuple;
import org.apache.ignite.lang.IgniteUuid;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
import org.apache.ignite.testframework.GridTestUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.cache.Cache;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
import static org.apache.ignite.cache.CacheMode.PARTITIONED;
import static org.apache.ignite.cache.CacheMode.REPLICATED;
/**
* Tests for {@link IgfsProcessor}.
*/
public class IgfsProcessorSelfTest extends IgfsCommonAbstractTest {
/** Test IP finder. */
private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
/** Random numbers generator. */
protected final SecureRandom rnd = new SecureRandom();
/** File system. */
protected IgniteFileSystem igfs;
/** Meta cache. */
private GridCacheAdapter<Object, Object> metaCache;
/** Meta cache name. */
private String metaCacheName;
/** {@inheritDoc} */
@Override protected void beforeTest() throws Exception {
IgniteEx grid = grid(0);
igfs = grid.fileSystem(igfsName());
FileSystemConfiguration[] cfgs = grid.configuration().getFileSystemConfiguration();
assert cfgs.length == 1;
metaCacheName = cfgs[0].getMetaCacheConfiguration().getName();
metaCache = ((IgniteKernal)grid).internalCache(metaCacheName);
}
/** {@inheritDoc} */
@Override protected void afterTest() throws Exception {
super.afterTest();
igfs.clear();
}
/** {@inheritDoc} */
@Override protected void beforeTestsStarted() throws Exception {
startGrids(nodesCount());
}
/** {@inheritDoc} */
@Override protected void afterTestsStopped() throws Exception {
stopAllGrids();
}
/** {@inheritDoc} */
@Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
TcpDiscoverySpi discoSpi = new TcpDiscoverySpi();
discoSpi.setIpFinder(IP_FINDER);
cfg.setDiscoverySpi(discoSpi);
FileSystemConfiguration igfsCfg = new FileSystemConfiguration();
igfsCfg.setMetaCacheConfiguration(cacheConfiguration("meta"));
igfsCfg.setDataCacheConfiguration(cacheConfiguration("data"));
igfsCfg.setName("igfs");
cfg.setFileSystemConfiguration(igfsCfg);
return cfg;
}
/** {@inheritDoc} */
protected CacheConfiguration cacheConfiguration(@NotNull String cacheName) {
CacheConfiguration cacheCfg = defaultCacheConfiguration();
cacheCfg.setName(cacheName);
if ("meta".equals(cacheName))
cacheCfg.setCacheMode(REPLICATED);
else {
cacheCfg.setCacheMode(PARTITIONED);
cacheCfg.setNearConfiguration(null);
cacheCfg.setBackups(0);
cacheCfg.setAffinityMapper(new IgfsGroupDataBlocksKeyMapper(128));
}
cacheCfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);
cacheCfg.setAtomicityMode(TRANSACTIONAL);
return cacheCfg;
}
/** @return Test nodes count. */
public int nodesCount() {
return 1;
}
/** @return FS name. */
public String igfsName() {
return "igfs";
}
/** @throws Exception If failed. */
public void testigfsEnabled() throws Exception {
IgniteFileSystem igfs = grid(0).fileSystem(igfsName());
assertNotNull(igfs);
}
/**
* Test properties management in meta-cache.
*
* @throws Exception If failed.
*/
public void testUpdateProperties() throws Exception {
IgfsPath p = path("/tmp/my");
igfs.mkdirs(p);
Map<String, String> oldProps = igfs.info(p).properties();
igfs.update(p, F.asMap("a", "1"));
igfs.update(p, F.asMap("b", "2"));
assertEquals("1", igfs.info(p).property("a"));
assertEquals("2", igfs.info(p).property("b"));
igfs.update(p, F.asMap("b", "3"));
Map<String, String> expProps = new HashMap<>(oldProps);
expProps.put("a", "1");
expProps.put("b", "3");
assertEquals("3", igfs.info(p).property("b"));
assertEquals(expProps, igfs.info(p).properties());
assertEquals("5", igfs.info(p).property("c", "5"));
assertUpdatePropertiesFails(null, null, NullPointerException.class, "Ouch! Argument cannot be null");
assertUpdatePropertiesFails(p, null, NullPointerException.class, "Ouch! Argument cannot be null");
assertUpdatePropertiesFails(null, F.asMap("x", "9"), NullPointerException.class,
"Ouch! Argument cannot be null");
assertUpdatePropertiesFails(p, Collections.<String, String>emptyMap(), IllegalArgumentException.class,
"Ouch! Argument is invalid");
}
/** @throws Exception If failed. */
public void testCreate() throws Exception {
IgfsPath path = path("/file");
try (IgfsOutputStream os = igfs.create(path, false)) {
assert os != null;
IgfsFileImpl info = (IgfsFileImpl)igfs.info(path);
for (int i = 0; i < nodesCount(); i++) {
IgfsEntryInfo fileInfo =
(IgfsEntryInfo)grid(i).cachex(metaCacheName).localPeek(info.fileId(), null, null);
assertNotNull(fileInfo);
assertNotNull(fileInfo.listing());
}
}
finally {
igfs.delete(path("/"), true);
}
}
/**
* Test make directories.
*
* @throws Exception In case of any exception.
*/
public void testMakeListDeleteDirs() throws Exception {
assertListDir("/");
igfs.mkdirs(path("/ab/cd/ef"));
assertListDir("/", "ab");
assertListDir("/ab", "cd");
assertListDir("/ab/cd", "ef");
igfs.mkdirs(path("/ab/ef"));
igfs.mkdirs(path("/cd/ef"));
igfs.mkdirs(path("/cd/gh"));
igfs.mkdirs(path("/ef"));
igfs.mkdirs(path("/ef/1"));
igfs.mkdirs(path("/ef/2"));
igfs.mkdirs(path("/ef/3"));
assertListDir("/", "ef", "ab", "cd");
assertListDir("/ab", "cd", "ef");
assertListDir("/ab/cd", "ef");
assertListDir("/ab/cd/ef");
assertListDir("/cd", "ef", "gh");
assertListDir("/cd/ef");
assertListDir("/ef", "1", "2", "3");
igfs.delete(path("/ef/2"), false);
assertListDir("/", "ef", "ab", "cd");
assertListDir("/ef", "1", "3");
// Delete should return false for non-existing paths.
assertFalse(igfs.delete(path("/ef/2"), false));
assertListDir("/", "ef", "ab", "cd");
assertListDir("/ef", "1", "3");
GridTestUtils.assertThrows(log, new Callable<Object>() {
@Override public Object call() throws Exception {
igfs.delete(path("/ef"), false);
return null;
}
}, IgfsDirectoryNotEmptyException.class, null);
assertListDir("/", "ef", "ab", "cd");
assertListDir("/ef", "1", "3");
igfs.delete(path("/ef"), true);
assertListDir("/", "ab", "cd");
}
/**
* Test make directories in multi-threaded environment.
*
* @throws Exception In case of any exception.
*/
@SuppressWarnings("TooBroadScope")
public void testMakeListDeleteDirsMultithreaded() throws Exception {
assertListDir("/");
final int max = 2 * 1000;
final int threads = 50;
final AtomicInteger cnt = new AtomicInteger();
info("Create directories: " + max);
GridTestUtils.runMultiThreaded(new Callable<Object>() {
@Override public Object call() throws Exception {
for (int cur = cnt.incrementAndGet(); cur < max; cur = cnt.incrementAndGet())
igfs.mkdirs(path(cur));
return null;
}
}, threads, "grid-test-make-directories");
info("Validate directories were created.");
cnt.set(0); // Reset counter.
GridTestUtils.runMultiThreaded(new Callable<Object>() {
@Override public Object call() throws Exception {
for (int cur = cnt.incrementAndGet(); cur < max; cur = cnt.incrementAndGet()) {
IgfsFile info = igfs.info(path(cur));
assertNotNull("Expects file exist: " + cur, info);
assertTrue("Expects file is a directory: " + cur, info.isDirectory());
}
return null;
}
}, threads, "grid-test-check-directories-exist");
info("Validate directories removing.");
cnt.set(0); // Reset counter.
GridTestUtils.runMultiThreaded(new Callable<Object>() {
@Override public Object call() throws Exception {
for (int cur = cnt.incrementAndGet(); cur < max; cur = cnt.incrementAndGet())
igfs.delete(path(cur), true);
return null;
}
}, threads, "grid-test-delete-directories");
}
/** @throws Exception If failed. */
public void testBasicOps() throws Exception {
// Create directories.
igfs.mkdirs(path("/A/B1/C1"));
for (Object key : metaCache.keySet())
info("Entry in cache [key=" + key + ", val=" + metaCache.get(key) + ']');
igfs.mkdirs(path("/A/B1/C2"));
igfs.mkdirs(path("/A/B1/C3"));
igfs.mkdirs(path("/A/B2/C1"));
igfs.mkdirs(path("/A/B2/C2"));
igfs.mkdirs(path("/A1/B1/C1"));
igfs.mkdirs(path("/A1/B1/C2"));
igfs.mkdirs(path("/A1/B1/C3"));
igfs.mkdirs(path("/A2/B2/C1"));
igfs.mkdirs(path("/A2/B2/C2"));
for (Object key : metaCache.keySet())
info("Entry in cache [key=" + key + ", val=" + metaCache.get(key) + ']');
// Check existence.
assert igfs.exists(path("/A/B1/C1"));
// List items.
Collection<IgfsPath> paths = igfs.listPaths(path("/"));
assert paths.size() == 3 : "Unexpected paths: " + paths;
paths = igfs.listPaths(path("/A"));
assert paths.size() == 2 : "Unexpected paths: " + paths;
paths = igfs.listPaths(path("/A/B1"));
assert paths.size() == 3 : "Unexpected paths: " + paths;
igfs.delete(path("/A1/B1/C1"), false);
assertNull(igfs.info(path("/A1/B1/C1")));
igfs.delete(path("/A1/B1/C2"), false);
assertNull(igfs.info(path("/A1/B1/C2")));
igfs.delete(path("/A1/B1/C3"), false);
assertNull(igfs.info(path("/A1/B1/C3")));
assertTrue(F.isEmpty(igfs.listPaths(path("/A1/B1"))));
igfs.delete(path("/A2/B2"), true);
assertNull(igfs.info(path("/A2/B2")));
assertTrue(F.isEmpty(igfs.listPaths(path("/A2"))));
assertEquals(Arrays.asList(path("/A"), path("/A1"), path("/A2")), sorted(igfs.listPaths(path("/"))));
// Delete root when it is not empty:
igfs.delete(path("/"), true);
igfs.delete(path("/"), false);
igfs.delete(path("/A"), true);
igfs.delete(path("/A1"), true);
igfs.delete(path("/A2"), true);
assertTrue(F.isEmpty(igfs.listPaths(path("/"))));
// Delete root when it is empty:
igfs.delete(path("/"), false);
igfs.delete(path("/"), true);
assertTrue(F.isEmpty(igfs.listPaths(path("/"))));
for (Cache.Entry<Object, Object> e : metaCache)
info("Entry in cache [key=" + e.getKey() + ", val=" + e.getValue() + ']');
}
/**
* Ensure correct size calculation.
*
* @throws Exception If failed.
*/
public void testSize() throws Exception {
IgfsPath dir1 = path("/dir1");
IgfsPath subDir1 = path("/dir1/subdir1");
IgfsPath dir2 = path("/dir2");
IgfsPath fileDir1 = path("/dir1/file");
IgfsPath fileSubdir1 = path("/dir1/subdir1/file");
IgfsPath fileDir2 = path("/dir2/file");
IgfsOutputStream os = igfs.create(fileDir1, false);
os.write(new byte[1000]);
os.close();
os = igfs.create(fileSubdir1, false);
os.write(new byte[2000]);
os.close();
os = igfs.create(fileDir2, false);
os.write(new byte[4000]);
os.close();
assert igfs.size(fileDir1) == 1000;
assert igfs.size(fileSubdir1) == 2000;
assert igfs.size(fileDir2) == 4000;
assert igfs.size(dir1) == 3000;
assert igfs.size(subDir1) == 2000;
assert igfs.size(dir2) == 4000;
}
/**
* Convert collection into sorted list.
*
* @param col Unsorted collection.
* @return Sorted collection.
*/
private <T extends Comparable<T>> List<T> sorted(Collection<T> col) {
List<T> list = new ArrayList<>(col);
Collections.sort(list);
return list;
}
/** @throws Exception If failed. */
public void testRename() throws Exception {
// Create directories.
igfs.mkdirs(path("/A/B1/C1"));
for (Object key : metaCache.keySet())
info("Entry in cache [key=" + key + ", val=" + metaCache.get(key) + ']');
// Move under itself.
GridTestUtils.assertThrowsInherited(log, new Callable<Object>() {
@Override public Object call() throws Exception {
igfs.rename(path("/A/B1/C1"), path("/A/B1/C1/C2"));
return null;
}
}, IgfsException.class, null);
// Move under itself.
GridTestUtils.assertThrowsInherited(log, new Callable<Object>() {
@Override public Object call() throws Exception {
igfs.rename(path("/A/B1/C1"), path("/A/B1/C1/D/C2"));
return null;
}
}, IgfsException.class, null);
// Move under itself.
GridTestUtils.assertThrowsInherited(log, new Callable<Object>() {
@Override
public Object call() throws Exception {
igfs.rename(path("/A/B1/C1"), path("/A/B1/C1/D/E/C2"));
return null;
}
}, IgfsException.class, null);
///
// F6 > Enter > Tab x N times
// "I like to move it, move it..."
//
Collection<IgniteBiTuple<String, String>> chain = Arrays.asList(
F.t("/A/B1/C1", "/A/B1/C2"),
F.t("/A/B1", "/A/B2"),
F.t("/A", "/Q"),
//F.t("/Q/B2/C2", "/C3"),
F.t("/Q/B2/C2", "/Q/B2/C1"),
F.t("/Q/B2", "/Q/B1"),
F.t("/Q", "/A"),
//F.t("/C3", "/A/B1/C1")
F.t("/A/B1/C1", "/"),
F.t("/C1", "/A/B1")
);
final IgfsPath root = path("/");
for (IgniteBiTuple<String, String> e : chain) {
final IgfsPath p1 = path(e.get1());
final IgfsPath p2 = path(e.get2());
assertTrue("Entry: " + e, igfs.exists(p1));
igfs.rename(p1, p2);
assertFalse("Entry: " + e, igfs.exists(p1));
assertTrue("Entry: " + e, igfs.exists(p2));
// Test root rename.
GridTestUtils.assertThrowsInherited(log, new Callable<Object>() {
@Override public Object call() throws Exception {
igfs.rename(root, p1);
return null;
}
}, IgfsException.class, null);
// Test root rename.
GridTestUtils.assertThrowsInherited(log, new Callable<Object>() {
@Override public Object call() throws Exception {
igfs.rename(p1, root);
return null;
}
}, IgfsException.class, null);
// Test root rename.
if (!root.equals(p2)) {
GridTestUtils.assertThrowsInherited(log, new Callable<Object>() {
@Override public Object call() throws Exception {
igfs.rename(root, p2);
return null;
}
}, IgfsException.class, null);
}
// Test same rename.
igfs.rename(p1, p1);
igfs.rename(p2, p2);
}
// List items.
assertEquals(Arrays.asList(path("/A")), sorted(igfs.listPaths(root)));
assertEquals(Arrays.asList(path("/A/B1")), sorted(igfs.listPaths(path("/A"))));
assertEquals(Arrays.asList(path("/A/B1/C1")), sorted(igfs.listPaths(path("/A/B1"))));
String text = "Test long number: " + rnd.nextLong();
// Create file.
assertEquals(text, create("/A/a", false, text));
// Validate renamed during reading.
try (IgfsInputStream in0 = igfs.open(path("/A/a"))) {
// Rename file.
igfs.rename(path("/A/a"), path("/b"));
assertEquals(text, IOUtils.toString(in0, UTF_8));
}
// Validate after renamed.
assertOpenFails("/A/a", "File not found");
assertEquals(text, read("/b"));
// Cleanup.
igfs.clear();
assertTrue(F.isEmpty(igfs.listPaths(root)));
}
/**
* @param path Path.
* @return IGFS path.
*/
private IgfsPath path(String path) {
assert path != null;
return new IgfsPath(path);
}
/**
* @param i Path index.
* @return IGFS path.
*/
private IgfsPath path(long i) {
//return path(String.format("/%d", i));
return path(String.format("/%d/q/%d/%d", i % 10, (i / 10) % 10, i));
}
/** @throws Exception If failed. */
public void testCreateOpenAppend() throws Exception {
// Error - path points to root directory.
assertCreateFails("/", false);
// Create directories.
igfs.mkdirs(path("/A/B1/C1"));
// Error - path points to directory.
for (String path : Arrays.asList("/A", "/A/B1", "/A/B1/C1")) {
assertCreateFails(path, false);
assertCreateFails(path, true);
assertAppendFails(path, false);
assertAppendFails(path, true);
assertOpenFails(path, "Failed to open file (not a file)");
}
String text1 = "Test long number #1: " + rnd.nextLong();
String text2 = "Test long number #2: " + rnd.nextLong();
// Error - parent does not exist.
for (String path : Arrays.asList("/A/a", "/A/B1/a", "/A/B1/C1/a")) {
// Error - file doesn't exist.
assertOpenFails(path, "File not found");
assertAppendFails(path, false);
// Create new and write.
assertEquals(text1, create(path, false, text1));
// Error - file already exists.
assertCreateFails(path, false);
// Overwrite existent.
assertEquals(text2, create(path, true, text2));
// Append text.
assertEquals(text2 + text1, append(path, false, text1));
// Append text.
assertEquals(text2 + text1 + text2, append(path, true, text2));
// Delete this file.
igfs.delete(path(path), true);
// Error - file doesn't exist.
assertOpenFails(path, "File not found");
assertAppendFails(path, false);
// Create with append.
assertEquals(text1, append(path, true, text1));
// Append.
for (String full = text1, cur = ""; full.length() < 10000; cur = ", long=" + rnd.nextLong())
assertEquals(full += cur, append(path, rnd.nextBoolean(), cur));
igfs.delete(path(path), false);
}
}
/** @throws Exception If failed. */
@SuppressWarnings("BusyWait")
public void testDeleteCacheConsistency() throws Exception {
IgfsPath path = new IgfsPath("/someFile");
String metaCacheName = grid(0).igfsx("igfs").configuration().getMetaCacheConfiguration().getName();
String dataCacheName = grid(0).igfsx("igfs").configuration().getDataCacheConfiguration().getName();
try (IgfsOutputStream out = igfs.create(path, true)) {
out.write(new byte[10 * 1024 * 1024]);
}
IgniteUuid fileId = U.field(igfs.info(path), "fileId");
GridCacheAdapter<IgniteUuid, IgfsEntryInfo> metaCache = ((IgniteKernal)grid(0)).internalCache(metaCacheName);
GridCacheAdapter<IgfsBlockKey, byte[]> dataCache = ((IgniteKernal)grid(0)).internalCache(dataCacheName);
IgfsEntryInfo info = metaCache.get(fileId);
assertNotNull(info);
assertTrue(info.isFile());
assertNotNull(metaCache.get(info.id()));
IgfsDataManager dataMgr = ((IgfsEx)igfs).context().data();
for (int i = 0; i < info.blocksCount(); i++)
assertNotNull(dataCache.get(dataMgr.blockKey(i, info)));
igfs.delete(path, true);
for (int i = 0; i < 25; i++) {
if (metaCache.get(info.id()) == null)
break;
U.sleep(100);
}
assertNull(metaCache.get(info.id()));
for (int i = 0; i < 10; i++) {
boolean doBreak = true;
for (int j = 0; j < info.blocksCount(); j++) {
if (dataCache.get(dataMgr.blockKey(i, info)) != null) {
doBreak = false;
break;
}
}
if (doBreak)
break;
else
Thread.sleep(100);
}
for (int i = 0; i < info.blocksCount(); i++)
assertNull(dataCache.get(new IgfsBlockKey(info.id(), null, false, i)));
}
/** @throws Exception If failed. */
public void testCreateAppendLongData1() throws Exception {
checkCreateAppendLongData(123, 1024, 100);
}
/** @throws Exception If failed. */
public void testCreateAppendLongData2() throws Exception {
checkCreateAppendLongData(123 + 1024, 1024, 100);
}
/** @throws Exception If failed. */
public void testCreateAppendLongData3() throws Exception {
checkCreateAppendLongData(123, 1024, 1000);
}
/** @throws Exception If failed. */
public void testCreateAppendLongData4() throws Exception {
checkCreateAppendLongData(123 + 1024, 1024, 1000);
}
/**
* Test format operation on non-empty file system.
*
* @throws Exception If failed.
*/
public void testFormatNonEmpty() throws Exception {
String dirPath = "/A/B/C";
igfs.mkdirs(path(dirPath));
String filePath = "/someFile";
create(filePath, false, "Some text.");
igfs.clear();
assert !igfs.exists(path(dirPath));
assert !igfs.exists(path(filePath));
GridTestUtils.waitForCondition(new GridAbsPredicate() {
@Override public boolean apply() {
int metaSize = 0;
for (Object metaId : grid(0).cachex(igfs.configuration().getMetaCacheConfiguration().getName())
.keySet()) {
if (!IgfsUtils.isRootOrTrashId((IgniteUuid)metaId))
metaSize++;
}
return metaSize == 0;
}
}, 5000);
}
/**
* Test format operation on empty file system.
*
* @throws Exception If failed.
*/
public void testFormatEmpty() throws Exception {
igfs.clear();
}
/**
* @param chunkSize Chunk size.
* @param bufSize Buffer size.
* @param cnt Count.
* @throws Exception If failed.
*/
private void checkCreateAppendLongData(int chunkSize, int bufSize, int cnt) throws Exception {
IgfsPath path = new IgfsPath("/someFile");
byte[] buf = new byte[chunkSize];
for (int i = 0; i < buf.length; i++)
buf[i] = (byte)(i * i);
IgfsOutputStream os = igfs.create(path, bufSize, true, null, 0, 1024, null);
try {
for (int i = 0; i < cnt; i++)
os.write(buf);
os.flush();
}
finally {
os.close();
}
os = igfs.append(path, chunkSize, false, null);
try {
for (int i = 0; i < cnt; i++)
os.write(buf);
os.flush();
}
finally {
os.close();
}
byte[] readBuf = new byte[chunkSize];
try (IgfsInputStream in = igfs.open(path)) {
long pos = 0;
for (int k = 0; k < 2 * cnt; k++) {
in.readFully(pos, readBuf);
for (int i = 0; i < readBuf.length; i++)
assertEquals(buf[i], readBuf[i]);
pos += readBuf.length;
}
}
}
/**
* Create file and write specified text to.
*
* @param path File path to create.
* @param overwrite Overwrite file if it already exists.
* @param text Text to write into file.
* @return Content of this file.
* @throws IgniteCheckedException In case of error.
*/
private String create(String path, boolean overwrite, String text) throws Exception {
try (IgfsOutputStream out = igfs.create(path(path), overwrite)) {
IOUtils.write(text, out, UTF_8);
}
assertNotNull(igfs.info(path(path)));
return read(path);
}
/**
* Appent text to the file.
*
* @param path File path to create.
* @param create Create file if it doesn't exist yet.
* @param text Text to append to file.
* @return Content of this file.
* @throws IgniteCheckedException In case of error.
*/
private String append(String path, boolean create, String text) throws Exception {
try (IgfsOutputStream out = igfs.append(path(path), create)) {
IOUtils.write(text, out, UTF_8);
}
assertNotNull(igfs.info(path(path)));
return read(path);
}
/**
* Read content of the file.
*
* @param path File path to read.
* @return Content of this file.
* @throws IgniteCheckedException In case of error.
*/
private String read(String path) throws Exception {
try (IgfsInputStream in = igfs.open(path(path))) {
return IOUtils.toString(in, UTF_8);
}
}
/**
* Test expected failures for 'update properties' operation.
*
* @param path Path to the file.
* @param props File properties to set.
* @param msg Failure message if expected exception was not thrown.
*/
private void assertUpdatePropertiesFails(@Nullable final IgfsPath path,
@Nullable final Map<String, String> props,
Class<? extends Throwable> cls, @Nullable String msg) {
GridTestUtils.assertThrows(log, new Callable() {
@Override public Object call() throws Exception {
return igfs.update(path, props);
}
}, cls, msg);
}
/**
* Test expected failures for 'create' operation.
*
* @param path File path to create.
* @param overwrite Overwrite file if it already exists. Note: you cannot overwrite an existent directory.
*/
private void assertCreateFails(final String path, final boolean overwrite) {
GridTestUtils.assertThrowsInherited(log, new Callable<Object>() {
@Override public Object call() throws Exception {
igfs.create(path(path), overwrite);
return false;
}
}, IgfsException.class, null);
}
/**
* Test expected failures for 'append' operation.
*
* @param path File path to append.
* @param create Create file if it doesn't exist yet.
*/
private void assertAppendFails(final String path, final boolean create) {
GridTestUtils.assertThrowsInherited(log, new Callable<Object>() {
@Override public Object call() throws Exception {
igfs.append(path(path), create);
return false;
}
}, IgfsException.class, null);
}
/**
* Test expected failures for 'open' operation.
*
* @param path File path to read.
* @param msg Failure message if expected exception was not thrown.
*/
private void assertOpenFails(final String path, @Nullable String msg) {
GridTestUtils.assertThrowsInherited(log, new Callable<Object>() {
@Override public Object call() throws Exception {
igfs.open(path(path));
return false;
}
}, IgniteException.class, msg);
}
/**
* Validate directory listing.
*
* @param path Directory path to validate listing for.
* @param item List of directory items.
*/
private void assertListDir(String path, String... item) {
Collection<IgfsFile> files = igfs.listFiles(new IgfsPath(path));
List<String> names = new ArrayList<>(item.length);
for (IgfsFile file : files)
names.add(file.path().name());
Arrays.sort(item);
Collections.sort(names);
assertEquals(Arrays.asList(item), names);
}
}