You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by yz...@apache.org on 2015/10/21 16:17:03 UTC

[18/50] [abbrv] ignite git commit: IGNITE-1590: Reworked create and append operations to match overall design.

http://git-wip-us.apache.org/repos/asf/ignite/blob/962fcce3/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsAbstractSelfTest.java
index cc89fd1..b290303 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsAbstractSelfTest.java
@@ -63,7 +63,6 @@ import org.apache.ignite.igfs.IgfsPathNotFoundException;
 import org.apache.ignite.igfs.secondary.IgfsSecondaryFileSystem;
 import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.IgniteInternalFuture;
-import org.apache.ignite.internal.IgniteInterruptedCheckedException;
 import org.apache.ignite.internal.IgniteKernal;
 import org.apache.ignite.internal.processors.cache.GridCacheAdapter;
 import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
@@ -102,10 +101,10 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
     protected static final long BLOCK_SIZE = 32 * 1024 * 1024;
 
     /** Default repeat count. */
-    protected static final int REPEAT_CNT = 10;
+    protected static final int REPEAT_CNT = 5; // Diagnostic: up to 500; Regression: 5
 
     /** Concurrent operations count. */
-    protected static final int OPS_CNT = 32;
+    protected static final int OPS_CNT = 16;
 
     /** Renames count. */
     protected static final int RENAME_CNT = OPS_CNT;
@@ -122,6 +121,9 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
     /** Create count. */
     protected static final int CREATE_CNT = OPS_CNT;
 
+    /** Time to wait until the caches get empty after format. */
+    private static final long CACHE_EMPTY_TIMEOUT = 30_000L;
+
     /** Seed to generate random numbers. */
     protected static final long SEED = System.currentTimeMillis();
 
@@ -761,6 +763,7 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
 
         create(igfs, null, new IgfsPath[] { new IgfsPath("/d/f") }); // "f" is a file.
         checkExist(igfs, igfsSecondary, new IgfsPath("/d/f"));
