IGNITE-3530: IGFS: Added missing "setTimes" method to IgfsSeconadryFileSystem.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/c075ab33
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/c075ab33
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/c075ab33

Branch: refs/heads/master
Commit: c075ab33254b7178c6e6b0a7b16801e787189ced
Parents: ce53491
Author: vozerov-gridgain <voze...@gridgain.com>
Authored: Mon Jul 25 08:54:05 2016 +0300
Committer: vozerov-gridgain <voze...@gridgain.com>
Committed: Mon Jul 25 08:54:05 2016 +0300

----------------------------------------------------------------------
 .../internal/processors/igfs/IgfsImpl.java      |  12 +-
 .../processors/igfs/IgfsMetaManager.java        | 115 ++++++++++++-------
 .../igfs/IgfsSecondaryFileSystemImpl.java       |  15 ++-
 .../igfs/IgfsSecondaryFileSystemV2.java         |  40 +++++++
 .../processors/igfs/IgfsAbstractSelfTest.java   | 111 +++++++++++++++++-
 .../igfs/IgfsDualAbstractSelfTest.java          |  34 ++++++
 .../igfs/IgfsExUniversalFileSystemAdapter.java  |  15 +++
 .../processors/igfs/IgfsModesSelfTest.java      |   2 -
 .../igfs/UniversalFileSystemAdapter.java        |  11 ++
 .../fs/IgniteHadoopIgfsSecondaryFileSystem.java |  16 ++-
 ...oopFileSystemUniversalFileSystemAdapter.java |   8 ++
 11 files changed, 316 insertions(+), 63 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/c075ab33/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