+        assertTrue(igfs.info(new IgfsPath("/d/f")).isFile());
 
         try {
             igfs.mkdirs(new IgfsPath("/d/f"), null);
@@ -770,6 +773,11 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
         catch (IgfsParentNotDirectoryException ignore) {
             // No-op.
         }
+        catch (IgfsException ignore) {
+            // Currently Ok for Hadoop fs:
+            if (!getClass().getSimpleName().startsWith("Hadoop"))
+                throw ignore;
+        }
 
         try {
             igfs.mkdirs(new IgfsPath("/d/f/something/else"), null);
@@ -779,6 +787,11 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
         catch (IgfsParentNotDirectoryException ignore) {
             // No-op.
         }
+        catch (IgfsException ignore) {
+            // Currently Ok for Hadoop fs:
+            if (!getClass().getSimpleName().startsWith("Hadoop"))
+                throw ignore;
+        }
 
         create(igfs, paths(DIR, SUBDIR), null);
 
@@ -1026,8 +1039,7 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
 
                 try {
                     is = igfs.open(FILE);
-                }
-                finally {
+                } finally {
                     U.closeQuiet(is);
                 }
 
@@ -1041,12 +1053,84 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
      *
      * @throws Exception If failed.
      */
+    @SuppressWarnings({"ConstantConditions", "EmptyTryBlock", "UnusedDeclaration"})
     public void testCreate() throws Exception {
         create(igfs, paths(DIR, SUBDIR), null);
 
         createFile(igfs.asSecondary(), FILE, true, chunk);
 
         checkFile(igfs, igfsSecondary, FILE, chunk);
+
+        try (IgfsOutputStream os = igfs.create(new IgfsPath("/r"), false)) {
+            checkExist(igfs, igfsSecondary, new IgfsPath("/r"));
+            assert igfs.info(new IgfsPath("/r")).isFile();
+        }
+
+        try (IgfsOutputStream os = igfs.create(new IgfsPath("/k/l"), false)) {
+            checkExist(igfs, igfsSecondary, new IgfsPath("/k/l"));
+            assert igfs.info(new IgfsPath("/k/l")).isFile();
+        }
+
+        try {
+            try (IgfsOutputStream os = igfs.create(new IgfsPath("/k/l"), false)) {}
+
+            fail("Exception expected");
+        } catch (IgniteException e) {
+            // okay
+        }
+
+        checkExist(igfs, igfsSecondary, new IgfsPath("/k/l"));
+        assert igfs.info(new IgfsPath("/k/l")).isFile();
+
+        try {
+            try (IgfsOutputStream os = igfs.create(new IgfsPath("/k/l/m"), true)) {}
+
+            fail("Exception expected");
+        } catch (IgniteException e) {
+            // okay
+        }
+        checkNotExist(igfs, igfsSecondary, new IgfsPath("/k/l/m"));
+        checkExist(igfs, igfsSecondary, new IgfsPath("/k/l"));
+        assert igfs.info(new IgfsPath("/k/l")).isFile();
+
+        try {
+            try (IgfsOutputStream os = igfs.create(new IgfsPath("/k/l/m/n/o/p"), true)) {}
+
+            fail("Exception expected");
+        } catch (IgniteException e) {
+            // okay
+        }
+        checkNotExist(igfs, igfsSecondary, new IgfsPath("/k/l/m"));
+        checkExist(igfs, igfsSecondary, new IgfsPath("/k/l"));
+        assert igfs.info(new IgfsPath("/k/l")).isFile();
+
+        igfs.mkdirs(new IgfsPath("/x/y"), null);
+        try {
+            try (IgfsOutputStream os = igfs.create(new IgfsPath("/x/y"), true)) {}
+
+            fail("Exception expected");
+        } catch (IgniteException e) {
+            // okay
+        }
+
+        checkExist(igfs, igfsSecondary, new IgfsPath("/x/y"));
+        assert igfs.info(new IgfsPath("/x/y")).isDirectory();
+
+        try (IgfsOutputStream os = igfs.create(new IgfsPath("/x/y/f"), false)) {
+            assert igfs.info(new IgfsPath("/x/y/f")).isFile();
+        }
+
+        try (IgfsOutputStream os = igfs.create(new IgfsPath("/x/y/z/f"), false)) {
+            assert igfs.info(new IgfsPath("/x/y/z/f")).isFile();
+        }
+
+        try (IgfsOutputStream os = igfs.create(new IgfsPath("/x/y/z/t/f"), false)) {
+            assert igfs.info(new IgfsPath("/x/y/z/t/f")).isFile();
+        }
+
+        try (IgfsOutputStream os = igfs.create(new IgfsPath("/x/y/z/t/t2/t3/t4/t5/f"), false)) {
+            assert igfs.info(new IgfsPath("/x/y/z/t/t2/t3/t4/t5/f")).isFile();
+        }
     }
 
     /**
@@ -1078,8 +1162,7 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
                 try {
                     os1 = igfs.create(FILE, true);
                     os2 = igfs.create(FILE, true);
-                }
-                finally {
+                } finally {
                     U.closeQuiet(os1);
                     U.closeQuiet(os2);
                 }
@@ -1141,26 +1224,47 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
     public void testCreateDeleteNoClose() throws Exception {
         create(igfs, paths(DIR, SUBDIR), null);
 
-        GridTestUtils.assertThrows(log, new Callable<Object>() {
-            @Override public Object call() throws Exception {
-                IgfsOutputStream os = null;
+        IgfsOutputStream os = null;
 
-                try {
-                    os = igfs.create(FILE, true);
+        IgniteUuid id = null;
+
+        try {
+            os = igfs.create(FILE, false);
+
+            id = igfs.context().meta().fileId(FILE);
+
+            assert id != null;
+
+            boolean del = igfs.delete(FILE, false);
+
+            assertTrue(del);
+            assertFalse(igfs.exists(FILE));
+            // The id still exists in meta cache since
+            // it is locked for writing and just moved to TRASH.
+            // Delete worker cannot delete it for that reason:
+            assertTrue(igfs.context().meta().exists(id));
+
+            os.write(chunk);
 
-                    igfs.format();
+            os.close();
+        }
+        finally {
+            U.closeQuiet(os);
+        }
 
-                    os.write(chunk);
+        final IgniteUuid id0 = id;
 
-                    os.close();
+        // Delete worker should delete the file once its output stream is finally closed:
+        GridTestUtils.waitForCondition(new GridAbsPredicate() {
+            @Override public boolean apply() {
+                try {
+                    return !igfs.context().meta().exists(id0);
                 }
-                finally {
-                    U.closeQuiet(os);
+                catch (IgniteCheckedException ice) {
+                    throw new IgniteException(ice);
                 }
-
-                return null;
             }
-        }, IOException.class, "File was concurrently deleted: " + FILE);
+        }, 5_000L);
     }
 
     /**
@@ -1171,29 +1275,47 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
     public void testCreateDeleteParentNoClose() throws Exception {
         create(igfs, paths(DIR, SUBDIR), null);
 
-        GridTestUtils.assertThrows(log, new Callable<Object>() {
-            @Override public Object call() throws Exception {
-                IgfsOutputStream os = null;
+        IgfsOutputStream os = null;
 
-                try {
-                    os = igfs.create(FILE, true);
+        IgniteUuid id = null;
+
+        try {
+            os = igfs.create(FILE, false);
+
+            id = igfs.context().meta().fileId(FILE);
 
-                    IgniteUuid id = igfs.context().meta().fileId(FILE);
+            assert id != null;
 
-                    igfs.delete(SUBDIR, true); // Since GG-4911 we allow deletes in this case.
+            boolean del = igfs.delete(SUBDIR, true);
 
-                    while (igfs.context().meta().exists(id))
-                        U.sleep(100);
+            assertTrue(del);
+            assertFalse(igfs.exists(FILE));
+            // The id still exists in meta cache since
+            // it is locked for writing and just moved to TRASH.
+            // Delete worker cannot delete it for that reason:
+            assertTrue(igfs.context().meta().exists(id));
 
-                    os.close();
+            os.write(chunk);
+
+            os.close();
+        }
+        finally {
+            U.closeQuiet(os);
+        }
+
+        final IgniteUuid id0 = id;
+
+        // Delete worker should delete the file once its output stream is finally closed:
+        GridTestUtils.waitForCondition(new GridAbsPredicate() {
+            @Override public boolean apply() {
+                try {
+                    return !igfs.context().meta().exists(id0);
                 }
-                finally {
-                    U.closeQuiet(os);
+                catch (IgniteCheckedException ice) {
+                    throw new IgniteException(ice);
                 }
-
-                return null;
             }
-        }, IOException.class, "File was concurrently deleted: " + FILE);
+        }, 5_000L);
     }
 
     /**
@@ -1221,6 +1343,41 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
     }
 
     /**
+     * Checks simple write.
+     *
+     * @throws Exception On error.
+     */
+    public void testSimpleWrite() throws Exception {
+        IgfsPath path = new IgfsPath("/file1");
+
+        IgfsOutputStream os = igfs.create(path, 128, true/*overwrite*/, null, 0, 256, null);
+
+        os.write(chunk);
+
+        os.close();
+
+        assert igfs.exists(path);
+        checkFileContent(igfs, path, chunk);
+
+        os = igfs.create(path, 128, true/*overwrite*/, null, 0, 256, null);
+
+        assert igfs.exists(path);
+
+        os.write(chunk);
+
+        assert igfs.exists(path);
+
+        os.write(chunk);
+
+        assert igfs.exists(path);
+
+        os.close();
+
+        assert igfs.exists(path);
+        checkFileContent(igfs, path, chunk, chunk);
+    }
+
+    /**
      * Ensure consistency of data during file creation.
      *
      * @throws Exception If failed.
@@ -1229,17 +1386,17 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
         final AtomicInteger ctr = new AtomicInteger();
         final AtomicReference<Exception> err = new AtomicReference<>();
 
-        int threadCnt = 10;
+        final int threadCnt = 10;
 
         multithreaded(new Runnable() {
             @Override public void run() {
                 int idx = ctr.incrementAndGet();
 
-                IgfsPath path = new IgfsPath("/file" + idx);
+                final IgfsPath path = new IgfsPath("/file" + idx);
 
                 try {
                     for (int i = 0; i < REPEAT_CNT; i++) {
-                        IgfsOutputStream os = igfs.create(path, 128, true, null, 0, 256, null);
+                        IgfsOutputStream os = igfs.create(path, 128, true/*overwrite*/, null, 0, 256, null);
 
                         os.write(chunk);
 
@@ -1275,11 +1432,11 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
 
         igfs.create(FILE, false).close();
 
-        int threadCnt = 5;
+        int threadCnt = 50;
 
         IgniteInternalFuture<?> fut = multithreadedAsync(new Runnable() {
             @Override public void run() {
-                while (!stop.get()) {
+                while (!stop.get() && err.get() == null) {
                     IgfsOutputStream os = null;
 
                     try {
@@ -1287,27 +1444,43 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
 
                         os.write(chunk);
 
-                        U.sleep(50);
-
                         os.close();
 
                         createCtr.incrementAndGet();
                     }
-                    catch (IgniteInterruptedCheckedException | IgniteException ignore) {
-                        try {
-                            U.sleep(10);
-                        }
-                        catch (IgniteInterruptedCheckedException ignored) {
-                            // nO-op.
+                    catch (IgniteException e) {
+                        Throwable[] chain = X.getThrowables(e);
+
+                        Throwable cause = chain[chain.length - 1];
+
+                        if (!e.getMessage().startsWith("Failed to overwrite file (file is opened for writing)")
+                                && (cause == null
+                                    || !cause.getMessage().startsWith("Failed to overwrite file (file is opened for writing)"))) {
+
+                            System.out.println("Failed due to IgniteException exception. Cause:");
+                            cause.printStackTrace(System.out);
+
+                            err.compareAndSet(null, e);
                         }
                     }
                     catch (IOException e) {
-                        // We can ignore concurrent deletion exception since we override the file.
-                        if (!e.getMessage().startsWith("File was concurrently deleted"))
-                            err.compareAndSet(null, e);
+                        err.compareAndSet(null, e);
+
+                        Throwable[] chain = X.getThrowables(e);
+
+                        Throwable cause = chain[chain.length - 1];
+
+                        System.out.println("Failed due to IOException exception. Cause:");
+                        cause.printStackTrace(System.out);
                     }
                     finally {
-                        U.closeQuiet(os);
+                        if (os != null)
+                            try {
+                                os.close();
+                            }
+                            catch (IOException ioe) {
+                                throw new IgniteException(ioe);
+                            }
                     }
                 }
             }
@@ -1315,7 +1488,9 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
 
         long startTime = U.currentTimeMillis();
 
-        while (createCtr.get() < 50 && U.currentTimeMillis() - startTime < 60 * 1000)
+        while (err.get() == null
+                && createCtr.get() < 500
+                && U.currentTimeMillis() - startTime < 60 * 1000)
             U.sleep(100);
 
         stop.set(true);
@@ -1324,8 +1499,11 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
 
         awaitFileClose(igfs.asSecondary(), FILE);
 
-        if (err.get() != null)
+        if (err.get() != null) {
+            X.println("Test failed: rethrowing first error: " + err.get());
+
             throw err.get();
+        }
 
         checkFileContent(igfs, FILE, chunk);
     }
@@ -1336,13 +1514,131 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
      * @throws Exception If failed.
      */
     public void testAppend() throws Exception {
+        if (dual)
+            fail("Test fails in DUAL modes, see https://issues.apache.org/jira/browse/IGNITE-1631");
+
         create(igfs, paths(DIR, SUBDIR), null);
 
+        assert igfs.exists(SUBDIR);
+
         createFile(igfs, FILE, true, BLOCK_SIZE, chunk);
 
+        checkFile(igfs, igfsSecondary, FILE, chunk);
+
         appendFile(igfs, FILE, chunk);
 
         checkFile(igfs, igfsSecondary, FILE, chunk, chunk);
+
+        // Test create via append:
+        IgfsPath path2 = FILE2;
+
+        IgfsOutputStream os = null;
+
+        try {
+            os = igfs.append(path2, true/*create*/);
+
+            writeFileChunks(os, chunk);
+        }
+        finally {
+            U.closeQuiet(os);
+
+            awaitFileClose(igfs.asSecondary(), path2);
+        }
+
+        try {
+            os = igfs.append(path2, false/*create*/);
+
+            writeFileChunks(os, chunk);
+        }
+        finally {
+            U.closeQuiet(os);
+
+            awaitFileClose(igfs.asSecondary(), path2);
+        }
+
+        checkFile(igfs, igfsSecondary, path2, chunk, chunk);
+
+        // Negative append (create == false):
+        try {
+            try (IgfsOutputStream os0 = igfs.append(new IgfsPath("/should-not-be-created"), false)) {}
+
+            fail("Exception expected");
+        } catch (IgniteException e) {
+            // okay
+        }
+        checkNotExist(igfs, igfsSecondary, new IgfsPath("/d1"));
+
+        // Positive mkdirs via append:
+        try (IgfsOutputStream os0 = igfs.append(new IgfsPath("/k/l"), true)) {
+            checkExist(igfs, igfsSecondary, new IgfsPath("/k/l"));
+            assert igfs.info(new IgfsPath("/k/l")).isFile();
+        }
+
+        // Negative append (file is immediate parent):
+        try {
+            try (IgfsOutputStream os0 = igfs.append(new IgfsPath("/k/l/m"), true)) {}
+
+            fail("Exception expected");
+        } catch (IgniteException e) {
+            // okay
+        }
+        checkNotExist(igfs, igfsSecondary, new IgfsPath("/k/l/m"));
+        checkExist(igfs, igfsSecondary, new IgfsPath("/k/l"));
+        assert igfs.info(new IgfsPath("/k/l")).isFile();
+
+        // Negative append (file is in the parent chain):
+        try {
+            try (IgfsOutputStream os0 = igfs.append(new IgfsPath("/k/l/m/n/o/p"), true)) {}
+
+            fail("Exception expected");
+        } catch (IgniteException e) {
+            // okay
+        }
+        checkNotExist(igfs, igfsSecondary, new IgfsPath("/k/l/m"));
+        checkExist(igfs, igfsSecondary, new IgfsPath("/k/l"));
+        assert igfs.info(new IgfsPath("/k/l")).isFile();
+
+        // Negative append (target is a directory):
+        igfs.mkdirs(new IgfsPath("/x/y"), null);
+        checkExist(igfs, igfsSecondary, new IgfsPath("/x/y"));
+        assert igfs.info(new IgfsPath("/x/y")).isDirectory();
+        try {
+            try (IgfsOutputStream os0 = igfs.append(new IgfsPath("/x/y"), true)) {}
+
+            fail("Exception expected");
+        } catch (IgniteException e) {
+            // okay
+        }
+
+        // Positive append with create
+        try (IgfsOutputStream os0 = igfs.append(new IgfsPath("/x/y/f"), true)) {
+            assert igfs.info(new IgfsPath("/x/y/f")).isFile();
+        }
+
+        // Positive append with create & 1 mkdirs:
+        try (IgfsOutputStream os0 = igfs.append(new IgfsPath("/x/y/z/f"), true)) {
+            assert igfs.info(new IgfsPath("/x/y/z/f")).isFile();
+        }
+
+        // Positive append with create & 2 mkdirs:
+        try (IgfsOutputStream os0 = igfs.append(new IgfsPath("/x/y/z/t/f"), true)) {
+            assert igfs.info(new IgfsPath("/x/y/z/t/f")).isFile();
+        }
+
+        // Positive mkdirs create & many mkdirs:
+        try (IgfsOutputStream os0 = igfs.append(new IgfsPath("/x/y/z/t/t2/t3/t4/t5/f"), true)) {
+            assert igfs.info(new IgfsPath("/x/y/z/t/t2/t3/t4/t5/f")).isFile();
+        }
+
+        // Negative mkdirs via append (create == false):
+        try {
+            try (IgfsOutputStream os0 = igfs.append(new IgfsPath("/d1/d2/d3/f"), false)) {}
+
+            fail("Exception expected");
+        } catch (IgniteException e) {
+            // okay
+        }
+        checkNotExist(igfs, igfsSecondary, new IgfsPath("/d1"));
     }
 
     /**
@@ -1447,26 +1743,44 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
 
         createFile(igfs.asSecondary(), FILE, false);
 
-        GridTestUtils.assertThrows(log, new Callable<Object>() {
-            @Override public Object call() throws Exception {
-                IgfsOutputStream os = null;
+        IgfsOutputStream os = null;
+        IgniteUuid id = null;
 
-                try {
-                    os = igfs.append(FILE, false);
+        try {
+            id = igfs.context().meta().fileId(FILE);
 
-                    igfs.format();
+            os = igfs.append(FILE, false);
 
-                    os.write(chunk);
+            boolean del = igfs.delete(FILE, false);
 
-                    os.close();
-                }
-                finally {
-                    U.closeQuiet(os);
-                }
+            assertTrue(del);
+            assertFalse(igfs.exists(FILE));
+            assertTrue(igfs.context().meta().exists(id)); // id still exists in meta cache since
+            // it is locked for writing and just moved to TRASH.
+            // Delete worker cannot delete it for that reason.
 
-                return null;
+            os.write(chunk);
+
+            os.close();
+        }
+        finally {
+            U.closeQuiet(os);
+        }
+
+        assert id != null;
+
+        final IgniteUuid id0 = id;
+
+        // Delete worker should delete the file once its output stream is finally closed:
+        GridTestUtils.waitForCondition(new GridAbsPredicate() {
+            @Override public boolean apply() {
+                try {
+                    return !igfs.context().meta().exists(id0);
+                } catch (IgniteCheckedException ice) {
+                    throw new IgniteException(ice);
+                }
             }
-        }, IOException.class, "File was concurrently deleted: " + FILE);
+        }, 5_000L);
     }
 
     /**
@@ -1479,31 +1793,44 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
 
         createFile(igfs.asSecondary(), FILE, false);
 
-        GridTestUtils.assertThrows(log, new Callable<Object>() {
-            @Override public Object call() throws Exception {
-                IgfsOutputStream os = null;
+        IgfsOutputStream os = null;
+        IgniteUuid id = null;
 
-                try {
-                    IgniteUuid id = igfs.context().meta().fileId(FILE);
+        try {
+            id = igfs.context().meta().fileId(FILE);
 
-                    os = igfs.append(FILE, false);
+            os = igfs.append(FILE, false);
 
-                    igfs.delete(SUBDIR, true); // Since GG-4911 we allow deletes in this case.
+            boolean del = igfs.delete(SUBDIR, true); // Since GG-4911 we allow deletes in this case.
 
-                    for (int i = 0; i < 100 && igfs.context().meta().exists(id); i++)
-                        U.sleep(100);
+            assertTrue(del);
+            assertFalse(igfs.exists(FILE));
+            assertTrue(igfs.context().meta().exists(id)); // id still exists in meta cache since
+            // it is locked for writing and just moved to TRASH.
+            // Delete worker cannot delete it for that reason.
 
-                    os.write(chunk);
+            os.write(chunk);
 
-                    os.close();
-                }
-                finally {
-                    U.closeQuiet(os);
-                }
+            os.close();
+        }
+        finally {
+            U.closeQuiet(os);
+        }
 
-                return null;
+        assert id != null;
+
+        final IgniteUuid id0 = id;
+
+        // Delete worker should delete the file once its output stream is finally closed:
+        GridTestUtils.waitForCondition(new GridAbsPredicate() {
+            @Override public boolean apply() {
+                try {
+                    return !igfs.context().meta().exists(id0);
+                } catch (IgniteCheckedException ice) {
+                    throw new IgniteException(ice);
+                }
             }
-        }, IOException.class, "File was concurrently deleted: " + FILE);
+        }, 5_000L);
     }
 
     /**
@@ -1594,11 +1921,11 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
 
         igfs.create(FILE, false).close();
 
-        int threadCnt = 5;
+        int threadCnt = 50;
 
         IgniteInternalFuture<?> fut = multithreadedAsync(new Runnable() {
             @Override public void run() {
-                while (!stop.get()) {
+                while (!stop.get() && err.get() == null) {
                     IgfsOutputStream os = null;
 
                     try {
@@ -1606,25 +1933,31 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
 
                         os.write(chunk);
 
-                        U.sleep(50);
-
                         os.close();
 
                         chunksCtr.incrementAndGet();
                     }
-                    catch (IgniteInterruptedCheckedException | IgniteException ignore) {
-                        try {
-                            U.sleep(10);
-                        }
-                        catch (IgniteInterruptedCheckedException ignored) {
-                            // nO-op.
-                        }
+                    catch (IgniteException e) {
+                        Throwable[] chain = X.getThrowables(e);
+
+                        Throwable cause = chain[chain.length - 1];
+
+                        if (!e.getMessage().startsWith("Failed to open file (file is opened for writing)")
+                                && (cause == null
+                                || !cause.getMessage().startsWith("Failed to open file (file is opened for writing)")))
+                            err.compareAndSet(null, e);
                     }
                     catch (IOException e) {
                         err.compareAndSet(null, e);
                     }
                     finally {
-                        U.closeQuiet(os);
+                        if (os != null)
+                            try {
+                                os.close();
+                            }
+                            catch (IOException ioe) {
+                                throw new IgniteException(ioe);
+                            }
                     }
                 }
             }
@@ -1632,7 +1965,8 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
 
         long startTime = U.currentTimeMillis();
 
-        while (chunksCtr.get() < 50 && U.currentTimeMillis() - startTime < 60 * 1000)
+        while (err.get() == null
+                && chunksCtr.get() < 50 && U.currentTimeMillis() - startTime < 60 * 1000)
             U.sleep(100);
 
         stop.set(true);
@@ -1641,8 +1975,11 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
 
         awaitFileClose(igfs.asSecondary(), FILE);
 
-        if (err.get() != null)
+        if (err.get() != null) {
+            X.println("Test failed: rethrowing first error: " + err.get());
+
             throw err.get();
+        }
 
         byte[][] data = new byte[chunksCtr.get()][];
 
@@ -2019,8 +2356,6 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
      * @throws Exception If failed.
      */
     public void testDeadlocksCreate() throws Exception {
-        assert false : "https://issues.apache.org/jira/browse/IGNITE-1590";
-
         checkDeadlocksRepeat(5, 2, 2, 2, 0, 0, 0, 0, CREATE_CNT);
     }
 
@@ -2030,8 +2365,6 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
      * @throws Exception If failed.
      */
     public void testDeadlocks() throws Exception {
-        assert false : "https://issues.apache.org/jira/browse/IGNITE-1590";
-
         checkDeadlocksRepeat(5, 2, 2, 2,  RENAME_CNT, DELETE_CNT, UPDATE_CNT, MKDIRS_CNT, CREATE_CNT);
     }
 
@@ -2057,6 +2390,9 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
             try {
                 checkDeadlocks(lvlCnt, childrenDirPerLvl, childrenFilePerLvl, primaryLvlCnt, renCnt, delCnt,
                     updateCnt, mkdirsCnt, createCnt);
+
+                if (i % 10 == 0)
+                    X.println(" - " + i);
             }
             finally {
                 clear(igfs, igfsSecondary);
@@ -2679,7 +3015,8 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
 
                     read = is.read(buf);
 
-                    assert read == chunk.length : "Chunk #" + chunkIdx + " was not read fully.";
+                    assert read == chunk.length : "Chunk #" + chunkIdx + " was not read fully:" +
+                            " read=" + read + ", expected=" + chunk.length;
                     assert Arrays.equals(chunk, buf) : "Bad chunk [igfs=" + uni.name() + ", chunkIdx=" + chunkIdx +
                         ", expected=" + Arrays.toString(chunk) + ", actual=" + Arrays.toString(buf) + ']';
 
@@ -2800,19 +3137,57 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
         // Clear igfs.
         igfs.format();
 
-        final IgniteFileSystem igfs0 = igfs;
+        int prevDifferentSize = Integer.MAX_VALUE; // Previous different size.
+        int size;
+        int constCnt = 0, totalCnt = 0;
+        final int constThreshold = 20;
+        final long sleepPeriod = 500L;
+        final long totalThreshold = CACHE_EMPTY_TIMEOUT / sleepPeriod;
 
-        if (!GridTestUtils.waitForCondition(new GridAbsPredicate() {
-            @Override public boolean apply() {
-                return isEmpty(igfs0);
+        while (true) {
+            size = sumCacheSize(igfs);
+
+            if (size <= 2)
+                return; // Caches are cleared, we're done. (2 because ROOT & TRASH always exist).
+
+            X.println("Sum size: " + size);
+
+            if (size > prevDifferentSize) {
+                X.println("Summary cache size has grown unexpectedly: size=" + size + ", prevSize=" + prevDifferentSize);
+
+                break;
             }
-        }, 10_000L)) {
-            dumpCache("MetaCache" , getMetaCache(igfs));
 
-            dumpCache("DataCache" , getDataCache(igfs));
+            if (totalCnt > totalThreshold) {
+                X.println("Timeout exceeded.");
 
-            assert false;
+                break;
+            }
+
+            if (size == prevDifferentSize) {
+                constCnt++;
+
+                if (constCnt == constThreshold) {
+                    X.println("Summary cache size stays unchanged for too long: size=" + size);
+
+                    break;
+                }
+            } else {
+                constCnt = 0;
+
+                prevDifferentSize = size; // renew;
+            }
+
+            Thread.sleep(sleepPeriod);
+
+            totalCnt++;
         }
+
+        dumpCache("MetaCache" , getMetaCache(igfs));
+
+        dumpCache("DataCache" , getDataCache(igfs));
+
+        fail("Caches are not empty.");
     }
 
     /**
@@ -2831,37 +3206,12 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
     }
 
     /**
-     * Answers if the given IGFS is empty.
-     *
-     * @param igfs IGFS to operate on.
-     * @return True if IGFS is empty.
+     * Gets summary IGFS cache size.
+     * @param igfs The IGFS to measure.
+     * @return data cache size + meta cache size.
      */
-    private static boolean isEmpty(IgniteFileSystem igfs) {
-        GridCacheAdapter dataCache = getDataCache(igfs);
-
-        assert dataCache != null;
-
-        int size1 = dataCache.size();
-
-        if (size1 > 0) {
-            X.println("Data cache size = " + size1);
-
-            return false;
-        }
-
-        GridCacheAdapter metaCache = getMetaCache(igfs);
-
-        assert metaCache != null;
-
-        int size2 = metaCache.size();
-
-        if (size2 > 2) {
-            X.println("Meta cache size = " + size2);
-
-            return false;
-        }
-
-        return true;
+    private static int sumCacheSize(IgniteFileSystem igfs) {
+        return getMetaCache(igfs).size() + getDataCache(igfs).size();
     }
 
     /**
@@ -2880,4 +3230,9 @@ public abstract class IgfsAbstractSelfTest extends IgfsCommonAbstractTest {
         // Clear the filesystem.
         uni.format();
     }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        clear(igfs, igfsSecondary);
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/962fcce3/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsDataManagerSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsDataManagerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsDataManagerSelfTest.java
index 6266ab4..84462fd 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsDataManagerSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsDataManagerSelfTest.java
@@ -165,7 +165,9 @@ public class IgfsDataManagerSelfTest extends IgfsCommonAbstractTest {
     public void testDataStoring() throws Exception {
         for (int i = 0; i < 10; i++) {
             IgfsPath path = new IgfsPath();
-            IgfsFileInfo info = new IgfsFileInfo(200, null, false, null);
+
+            IgfsFileInfo info = new IgfsFileInfo(200, 0L, null, IgfsMetaManager.DELETE_LOCK_ID,
+                    false, null);
 
             assertNull(mgr.dataBlock(info, path, 0, null).get());
 
@@ -246,7 +248,9 @@ public class IgfsDataManagerSelfTest extends IgfsCommonAbstractTest {
 
         for (int i = 0; i < 10; i++) {
             IgfsPath path = new IgfsPath();
-            IgfsFileInfo info = new IgfsFileInfo(blockSize, null, false, null);
+
+            IgfsFileInfo info = new IgfsFileInfo(blockSize, 0L, null, IgfsMetaManager.DELETE_LOCK_ID,
+                false, null);
 
             assertNull(mgr.dataBlock(info, path, 0, null).get());
 
@@ -333,7 +337,10 @@ public class IgfsDataManagerSelfTest extends IgfsCommonAbstractTest {
 
         for (int i = 0; i < 10; i++) {
             IgfsPath path = new IgfsPath();
-            IgfsFileInfo info = new IgfsFileInfo(blockSize, null, false, null);
+
+            IgfsFileInfo info =
+                new IgfsFileInfo(blockSize, 0L, null, IgfsMetaManager.DELETE_LOCK_ID,
+                    false, null);
 
             IgfsFileAffinityRange range = new IgfsFileAffinityRange();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/962fcce3/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMetaManagerSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMetaManagerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMetaManagerSelfTest.java
index 4072636..df519ed 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMetaManagerSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMetaManagerSelfTest.java
@@ -26,7 +26,6 @@ import org.apache.ignite.IgniteCheckedException;
 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.IgfsGroupDataBlocksKeyMapper;
 import org.apache.ignite.igfs.IgfsPath;
@@ -46,7 +45,6 @@ import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
 import static org.apache.ignite.internal.processors.igfs.IgfsFileInfo.ROOT_ID;
 import static org.apache.ignite.testframework.GridTestUtils.assertThrows;
 import static org.apache.ignite.testframework.GridTestUtils.assertThrowsInherited;
-import static org.apache.ignite.testframework.GridTestUtils.getFieldValue;
 
 /**
  * {@link IgfsMetaManager} test case.
@@ -143,17 +141,20 @@ public class IgfsMetaManagerSelfTest extends IgfsCommonAbstractTest {
     public void testUpdateProperties() throws Exception {
         assertEmpty(mgr.directoryListing(ROOT_ID));
 
-        IgfsFileInfo dir = new IgfsFileInfo(true, null);
-        IgfsFileInfo file = new IgfsFileInfo(new IgfsFileInfo(400, null, false, null), 1);
+        assertTrue(mgr.mkdirs(new IgfsPath("/dir"), IgfsImpl.DFLT_DIR_META));
+        assertNotNull(mgr.create(new IgfsPath("/file"), false, false, null, 400, null, false, null));
 
-        assertNull(mgr.putIfAbsent(ROOT_ID, "dir", dir));
-        assertNull(mgr.putIfAbsent(ROOT_ID, "file", file));
+        IgfsListingEntry dirEntry = mgr.directoryListing(ROOT_ID).get("dir");
+        assertNotNull(dirEntry);
+        assertTrue(dirEntry.isDirectory());
+        IgfsFileInfo dir = mgr.info(dirEntry.fileId());
 
-        assertEquals(F.asMap("dir", new IgfsListingEntry(dir), "file", new IgfsListingEntry(file)),
-            mgr.directoryListing(ROOT_ID));
+        IgfsListingEntry fileEntry = mgr.directoryListing(ROOT_ID).get("file");
+        assertNotNull(fileEntry);
+        assertTrue(!fileEntry.isDirectory());
+        IgfsFileInfo file = mgr.info(fileEntry.fileId());
 
-        assertEquals(dir, mgr.info(dir.id()));
-        assertEquals(file, mgr.info(file.id()));
+        assertEquals(2, mgr.directoryListing(ROOT_ID).size());
 
         for (IgniteBiTuple<IgniteUuid, String> tup: Arrays.asList(F.t(dir.id(), "dir"), F.t(file.id(), "file"))) {
             IgniteUuid fileId = tup.get1();
@@ -167,38 +168,63 @@ public class IgfsMetaManagerSelfTest extends IgfsCommonAbstractTest {
 
             IgfsFileInfo info = mgr.info(fileId);
 
-            assertNull("Expects empty properties are not stored: " + info, getFieldValue(info, "props"));
-            assertEquals("Expects empty properties are not stored: " + info, Collections.<String, String>emptyMap(),
-                info.properties());
+            assertNull("Unexpected stored properties: " + info, info.properties().get(key1));
+            assertNull("Unexpected stored properties: " + info, info.properties().get(key2));
 
             info = mgr.updateProperties(ROOT_ID, fileId, fileName, F.asMap(key1, "1"));
 
-            assertEquals("Unexpected stored properties: " + info, F.asMap(key1, "1"), info.properties());
+            assertEquals("Unexpected stored properties: " + info, "1", info.properties().get(key1));
 
             info = mgr.updateProperties(ROOT_ID, fileId, fileName, F.asMap(key2, "2"));
 
-            assertEquals("Unexpected stored properties: " + info, F.asMap(key1, "1", key2, "2"), info.properties());
+           // assertEquals("Unexpected stored properties: " + info, F.asMap(key1, "1", key2, "2"), info.properties());
+            assertEquals("Unexpected stored properties: " + info, "1", info.properties().get(key1));
+            assertEquals("Unexpected stored properties: " + info, "2", info.properties().get(key2));
 
             info = mgr.updateProperties(ROOT_ID, fileId, fileName, F.<String, String>asMap(key1, null));
 
-            assertEquals("Unexpected stored properties: " + info, F.asMap(key2, "2"), info.properties());
+            assertEquals("Unexpected stored properties: " + info, "2", info.properties().get(key2));
 
             info = mgr.updateProperties(ROOT_ID, fileId, fileName, F.<String, String>asMap(key2, null));
 
-            assertNull("Expects empty properties are not stored: " + info, getFieldValue(info, "props"));
-            assertEquals("Expects empty properties are not stored: " + info, Collections.<String, String>emptyMap(),
-                info.properties());
+            assertNull("Unexpected stored properties: " + info, info.properties().get(key1));
+            assertNull("Unexpected stored properties: " + info, info.properties().get(key2));
 
             assertNull(mgr.updateProperties(ROOT_ID, fileId, "not_exists", F.<String, String>asMap(key2, null)));
         }
 
-        mgr.removeIfEmpty(ROOT_ID, "dir", dir.id(), new IgfsPath("/dir"), true);
-        mgr.removeIfEmpty(ROOT_ID, "file", file.id(), new IgfsPath("/file"), true);
+        mgr.softDelete(new IgfsPath("/dir"), true);
+        mgr.softDelete(new IgfsPath("/file"), false);
 
         assertNull(mgr.updateProperties(ROOT_ID, dir.id(), "dir", F.asMap("p", "7")));
         assertNull(mgr.updateProperties(ROOT_ID, file.id(), "file", F.asMap("q", "8")));
     }
 
+    private IgfsFileInfo mkdirsAndGetInfo(String path) throws IgniteCheckedException {
+        IgfsPath p = path(path);
+
+        mgr.mkdirs(p, IgfsImpl.DFLT_DIR_META);
+
+        IgniteUuid id = mgr.fileId(p);
+
+        IgfsFileInfo info = mgr.info(id);
+
+        assert info.isDirectory();
+
+        return info;
+    }
+
+    private IgfsFileInfo createFileAndGetInfo(String path) throws IgniteCheckedException {
+        IgfsPath p = path(path);
+
+        IgniteBiTuple<IgfsFileInfo, IgniteUuid> t2 = mgr.create(p, false, false, null, 400, null, false, null);
+
+        assert t2 != null;
+        assert !t2.get1().isDirectory();
+
+        return t2.get1();
+    }
+
     /**
      * Test file system structure in meta-cache.
      *
@@ -206,31 +232,22 @@ public class IgfsMetaManagerSelfTest extends IgfsCommonAbstractTest {
      */
     public void testStructure() throws Exception {
         IgfsFileInfo rootInfo = new IgfsFileInfo();
+
         // Test empty structure.
         assertEmpty(mgr.directoryListing(ROOT_ID));
         assertEquals(rootInfo, mgr.info(ROOT_ID));
         assertEquals(F.asMap(ROOT_ID, rootInfo), mgr.infos(Arrays.asList(ROOT_ID)));
 
-        IgfsFileInfo a = new IgfsFileInfo(true, null);
-        IgfsFileInfo b = new IgfsFileInfo(true, null);
-        IgfsFileInfo k = new IgfsFileInfo(true, null);
-        IgfsFileInfo z = new IgfsFileInfo(true, null);
-
-        IgfsFileInfo f1 = new IgfsFileInfo(400, null, false, null);
-        IgfsFileInfo f2 = new IgfsFileInfo(new IgfsFileInfo(400, null, false, null), 0);
-        IgfsFileInfo f3 = new IgfsFileInfo(new IgfsFileInfo(400, null, false, null), 200000L);
+        // Directories:
+        IgfsFileInfo a = mkdirsAndGetInfo("/a");
+        IgfsFileInfo b = mkdirsAndGetInfo("/a/b");
+        IgfsFileInfo k = mkdirsAndGetInfo("/a/b/k");
+        IgfsFileInfo z = mkdirsAndGetInfo("/a/k");
 
-        // Validate 'add file' operation.
-        assertNull(mgr.putIfAbsent(ROOT_ID, "a", a));
-        assertNull(mgr.putIfAbsent(ROOT_ID, "f1", f1));
-        assertNull(mgr.putIfAbsent(a.id(), "b", b));
-        assertNull(mgr.putIfAbsent(a.id(), "k", z));
-        assertNull(mgr.putIfAbsent(b.id(), "k", k));
-        assertNull(mgr.putIfAbsent(a.id(), "f2", f2));
-        assertNull(mgr.putIfAbsent(b.id(), "f3", f3));
-
-        assertEquals(b.id(), mgr.putIfAbsent(a.id(), "b", f3));
-        expectsPutIfAbsentFail(a.id(), "c", f3, "Failed to add file details into cache");
+        // Files:
+        IgfsFileInfo f1 = createFileAndGetInfo("/f1");
+        IgfsFileInfo f2 = createFileAndGetInfo("/a/f2");
+        IgfsFileInfo f3 = createFileAndGetInfo("/a/b/f3");
 
         assertEquals(F.asMap("a", new IgfsListingEntry(a), "f1", new IgfsListingEntry(f1)),
             mgr.directoryListing(ROOT_ID));
@@ -315,25 +332,12 @@ public class IgfsMetaManagerSelfTest extends IgfsCommonAbstractTest {
 
         mgr.move(path("/a2"), path("/a"));
 
-        // Validate 'remove' operation.
-        for (int i = 0; i < 100; i++) {
-            // One of participants doesn't exist.
-            assertNull(mgr.removeIfEmpty(ROOT_ID, "a", IgniteUuid.randomUuid(), new IgfsPath("/a"), true));
-            assertNull(mgr.removeIfEmpty(IgniteUuid.randomUuid(), "a", IgniteUuid.randomUuid(),
-                new IgfsPath("/" + IgniteUuid.randomUuid() + "/a"), true));
-        }
-
-        expectsRemoveFail(ROOT_ID, "a", a.id(), new IgfsPath("/a"),
-            "Failed to remove file (directory is not empty)");
-        expectsRemoveFail(a.id(), "b", b.id(), new IgfsPath("/a/b"),
-            "Failed to remove file (directory is not empty)");
-        assertNull(mgr.removeIfEmpty(ROOT_ID, "a", f1.id(), new IgfsPath("/a"), true));
-        assertNull(mgr.removeIfEmpty(a.id(), "b", f1.id(), new IgfsPath("/a/b"), true));
+        IgniteUuid del = mgr.softDelete(path("/a/b/f3"), false);
 
-        assertEquals(f3, mgr.removeIfEmpty(b.id(), "f3", f3.id(), new IgfsPath("/a/b/f3"), true));
+        assertEquals(f3.id(), del);
 
         assertEquals(F.asMap("a", new IgfsListingEntry(a), "f1", new IgfsListingEntry(f1)),
-            mgr.directoryListing(ROOT_ID));
+                mgr.directoryListing(ROOT_ID));
 
         assertEquals(
             F.asMap("b", new IgfsListingEntry(b),
@@ -342,7 +346,9 @@ public class IgfsMetaManagerSelfTest extends IgfsCommonAbstractTest {
 
         assertEmpty(mgr.directoryListing(b.id()));
 
-        assertEquals(b, mgr.removeIfEmpty(a.id(), "b", b.id(), new IgfsPath("/a/b"), true));
+        //assertEquals(b, mgr.removeIfEmpty(a.id(), "b", b.id(), new IgfsPath("/a/b"), true));
+        del = mgr.softDelete(path("/a/b"), false);
+        assertEquals(b.id(), del);
 
         assertEquals(F.asMap("a", new IgfsListingEntry(a), "f1", new IgfsListingEntry(f1)),
             mgr.directoryListing(ROOT_ID));
@@ -362,7 +368,8 @@ public class IgfsMetaManagerSelfTest extends IgfsCommonAbstractTest {
         assertEquals(f2.id(), newF2.id());
         assertNotSame(f2, newF2);
 
-        assertEquals(newF2, mgr.removeIfEmpty(a.id(), "f2", f2.id(), new IgfsPath("/a/f2"), true));
+        del = mgr.softDelete(path("/a/f2"), false);
+        assertEquals(f2.id(), del);
 
         assertEquals(F.asMap("a", new IgfsListingEntry(a), "f1", new IgfsListingEntry(f1)),
             mgr.directoryListing(ROOT_ID));
@@ -370,14 +377,16 @@ public class IgfsMetaManagerSelfTest extends IgfsCommonAbstractTest {
         assertEmpty(mgr.directoryListing(a.id()));
         assertEmpty(mgr.directoryListing(b.id()));
 
-        assertEquals(f1, mgr.removeIfEmpty(ROOT_ID, "f1", f1.id(), new IgfsPath("/f1"), true));
+        del = mgr.softDelete(path("/f1"), false);
+        assertEquals(f1.id(), del);
 
         assertEquals(F.asMap("a", new IgfsListingEntry(a)), mgr.directoryListing(ROOT_ID));
 
         assertEmpty(mgr.directoryListing(a.id()));
         assertEmpty(mgr.directoryListing(b.id()));
 
-        assertEquals(a, mgr.removeIfEmpty(ROOT_ID, "a", a.id(), new IgfsPath("/a"), true));
+        del = mgr.softDelete(path("/a"), false);
+        assertEquals(a.id(), del);
 
         assertEmpty(mgr.directoryListing(ROOT_ID));
         assertEmpty(mgr.directoryListing(a.id()));
@@ -420,25 +429,6 @@ public class IgfsMetaManagerSelfTest extends IgfsCommonAbstractTest {
     }
 
     /**
-     * Test expected failures for 'add file' operation.
-     *
-     * @param parentId Parent file ID.
-     * @param fileName New file name in the parent's listing.
-     * @param fileInfo New file initial details.
-     * @param msg Failure message if expected exception was not thrown.
-     */
-    private void expectsPutIfAbsentFail(final IgniteUuid parentId, final String fileName, final IgfsFileInfo fileInfo,
-        @Nullable String msg) {
-        Throwable err = assertThrows(log, new Callable() {
-            @Override public Object call() throws Exception {
-                return mgr.putIfAbsent(parentId, fileName, fileInfo);
-            }
-        }, IgniteCheckedException.class, msg);
-
-        assertTrue("Unexpected cause: " + err.getCause(), err.getCause() instanceof IgfsException);
-    }
-
-    /**
      * Test expected failures for 'move file' operation.
      *
      * @param msg Failure message if expected exception was not thrown.
@@ -454,26 +444,4 @@ public class IgfsMetaManagerSelfTest extends IgfsCommonAbstractTest {
 
         assertTrue("Unexpected cause: " + err, err instanceof IgfsException);
     }
-
-    /**
-     * Test expected failures for 'remove file' operation.
-     *
-     * @param parentId Parent file ID to remove file from.
-     * @param fileName File name in the parent's listing.
-     * @param fileId File ID to remove.
-     * @param path Removed file path.
-     * @param msg Failure message if expected exception was not thrown.
-     */
-    private void expectsRemoveFail(final IgniteUuid parentId, final String fileName, final IgniteUuid fileId,
-        final IgfsPath path, @Nullable String msg) {
-        Throwable err = assertThrows(log, new Callable() {
-            @Nullable @Override public Object call() throws Exception {
-                mgr.removeIfEmpty(parentId, fileName, fileId, path, true);
-
-                return null;
-            }
-        }, IgniteCheckedException.class, msg);
-
-        assertTrue("Unexpected cause: " + err.getCause(), err.getCause() instanceof IgfsDirectoryNotEmptyException);
-    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/962fcce3/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsProcessorSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsProcessorSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsProcessorSelfTest.java
index 9c4d832..c6853ae 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsProcessorSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsProcessorSelfTest.java
@@ -626,17 +626,17 @@ public class IgfsProcessorSelfTest extends IgfsCommonAbstractTest {
     /** @throws Exception If failed. */
     public void testCreateOpenAppend() throws Exception {
         // Error - path points to root directory.
-        assertCreateFails("/", false, "Failed to resolve parent directory");
+        assertCreateFails("/", false, "Failed to create file (path points to an existing directory)");
 
         // 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, "Failed to create file (file already exists)");
-            assertCreateFails(path, true, "Failed to create file (path points to a directory)");
-            assertAppendFails(path, false, "Failed to open file (not a file)");
-            assertAppendFails(path, true, "Failed to open file (not a file)");
+            assertCreateFails(path, false, "Failed to create file (path points to an existing directory)");
+            assertCreateFails(path, true, "Failed to create file (path points to an existing directory)");
+            assertAppendFails(path, false, "Failed to open file (path points to an existing directory)");
+            assertAppendFails(path, true, "Failed to open file (path points to an existing directory)");
             assertOpenFails(path, "Failed to open file (not a file)");
         }
 
@@ -653,7 +653,7 @@ public class IgfsProcessorSelfTest extends IgfsCommonAbstractTest {
             assertEquals(text1, create(path, false, text1));
 
             // Error - file already exists.
-            assertCreateFails(path, false, "Failed to create file (file already exists)");
+            assertCreateFails(path, false, "Failed to create file (file already exists and overwrite flag is false)");
 
             // Overwrite existent.
             assertEquals(text2, create(path, true, text2));

http://git-wip-us.apache.org/repos/asf/ignite/blob/962fcce3/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteIgfsTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteIgfsTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteIgfsTestSuite.java
index 954a011..cc5e1ce 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteIgfsTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteIgfsTestSuite.java
@@ -66,6 +66,12 @@ public class IgniteIgfsTestSuite extends TestSuite {
     public static TestSuite suite() throws Exception {
         TestSuite suite = new TestSuite("Ignite FS Test Suite For Platform Independent Tests");
 
+        suite.addTest(new TestSuite(IgfsPrimarySelfTest.class));
+        suite.addTest(new TestSuite(IgfsPrimaryOffheapTieredSelfTest.class));
+        suite.addTest(new TestSuite(IgfsPrimaryOffheapValuesSelfTest.class));
+        suite.addTest(new TestSuite(IgfsDualSyncSelfTest.class));
+        suite.addTest(new TestSuite(IgfsDualAsyncSelfTest.class));
+
         suite.addTest(new TestSuite(IgfsSizeSelfTest.class));
         suite.addTest(new TestSuite(IgfsAttributesSelfTest.class));
         suite.addTest(new TestSuite(IgfsFileInfoSelfTest.class));

http://git-wip-us.apache.org/repos/asf/ignite/blob/962fcce3/modules/hadoop/src/test/java/org/apache/ignite/igfs/Hadoop1DualAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/test/java/org/apache/ignite/igfs/Hadoop1DualAbstractTest.java b/modules/hadoop/src/test/java/org/apache/ignite/igfs/Hadoop1DualAbstractTest.java
index efe95be..ea65464 100644
--- a/modules/hadoop/src/test/java/org/apache/ignite/igfs/Hadoop1DualAbstractTest.java
+++ b/modules/hadoop/src/test/java/org/apache/ignite/igfs/Hadoop1DualAbstractTest.java
@@ -64,11 +64,6 @@ public abstract class Hadoop1DualAbstractTest extends IgfsDualAbstractSelfTest {
         super(mode);
     }
 
-    /** {@inheritDoc} */
-    @Override public void testMkdirs() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-1620");
-    }
-
     /**
      * Creates secondary filesystems.
      * @return IgfsSecondaryFileSystem

http://git-wip-us.apache.org/repos/asf/ignite/blob/962fcce3/modules/hadoop/src/test/java/org/apache/ignite/igfs/HadoopIgfs20FileSystemAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/test/java/org/apache/ignite/igfs/HadoopIgfs20FileSystemAbstractSelfTest.java b/modules/hadoop/src/test/java/org/apache/ignite/igfs/HadoopIgfs20FileSystemAbstractSelfTest.java
index c938571..b3afd22 100644
--- a/modules/hadoop/src/test/java/org/apache/ignite/igfs/HadoopIgfs20FileSystemAbstractSelfTest.java
+++ b/modules/hadoop/src/test/java/org/apache/ignite/igfs/HadoopIgfs20FileSystemAbstractSelfTest.java
@@ -897,7 +897,7 @@ public abstract class HadoopIgfs20FileSystemAbstractSelfTest extends IgfsCommonA
 
         os.close();
 
-        GridTestUtils.assertThrows(log, new Callable<Object>() {
+        GridTestUtils.assertThrowsInherited(log, new Callable<Object>() {
             @Override public Object call() throws Exception {
                 return fs.create(new Path(fsHome, dir), EnumSet.of(CreateFlag.APPEND),
                     Options.CreateOpts.perms(FsPermission.getDefault()));
@@ -919,8 +919,7 @@ public abstract class HadoopIgfs20FileSystemAbstractSelfTest extends IgfsCommonA
             Options.CreateOpts.perms(FsPermission.getDefault()));
 
         GridTestUtils.assertThrows(log, new Callable<Object>() {
-            @Override
-            public Object call() throws Exception {
+            @Override public Object call() throws Exception {
                 return fs.create(file, EnumSet.of(CreateFlag.APPEND),
                     Options.CreateOpts.perms(FsPermission.getDefault()));
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/962fcce3/modules/hadoop/src/test/java/org/apache/ignite/igfs/IgniteHadoopFileSystemAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/test/java/org/apache/ignite/igfs/IgniteHadoopFileSystemAbstractSelfTest.java b/modules/hadoop/src/test/java/org/apache/ignite/igfs/IgniteHadoopFileSystemAbstractSelfTest.java
index 2626ebb..d368955 100644
--- a/modules/hadoop/src/test/java/org/apache/ignite/igfs/IgniteHadoopFileSystemAbstractSelfTest.java
+++ b/modules/hadoop/src/test/java/org/apache/ignite/igfs/IgniteHadoopFileSystemAbstractSelfTest.java
@@ -1096,7 +1096,7 @@ public abstract class IgniteHadoopFileSystemAbstractSelfTest extends IgfsCommonA
 
         os.close();
 
-        GridTestUtils.assertThrows(log, new Callable<Object>() {
+        GridTestUtils.assertThrowsInherited(log, new Callable<Object>() {
             @Override public Object call() throws Exception {
                 return fs.append(new Path(fsHome, dir), 1024);
             }