index 5b87698..df7dfb5 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
@@ -1139,16 +1139,12 @@ public final class IgfsImpl implements IgfsEx {
 
         safeOp(new Callable<Void>() {
             @Override public Void call() throws Exception {
-                FileDescriptor desc = getFileDescriptor(path);
-
-                if (desc == null)
-                    throw new IgfsPathNotFoundException("Failed to update 
times (path not found): " + path);
+                IgfsMode mode = resolveMode(path);
 
-                // Cannot update times for root.
-                if (desc.parentId == null)
-                    return null;
+                boolean useSecondary = IgfsUtils.isDualMode(mode) && 
secondaryFs instanceof IgfsSecondaryFileSystemV2;
 
-                meta.updateTimes(desc.parentId, desc.fileId, desc.fileName, 
accessTime, modificationTime);
+                meta.updateTimes(path, accessTime, modificationTime,
+                    useSecondary ? (IgfsSecondaryFileSystemV2)secondaryFs : 
null);
 
                 return null;
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/c075ab33/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsMetaManager.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsMetaManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsMetaManager.java
index 1640918..d891b38 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsMetaManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsMetaManager.java
@@ -51,14 +51,14 @@ import 
org.apache.ignite.internal.processors.igfs.client.IgfsClientAbstractCalla
 import 
org.apache.ignite.internal.processors.igfs.client.meta.IgfsClientMetaIdsForPathCallable;
 import 
org.apache.ignite.internal.processors.igfs.client.meta.IgfsClientMetaInfoForPathCallable;
 import 
org.apache.ignite.internal.processors.igfs.meta.IgfsMetaDirectoryCreateProcessor;
+import 
org.apache.ignite.internal.processors.igfs.meta.IgfsMetaDirectoryListingAddProcessor;
+import 
org.apache.ignite.internal.processors.igfs.meta.IgfsMetaDirectoryListingRemoveProcessor;
 import 
org.apache.ignite.internal.processors.igfs.meta.IgfsMetaDirectoryListingRenameProcessor;
+import 
org.apache.ignite.internal.processors.igfs.meta.IgfsMetaDirectoryListingReplaceProcessor;
 import 
org.apache.ignite.internal.processors.igfs.meta.IgfsMetaFileCreateProcessor;
 import 
org.apache.ignite.internal.processors.igfs.meta.IgfsMetaFileLockProcessor;
 import 
org.apache.ignite.internal.processors.igfs.meta.IgfsMetaFileReserveSpaceProcessor;
 import 
org.apache.ignite.internal.processors.igfs.meta.IgfsMetaFileUnlockProcessor;
-import 
org.apache.ignite.internal.processors.igfs.meta.IgfsMetaDirectoryListingAddProcessor;
-import 
org.apache.ignite.internal.processors.igfs.meta.IgfsMetaDirectoryListingRemoveProcessor;
-import 
org.apache.ignite.internal.processors.igfs.meta.IgfsMetaDirectoryListingReplaceProcessor;
 import 
org.apache.ignite.internal.processors.igfs.meta.IgfsMetaUpdatePropertiesProcessor;
 import 
org.apache.ignite.internal.processors.igfs.meta.IgfsMetaUpdateTimesProcessor;
 import org.apache.ignite.internal.util.GridLeanMap;
@@ -1155,16 +1155,20 @@ public class IgfsMetaManager extends IgfsManager {
     }
 
     /**
-     * Wheter operation must be re-tries because we have suspicious links 
which may broke secondary file system
+     * Whether operation must be re-tried because we have suspicious links 
which may broke secondary file system
      * consistency.
      *
      * @param pathIds Path IDs.
      * @param lockInfos Lock infos.
      * @return Whether to re-try.
      */
-    private boolean isRetryForSecondary(IgfsPathIds pathIds, Map<IgniteUuid, 
IgfsEntryInfo> lockInfos) {
+    private static boolean isRetryForSecondary(IgfsPathIds pathIds, 
Map<IgniteUuid, IgfsEntryInfo> lockInfos) {
         // We need to ensure that the last locked info is not linked with 
expected child.
         // Otherwise there was some concurrent file system update and we have 
to re-try.
+        // That is, the following situation lead to re-try:
+        // 1) We queried path /A/B/C
+        // 2) Returned IDs are ROOT_ID, A_ID, B_ID, null
+        // 3) But B's info contains C as child. It mean's that
         if (!pathIds.allExists()) {
             // Find the last locked index
             IgfsEntryInfo lastLockedInfo = null;
@@ -2754,59 +2758,82 @@ public class IgfsMetaManager extends IgfsManager {
     }
 
     /**
-     * Updates last access and last modification times.
+     * Update times.
      *
-     * @param parentId File parent ID.
-     * @param fileId File ID to update.
-     * @param fileName File name to update. Must match file ID.
-     * @param accessTime Access time to set. If {@code -1}, will not be 
updated.
-     * @param modificationTime Modification time to set. If {@code -1}, will 
not be updated.
-     * @throws IgniteCheckedException If update failed.
+     * @param path Path.
+     * @param accessTime Access time.
+     * @param modificationTime Modification time.
+     * @param secondaryFs Secondary file system.
+     * @throws IgniteCheckedException If failed.
      */
-    public void updateTimes(IgniteUuid parentId, IgniteUuid fileId, String 
fileName, long accessTime,
-        long modificationTime) throws IgniteCheckedException {
-        if (busyLock.enterBusy()) {
-            try {
-                validTxState(false);
+    public void updateTimes(IgfsPath path, long accessTime, long 
modificationTime,
+        IgfsSecondaryFileSystemV2 secondaryFs) throws IgniteCheckedException {
+        while (true) {
+            if (busyLock.enterBusy()) {
+                try {
+                    validTxState(false);
 
-                // Start pessimistic transaction.
-                try (IgniteInternalTx tx = startTx()) {
-                    Map<IgniteUuid, IgfsEntryInfo> infoMap = lockIds(fileId, 
parentId);
+                    // Prepare path IDs.
+                    IgfsPathIds pathIds = pathIds(path);
+
+                    // Prepare lock IDs.
+                    Set<IgniteUuid> lockIds = new 
TreeSet<>(PATH_ID_SORTING_COMPARATOR);
+
+                    pathIds.addExistingIds(lockIds, relaxed);
+
+                    // Start TX.
+                    try (IgniteInternalTx tx = startTx()) {
+                        Map<IgniteUuid, IgfsEntryInfo> lockInfos = 
lockIds(lockIds);
 
-                    IgfsEntryInfo fileInfo = infoMap.get(fileId);
+                        if (secondaryFs != null && 
isRetryForSecondary(pathIds, lockInfos))
+                            continue;
 
-                    if (fileInfo == null)
-                        throw fsException(new 
IgfsPathNotFoundException("Failed to update times " +
-                            "(path was not found): " + fileName));
+                        if (!pathIds.verifyIntegrity(lockInfos, relaxed))
+                            // Directory structure changed concurrently. So we 
re-try.
+                            continue;
 
-                    IgfsEntryInfo parentInfo = infoMap.get(parentId);
+                        if (pathIds.allExists()) {
+                            // All files are in place. Update both primary and 
secondary file systems.
+                            if (secondaryFs != null)
+                                secondaryFs.setTimes(path, accessTime, 
modificationTime);
 
-                    if (parentInfo == null)
-                        throw fsException(new 
IgfsPathNotFoundException("Failed to update times " +
-                            "(parent was not found): " + fileName));
+                            IgniteUuid targetId = pathIds.lastExistingId();
+                            IgfsEntryInfo targetInfo = lockInfos.get(targetId);
 
-                    // Validate listing.
-                    if (!parentInfo.hasChild(fileName, fileId))
-                        throw fsException(new 
IgfsConcurrentModificationException("Failed to update times " +
-                            "(file concurrently modified): " + fileName));
+                            id2InfoPrj.invoke(targetId, new 
IgfsMetaUpdateTimesProcessor(
+                                accessTime == -1 ? targetInfo.accessTime() : 
accessTime,
+                                modificationTime == -1 ? 
targetInfo.modificationTime() : modificationTime)
+                            );
 
-                    assert parentInfo.isDirectory();
+                            tx.commit();
 
-                    id2InfoPrj.invoke(fileId, new IgfsMetaUpdateTimesProcessor(
-                        accessTime == -1 ? fileInfo.accessTime() : accessTime,
-                        modificationTime == -1 ? fileInfo.modificationTime() : 
modificationTime)
-                    );
+                            return;
+                        }
+                        else {
+                            // Propagate call to the secondary FS, as we might 
haven't cache this part yet.
+                            if (secondaryFs != null) {
+                                secondaryFs.setTimes(path, accessTime, 
modificationTime);
 
-                    tx.commit();
+                                return;
+                            }
+                            else
+                                throw new IgfsPathNotFoundException("Failed to 
update times (path not found): " + path);
+                        }
+                    }
+                }
+                catch (IgniteException | IgniteCheckedException e) {
+                    throw e;
+                }
+                catch (Exception e) {
+                    throw new IgniteCheckedException("setTimes failed due to 
unexpected exception: " + path, e);
+                }
+                finally {
+                    busyLock.leaveBusy();
                 }
             }
-            finally {
-                busyLock.leaveBusy();
-            }
+            else
+                throw new IllegalStateException("Failed to update times 
because Grid is stopping: " + path);
         }
-        else
-            throw new IllegalStateException("Failed to update times because 
Grid is stopping [parentId=" + parentId +
-                ", fileId=" + fileId + ", fileName=" + fileName + ']');
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/c075ab33/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryFileSystemImpl.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryFileSystemImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryFileSystemImpl.java
index 44e858f..453682c 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryFileSystemImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryFileSystemImpl.java
@@ -17,20 +17,20 @@
 
 package org.apache.ignite.internal.processors.igfs;
 
-import java.io.OutputStream;
-import java.util.Collection;
-import java.util.Map;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.igfs.IgfsFile;
 import org.apache.ignite.igfs.IgfsPath;
-import org.apache.ignite.igfs.secondary.IgfsSecondaryFileSystem;
 import 
org.apache.ignite.igfs.secondary.IgfsSecondaryFileSystemPositionedReadable;
 import org.jetbrains.annotations.Nullable;
 
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.Map;
+
 /**
  * Secondary file system over native IGFS.
  */
-class IgfsSecondaryFileSystemImpl implements IgfsSecondaryFileSystem {
+class IgfsSecondaryFileSystemImpl implements IgfsSecondaryFileSystemV2 {
     /** Delegate. */
     private final IgfsEx igfs;
 
@@ -115,4 +115,9 @@ class IgfsSecondaryFileSystemImpl implements 
IgfsSecondaryFileSystem {
     @Override public long usedSpaceSize() throws IgniteException {
         return igfs.usedSpaceSize();
     }
+
+    /** {@inheritDoc} */
+    @Override public void setTimes(IgfsPath path, long accessTime, long 
modificationTime) throws IgniteException {
+        igfs.setTimes(path, accessTime, modificationTime);
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/c075ab33/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryFileSystemV2.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryFileSystemV2.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryFileSystemV2.java
new file mode 100644
index 0000000..3775574
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryFileSystemV2.java
@@ -0,0 +1,40 @@
+/*
+ * 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.ignite.IgniteException;
+import org.apache.ignite.igfs.IgfsPath;
+import org.apache.ignite.igfs.secondary.IgfsSecondaryFileSystem;
+
+/**
+ * Extended version of secondary file system with missing methods.
+ *
+ * @deprecated Will be removed in Apache Ignite 2.0. Methods will be merged to 
{@link IgfsSecondaryFileSystem}.
+ */
+@Deprecated
+public interface IgfsSecondaryFileSystemV2 extends IgfsSecondaryFileSystem {
+    /**
+     * Set times for the given path.
+     *
+     * @param path Path.
+     * @param accessTime Access time.
+     * @param modificationTime Modification time.
+     * @throws IgniteException If failed.
+     */
+    public void setTimes(IgfsPath path, long accessTime, long 
modificationTime) throws IgniteException;
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/c075ab33/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 c1c6c6c..384da95 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
@@ -50,6 +50,7 @@ import 
org.apache.ignite.internal.util.future.GridFutureAdapter;
 import org.apache.ignite.internal.util.lang.GridAbsPredicate;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.internal.util.typedef.T2;
 import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteBiTuple;
@@ -1123,6 +1124,112 @@ public abstract class IgfsAbstractSelfTest extends 
IgfsCommonAbstractTest {
     }
 
     /**
+     * Test setTimes operation.
+     *
+     * @throws Exception If failed.
+     */
+    public void testSetTimes() throws Exception {
+        createFile(igfs.asSecondary(), FILE, true, chunk);
+
+        checkExist(igfs, igfsSecondary, DIR);
+        checkExist(igfs, igfsSecondary, SUBDIR);
+        checkExist(igfs, igfsSecondary, FILE);
+
+        checkSetTimes(SUBDIR);
+        checkSetTimes(FILE);
+
+        try {
+            igfs.setTimes(FILE2, Long.MAX_VALUE, Long.MAX_VALUE);
+
+            fail("Exception is not thrown for missing file.");
+        }
+        catch (Exception ignore) {
+            // No-op.
+        }
+    }
+
+    /**
+     * Check setTimes logic for path.
+     *
+     * @param path Path.
+     * @throws Exception If failed.
+     */
+    private void checkSetTimes(IgfsPath path) throws Exception {
+        IgfsFile info = igfs.info(path);
+        T2<Long, Long> secondaryTimes = dual ? 
igfsSecondary.times(path.toString()) : null;
+
+        assert info != null;
+
+        // Change nothing.
+        igfs.setTimes(path, -1, -1);
+
+        IgfsFile newInfo = igfs.info(path);
+
+        assert newInfo != null;
+
+        assertEquals(info.accessTime(), newInfo.accessTime());
+        assertEquals(info.modificationTime(), newInfo.modificationTime());
+
+        if (dual) {
+            T2<Long, Long> newSecondaryTimes = 
igfsSecondary.times(path.toString());
+
+            assertEquals(secondaryTimes.get1(), newSecondaryTimes.get1());
+            assertEquals(secondaryTimes.get2(), newSecondaryTimes.get2());
+        }
+
+        // Change only access time.
+        igfs.setTimes(path, info.accessTime() + 1, -1);
+
+        newInfo = igfs.info(path);
+
+        assert newInfo != null;
+
+        assertEquals(info.accessTime() + 1, newInfo.accessTime());
+        assertEquals(info.modificationTime(), newInfo.modificationTime());
+
+        if (dual) {
+            T2<Long, Long> newSecondaryTimes = 
igfsSecondary.times(path.toString());
+
+            assertEquals(newInfo.accessTime(), (long)newSecondaryTimes.get1());
+            assertEquals(secondaryTimes.get2(), newSecondaryTimes.get2());
+        }
+
+        // Change only modification time.
+        igfs.setTimes(path, -1, info.modificationTime() + 1);
+
+        newInfo = igfs.info(path);
+
+        assert newInfo != null;
+
+        assertEquals(info.accessTime() + 1, newInfo.accessTime());
+        assertEquals(info.modificationTime() + 1, newInfo.modificationTime());
+
+        if (dual) {
+            T2<Long, Long> newSecondaryTimes = 
igfsSecondary.times(path.toString());
+
+            assertEquals(newInfo.accessTime(), (long)newSecondaryTimes.get1());
+            assertEquals(newInfo.modificationTime(), 
(long)newSecondaryTimes.get2());
+        }
+
+        // Change both.
+        igfs.setTimes(path, info.accessTime() + 2, info.modificationTime() + 
2);
+
+        newInfo = igfs.info(path);
+
+        assert newInfo != null;
+
+        assertEquals(info.accessTime() + 2, newInfo.accessTime());
+        assertEquals(info.modificationTime() + 2, newInfo.modificationTime());
+
+        if (dual) {
+            T2<Long, Long> newSecondaryTimes = 
igfsSecondary.times(path.toString());
+
+            assertEquals(newInfo.accessTime(), (long)newSecondaryTimes.get1());
+            assertEquals(newInfo.modificationTime(), 
(long)newSecondaryTimes.get2());
+        }
+    }
+
+    /**
      * Test regular create.
      *
      * @throws Exception If failed.
@@ -2764,8 +2871,8 @@ public abstract class IgfsAbstractSelfTest extends 
IgfsCommonAbstractTest {
      * @param chunks Data chunks.
      * @throws IOException In case of IO exception.
      */
-    protected static void createFile(IgfsSecondaryFileSystem igfs, IgfsPath 
file, boolean overwrite, @Nullable byte[]... chunks)
-        throws IOException {
+    protected static void createFile(IgfsSecondaryFileSystem igfs, IgfsPath 
file, boolean overwrite,
+        @Nullable byte[]... chunks) throws IOException {
         OutputStream os = null;
 
         try {

http://git-wip-us.apache.org/repos/asf/ignite/blob/c075ab33/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsDualAbstractSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsDualAbstractSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsDualAbstractSelfTest.java
index b8c8978..124bec6 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsDualAbstractSelfTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsDualAbstractSelfTest.java
@@ -1682,4 +1682,38 @@ public abstract class IgfsDualAbstractSelfTest extends 
IgfsAbstractSelfTest {
         assertEquals(timesFile0, timesFile1);
         assertEquals(timesFile20, timesFile21);
     }
+
+    /**
+     * Test setTimes method when path is partially missing.
+     *
+     * @throws Exception If failed.
+     */
+    public void testSetTimesMissingPartially() throws Exception {
+        create(igfs, paths(DIR), null);
+
+        createFile(igfsSecondary, FILE, chunk);
+
+        igfs.setTimes(FILE, Long.MAX_VALUE - 1, Long.MAX_VALUE);
+
+        IgfsFile info = igfs.info(FILE);
+
+        assert info != null;
+
+        assertEquals(Long.MAX_VALUE - 1, info.accessTime());
+        assertEquals(Long.MAX_VALUE, info.modificationTime());
+
+        T2<Long, Long> secondaryTimes = igfsSecondary.times(FILE.toString());
+
+        assertEquals(info.accessTime(), (long)secondaryTimes.get1());
+        assertEquals(info.modificationTime(), (long)secondaryTimes.get2());
+
+        try {
+            igfs.setTimes(FILE2, Long.MAX_VALUE, Long.MAX_VALUE);
+
+            fail("Exception is not thrown for missing file.");
+        }
+        catch (Exception ignore) {
+            // No-op.
+        }
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/c075ab33/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsExUniversalFileSystemAdapter.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsExUniversalFileSystemAdapter.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsExUniversalFileSystemAdapter.java
index c6bef72..80b320b 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsExUniversalFileSystemAdapter.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsExUniversalFileSystemAdapter.java
@@ -21,8 +21,11 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Map;
+
+import org.apache.ignite.igfs.IgfsFile;
 import org.apache.ignite.igfs.IgfsOutputStream;
 import org.apache.ignite.igfs.IgfsPath;
+import org.apache.ignite.internal.util.typedef.T2;
 
 /**
  * Universal adapter over {@link IgfsEx} filesystem.
@@ -60,6 +63,7 @@ public class IgfsExUniversalFileSystemAdapter implements 
UniversalFileSystemAdap
     }
 
     /** {@inheritDoc} */
+    @SuppressWarnings("ConstantConditions")
     @Override public Map<String, String> properties(String path) {
         return igfsEx.info(new IgfsPath(path)).properties();
     }
@@ -92,6 +96,17 @@ public class IgfsExUniversalFileSystemAdapter implements 
UniversalFileSystemAdap
     }
 
     /** {@inheritDoc} */
+    @Override public T2<Long, Long> times(String path) throws IOException {
+        IgfsFile info = igfsEx.info(new IgfsPath(path));
+
+        if (info == null)
+            throw new IOException("Path not found: " + path);
+
+        return new T2<>(info.accessTime(), info.modificationTime());
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("unchecked")
     @Override public <T> T unwrap(Class<T> clazz) {
         if (clazz == IgfsEx.class)
             return (T)igfsEx;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c075ab33/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsModesSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsModesSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsModesSelfTest.java
index a6b7502..5fcd8dd 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsModesSelfTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsModesSelfTest.java
@@ -492,8 +492,6 @@ public class IgfsModesSelfTest extends 
IgfsCommonAbstractTest {
      * @throws Exception If failed.
      */
     public void testPropagationDualAsync() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-822";);
-
         mode = DUAL_ASYNC;
 
         checkPropagation();

http://git-wip-us.apache.org/repos/asf/ignite/blob/c075ab33/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/UniversalFileSystemAdapter.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/UniversalFileSystemAdapter.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/UniversalFileSystemAdapter.java
index eef0057..3f6d07e 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/UniversalFileSystemAdapter.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/UniversalFileSystemAdapter.java
@@ -17,6 +17,8 @@
 
 package org.apache.ignite.internal.processors.igfs;
 
+import org.apache.ignite.internal.util.typedef.T2;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -89,6 +91,15 @@ public interface UniversalFileSystemAdapter {
     OutputStream openOutputStream(String path, boolean append) throws 
IOException;
 
     /**
+     * Get times for path.
+     *
+     * @param path Path.
+     * @return Times for path.
+     * @throws IOException If failed.
+     */
+    T2<Long, Long> times(String path) throws IOException;
+
+    /**
      * Gets an entity of the given type (class) associated with this universal 
adapter.
      * @param clazz The class representing the type we wish to adapt to.
      * @param <T> The type we need to adapt to.

http://git-wip-us.apache.org/repos/asf/ignite/blob/c075ab33/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/IgniteHadoopIgfsSecondaryFileSystem.java
----------------------------------------------------------------------
diff --git 
a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/IgniteHadoopIgfsSecondaryFileSystem.java
 
b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/IgniteHadoopIgfsSecondaryFileSystem.java
index 329c605..0f17fa2 100644
--- 
a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/IgniteHadoopIgfsSecondaryFileSystem.java
+++ 
b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/fs/IgniteHadoopIgfsSecondaryFileSystem.java
@@ -36,13 +36,13 @@ import org.apache.ignite.igfs.IgfsPath;
 import org.apache.ignite.igfs.IgfsPathAlreadyExistsException;
 import org.apache.ignite.igfs.IgfsPathNotFoundException;
 import org.apache.ignite.igfs.IgfsUserContext;
-import org.apache.ignite.igfs.secondary.IgfsSecondaryFileSystem;
 import 
org.apache.ignite.igfs.secondary.IgfsSecondaryFileSystemPositionedReadable;
 import org.apache.ignite.internal.processors.hadoop.HadoopPayloadAware;
 import org.apache.ignite.internal.processors.hadoop.igfs.HadoopIgfsProperties;
 import 
org.apache.ignite.internal.processors.hadoop.igfs.HadoopIgfsSecondaryFileSystemPositionedReadable;
 import org.apache.ignite.internal.processors.igfs.IgfsEntryInfo;
 import org.apache.ignite.internal.processors.igfs.IgfsFileImpl;
+import org.apache.ignite.internal.processors.igfs.IgfsSecondaryFileSystemV2;
 import org.apache.ignite.internal.processors.igfs.IgfsUtils;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.lang.IgniteOutClosure;
@@ -66,7 +66,7 @@ import java.util.concurrent.Callable;
  * <p>
  * Target {@code FileSystem}'s are created on per-user basis using passed 
{@link HadoopFileSystemFactory}.
  */
-public class IgniteHadoopIgfsSecondaryFileSystem implements 
IgfsSecondaryFileSystem, LifecycleAware,
+public class IgniteHadoopIgfsSecondaryFileSystem implements 
IgfsSecondaryFileSystemV2, LifecycleAware,
     HadoopPayloadAware {
     /** The default user name. It is used if no user context is set. */
     private String dfltUsrName;
@@ -515,6 +515,18 @@ public class IgniteHadoopIgfsSecondaryFileSystem 
implements IgfsSecondaryFileSys
         }
     }
 
+    /** {@inheritDoc} */
+    @Override public void setTimes(IgfsPath path, long accessTime, long 
modificationTime) throws IgniteException {
+        try {
+            // We don't use FileSystem#getUsed() since it counts only the files
+            // in the filesystem root, not all the files recursively.
+            fileSystemForUser().setTimes(convert(path), modificationTime, 
accessTime);
+        }
+        catch (IOException e) {
+            throw handleSecondaryFsError(e, "Failed set times for path: " + 
path);
+        }
+    }
+
     /**
      * Gets the underlying {@link FileSystem}.
      * This method is used solely for testing.

http://git-wip-us.apache.org/repos/asf/ignite/blob/c075ab33/modules/hadoop/src/test/java/org/apache/ignite/igfs/HadoopFileSystemUniversalFileSystemAdapter.java
----------------------------------------------------------------------
diff --git 
a/modules/hadoop/src/test/java/org/apache/ignite/igfs/HadoopFileSystemUniversalFileSystemAdapter.java
 
b/modules/hadoop/src/test/java/org/apache/ignite/igfs/HadoopFileSystemUniversalFileSystemAdapter.java
index 44b8f40..5239054 100644
--- 
a/modules/hadoop/src/test/java/org/apache/ignite/igfs/HadoopFileSystemUniversalFileSystemAdapter.java
+++ 
b/modules/hadoop/src/test/java/org/apache/ignite/igfs/HadoopFileSystemUniversalFileSystemAdapter.java
@@ -31,6 +31,7 @@ import org.apache.ignite.hadoop.fs.HadoopFileSystemFactory;
 import org.apache.ignite.internal.processors.hadoop.igfs.HadoopIgfsUtils;
 import org.apache.ignite.internal.processors.igfs.IgfsUtils;
 import org.apache.ignite.internal.processors.igfs.UniversalFileSystemAdapter;
+import org.apache.ignite.internal.util.typedef.T2;
 
 /**
  * Universal adapter wrapping {@link org.apache.hadoop.fs.FileSystem} instance.
@@ -111,6 +112,13 @@ public class HadoopFileSystemUniversalFileSystemAdapter 
implements UniversalFile
     }
 
     /** {@inheritDoc} */
+    @Override public T2<Long, Long> times(String path) throws IOException {
+        FileStatus status = get().getFileStatus(new Path(path));
+
+        return new T2<>(status.getAccessTime(), status.getModificationTime());
+    }
+
+    /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
     @Override public <T> T unwrap(Class<T> cls) {
         if (HadoopFileSystemFactory.class.isAssignableFrom(cls))

Reply via email to