You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2016/06/17 08:54:15 UTC

[06/41] ignite git commit: IGNITE-3294: IGFS: Improved "create" performance in DUAL mode.

IGNITE-3294: IGFS: Improved "create" performance in DUAL mode.


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

Branch: refs/heads/ignite-3331
Commit: 40e6614f2426912aaec4220b8f720c12c3e5214a
Parents: 7f878c5
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Tue Jun 14 11:09:01 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Tue Jun 14 11:09:01 2016 +0300

----------------------------------------------------------------------
 .../processors/igfs/IgfsCreateResult.java       |  66 ++
 .../internal/processors/igfs/IgfsImpl.java      |  53 +-
 .../processors/igfs/IgfsMetaManager.java        | 612 +++++++++----------
 .../IgfsSecondaryFileSystemCreateContext.java   | 111 ++++
 .../IgfsSecondaryOutputStreamDescriptor.java    |  59 --
 .../meta/IgfsMetaDirectoryCreateProcessor.java  |  40 +-
 .../igfs/meta/IgfsMetaFileCreateProcessor.java  |  46 +-
 .../igfs/IgfsMetaManagerSelfTest.java           |   4 +-
 8 files changed, 538 insertions(+), 453 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/40e6614f/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsCreateResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsCreateResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsCreateResult.java
new file mode 100644
index 0000000..0b09e02
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsCreateResult.java
@@ -0,0 +1,66 @@
+/*
+ * 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.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.OutputStream;
+
+/**
+ * IGFS file create result.
+ */
+public class IgfsCreateResult {
+    /** File info in the primary file system. */
+    private final IgfsEntryInfo info;
+
+    /** Output stream to the secondary file system. */
+    private final OutputStream secondaryOut;
+
+    /**
+     * Constructor.
+     *
+     * @param info File info in the primary file system.
+     * @param secondaryOut Output stream to the secondary file system.
+     */
+    public IgfsCreateResult(IgfsEntryInfo info, @Nullable OutputStream secondaryOut) {
+        assert info != null;
+
+        this.info = info;
+        this.secondaryOut = secondaryOut;
+    }
+
+    /**
+     * @return File info in the primary file system.
+     */
+    public IgfsEntryInfo info() {
+        return info;
+    }
+
+    /**
+     * @return Output stream to the secondary file system.
+     */
+    @Nullable public OutputStream secondaryOutputStream() {
+        return secondaryOut;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(IgfsCreateResult.class, this);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/40e6614f/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 0808619..7234e52 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
@@ -106,7 +106,6 @@ import static org.apache.ignite.events.EventType.EVT_IGFS_DIR_DELETED;
 import static org.apache.ignite.events.EventType.EVT_IGFS_FILE_CLOSED_READ;
 import static org.apache.ignite.events.EventType.EVT_IGFS_FILE_DELETED;
 import static org.apache.ignite.events.EventType.EVT_IGFS_FILE_OPENED_READ;
-import static org.apache.ignite.events.EventType.EVT_IGFS_FILE_OPENED_WRITE;
 import static org.apache.ignite.events.EventType.EVT_IGFS_META_UPDATED;
 import static org.apache.ignite.igfs.IgfsMode.DUAL_ASYNC;
 import static org.apache.ignite.igfs.IgfsMode.DUAL_SYNC;
@@ -1019,28 +1018,10 @@ public final class IgfsImpl implements IgfsEx {
                     log.debug("Open file for writing [path=" + path + ", bufSize=" + bufSize + ", overwrite=" +
                         overwrite + ", props=" + props + ']');
 
+                // Resolve mode.
                 final IgfsMode mode = resolveMode(path);
 
-                IgfsFileWorkerBatch batch;
-
-                if (mode != PRIMARY) {
-                    assert mode == DUAL_SYNC || mode == DUAL_ASYNC;
-
-                    await(path);
-
-                    IgfsSecondaryOutputStreamDescriptor desc = meta.createDual(secondaryFs, path, simpleCreate,
-                        props, overwrite, bufSize, (short) replication, groupBlockSize(), affKey);
-
-                    batch = newBatch(path, desc.out());
-
-                    IgfsOutputStreamImpl os = new IgfsOutputStreamImpl(igfsCtx, path, desc.info(),
-                        bufferSize(bufSize), mode, batch);
-
-                    IgfsUtils.sendEvents(igfsCtx.kernalContext(), path, EVT_IGFS_FILE_OPENED_WRITE);
-
-                    return os;
-                }
-
+                // Prepare properties.
                 final Map<String, String> dirProps, fileProps;
 
                 if (props == null) {
@@ -1051,19 +1032,37 @@ public final class IgfsImpl implements IgfsEx {
                 else
                     dirProps = fileProps = new HashMap<>(props);
 
-                IgfsEntryInfo res = meta.create(
+                // Prepare context for DUAL mode.
+                IgfsSecondaryFileSystemCreateContext secondaryCtx = null;
+
+                if (mode != PRIMARY)
+                    secondaryCtx = new IgfsSecondaryFileSystemCreateContext(secondaryFs, path, overwrite, simpleCreate,
+                        fileProps, (short)replication, groupBlockSize(), bufSize);
+
+                // Await for async ops completion if in DUAL mode.
+                if (mode != PRIMARY)
+                    await(path);
+
+                // Perform create.
+                IgfsCreateResult res = meta.create(
                     path,
                     dirProps,
                     overwrite,
                     cfg.getBlockSize(),
                     affKey,
-                    evictExclude(path, true),
-                    fileProps
+                    evictExclude(path, mode == PRIMARY),
+                    fileProps,
+                    secondaryCtx
                 );
 
                 assert res != null;
 
-                return new IgfsOutputStreamImpl(igfsCtx, path, res, bufferSize(bufSize), mode, null);
+                // Create secondary file system batch.
+                OutputStream secondaryStream = res.secondaryOutputStream();
+
+                IgfsFileWorkerBatch batch = secondaryStream != null ? newBatch(path, secondaryStream) : null;
+
+                return new IgfsOutputStreamImpl(igfsCtx, path, res.info(), bufferSize(bufSize), mode, batch);
             }
         });
     }
@@ -1094,9 +1093,9 @@ public final class IgfsImpl implements IgfsEx {
 
                     await(path);
 
-                    IgfsSecondaryOutputStreamDescriptor desc = meta.appendDual(secondaryFs, path, bufSize);
+                    IgfsCreateResult desc = meta.appendDual(secondaryFs, path, bufSize);
 
-                    batch = newBatch(path, desc.out());
+                    batch = newBatch(path, desc.secondaryOutputStream());
 
                     return new IgfsOutputStreamImpl(igfsCtx, path, desc.info(), bufferSize(bufSize), mode, batch);
                 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/40e6614f/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 2fb6066..c08d6a0 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
@@ -393,40 +393,47 @@ public class IgfsMetaManager extends IgfsManager {
      * @throws IgniteCheckedException If failed.
      */
     public IgfsPathIds pathIds(IgfsPath path) throws IgniteCheckedException {
-        if (busyLock.enterBusy()) {
-            try {
-                validTxState(false);
+        // Prepare parts.
+        String[] components = path.componentsArray();
 
-                // Prepare parts.
-                String[] components = path.componentsArray();
+        String[] parts = new String[components.length + 1];
 
-                String[] parts = new String[components.length + 1];
+        System.arraycopy(components, 0, parts, 1, components.length);
 
-                System.arraycopy(components, 0, parts, 1, components.length);
+        // Get IDs.
+        if (client) {
+            List<IgniteUuid> ids = runClientTask(new IgfsClientMetaIdsForPathCallable(cfg.getName(), path));
 
-                // Prepare IDs.
-                IgniteUuid[] ids = new IgniteUuid[parts.length];
+            return new IgfsPathIds(path, parts, ids.toArray(new IgniteUuid[ids.size()]));
+        }
+        else {
+            if (busyLock.enterBusy()) {
+                try {
+                    validTxState(false);
 
-                ids[0] = IgfsUtils.ROOT_ID;
+                    IgniteUuid[] ids = new IgniteUuid[parts.length];
 
-                for (int i = 1; i < ids.length; i++) {
-                    IgniteUuid id = fileId(ids[i - 1], parts[i], false);
+                    ids[0] = IgfsUtils.ROOT_ID;
 
-                    if (id != null)
-                        ids[i] = id;
-                    else
-                        break;
-                }
+                    for (int i = 1; i < ids.length; i++) {
+                        IgniteUuid id = fileId(ids[i - 1], parts[i], false);
 
-                // Return.
-                return new IgfsPathIds(path, parts, ids);
-            }
-            finally {
-                busyLock.leaveBusy();
+                        if (id != null)
+                            ids[i] = id;
+                        else
+                            break;
+                    }
+
+                    // Return.
+                    return new IgfsPathIds(path, parts, ids);
+                }
+                finally {
+                    busyLock.leaveBusy();
+                }
             }
+            else
+                throw new IllegalStateException("Failed to get file IDS because Grid is stopping: " + path);
         }
-        else
-            throw new IllegalStateException("Failed to get file IDS because Grid is stopping: " + path);
     }
 
     /**
@@ -1146,6 +1153,46 @@ public class IgfsMetaManager extends IgfsManager {
     }
 
     /**
+     * Wheter operation must be re-tries 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) {
+        // 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.
+        if (!pathIds.allExists()) {
+            // Find the last locked index
+            IgfsEntryInfo lastLockedInfo = null;
+            int lastLockedIdx = -1;
+
+            while (lastLockedIdx < pathIds.lastExistingIndex()) {
+                IgfsEntryInfo nextInfo = lockInfos.get(pathIds.id(lastLockedIdx + 1));
+
+                if (nextInfo != null) {
+                    lastLockedInfo = nextInfo;
+                    lastLockedIdx++;
+                }
+                else
+                    break;
+            }
+
+            assert lastLockedIdx < pathIds.count();
+
+            if (lastLockedInfo != null) {
+                String part = pathIds.part(lastLockedIdx + 1);
+
+                if (lastLockedInfo.listing().containsKey(part))
+                    return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
      * Move path to the trash directory.
      *
      * @param path Path.
@@ -1154,8 +1201,8 @@ public class IgfsMetaManager extends IgfsManager {
      * @return ID of an entry located directly under the trash directory.
      * @throws IgniteCheckedException If failed.
      */
-    IgfsDeleteResult softDelete(final IgfsPath path, final boolean recursive, @Nullable IgfsSecondaryFileSystem secondaryFs)
-        throws IgniteCheckedException {
+    IgfsDeleteResult softDelete(final IgfsPath path, final boolean recursive,
+        @Nullable IgfsSecondaryFileSystem secondaryFs) throws IgniteCheckedException {
         while (true) {
             if (busyLock.enterBusy()) {
                 try {
@@ -1163,16 +1210,8 @@ public class IgfsMetaManager extends IgfsManager {
 
                     IgfsPathIds pathIds = pathIds(path);
 
-                    boolean relaxed0 = relaxed;
-
-                    if (!pathIds.allExists()) {
-                        if (secondaryFs == null)
-                            // Return early if target path doesn't exist and we do not have secondary file system.
-                            return new IgfsDeleteResult(false, null);
-                        else
-                            // If path is missing partially, we need more serious locking for DUAL mode.
-                            relaxed0 = false;
-                    }
+                    if (!pathIds.allExists() && secondaryFs == null)
+                        return new IgfsDeleteResult(false, null);
 
                     IgniteUuid victimId = pathIds.lastId();
                     String victimName = pathIds.lastPart();
@@ -1183,7 +1222,7 @@ public class IgfsMetaManager extends IgfsManager {
                     // Prepare IDs to lock.
                     SortedSet<IgniteUuid> allIds = new TreeSet<>(PATH_ID_SORTING_COMPARATOR);
 
-                    pathIds.addExistingIds(allIds, relaxed0);
+                    pathIds.addExistingIds(allIds, relaxed);
 
                     IgniteUuid trashId = IgfsUtils.randomTrashId();
 
@@ -1193,38 +1232,11 @@ public class IgfsMetaManager extends IgfsManager {
                         // Lock participants.
                         Map<IgniteUuid, IgfsEntryInfo> lockInfos = lockIds(allIds);
 
-                        if (!pathIds.allExists()) {
-                            // We need to ensure that the last locked info is not linked with expected child.
-                            // Otherwise there was some ocncurrent file system update and we have to re-try.
-                            assert secondaryFs != null;
-
-                            // Find the last locked index
-                            IgfsEntryInfo lastLockedInfo = null;
-                            int lastLockedIdx = -1;
-
-                            while (lastLockedIdx < pathIds.lastExistingIndex()) {
-                                IgfsEntryInfo nextInfo = lockInfos.get(pathIds.id(lastLockedIdx + 1));
-
-                                if (nextInfo != null) {
-                                    lastLockedInfo = nextInfo;
-                                    lastLockedIdx++;
-                                }
-                                else
-                                    break;
-                            }
-
-                            assert lastLockedIdx < pathIds.count();
-
-                            if (lastLockedInfo != null) {
-                                String part = pathIds.part(lastLockedIdx + 1);
-
-                                if (lastLockedInfo.listing().containsKey(part))
-                                    continue;
-                            }
-                        }
+                        if (secondaryFs != null && isRetryForSecondary(pathIds, lockInfos))
+                            continue;
 
                         // Ensure that all participants are still in place.
-                        if (!pathIds.allExists() || !pathIds.verifyIntegrity(lockInfos, relaxed0)) {
+                        if (!pathIds.allExists() || !pathIds.verifyIntegrity(lockInfos, relaxed)) {
                             // For DUAL mode we will try to update the underlying FS still. Note we do that inside TX.
                             if (secondaryFs != null) {
                                 boolean res = secondaryFs.delete(path, recursive);
@@ -1717,7 +1729,7 @@ public class IgfsMetaManager extends IgfsManager {
     /**
      * Transfer entry from one directory to another.
      *
-     * @param entry Entry to be transfered.
+     * @param entry Entry to be transferred.
      * @param srcId Source ID.
      * @param srcName Source name.
      * @param destId Destination ID.
@@ -1728,8 +1740,19 @@ public class IgfsMetaManager extends IgfsManager {
         IgniteUuid destId, String destName) throws IgniteCheckedException {
         validTxState(true);
 
-        id2InfoPrj.invoke(srcId, new IgfsMetaDirectoryListingRemoveProcessor(srcName, entry.fileId()));
-        id2InfoPrj.invoke(destId, new IgfsMetaDirectoryListingAddProcessor(destName, entry));
+        if (F.eq(srcId, destId)) {
+            id2InfoPrj.invoke(srcId, new IgfsMetaDirectoryListingRemoveProcessor(srcName, entry.fileId()));
+            id2InfoPrj.invoke(destId, new IgfsMetaDirectoryListingAddProcessor(destName, entry));
+        }
+        else {
+
+            Map<IgniteUuid, EntryProcessor<IgniteUuid, IgfsEntryInfo, Void>> procMap = new HashMap<>();
+
+            procMap.put(srcId, new IgfsMetaDirectoryListingRemoveProcessor(srcName, entry.fileId()));
+            procMap.put(destId, new IgfsMetaDirectoryListingAddProcessor(destName, entry));
+
+            id2InfoPrj.invokeAll(procMap);
+        }
     }
 
     /**
@@ -1786,59 +1809,6 @@ public class IgfsMetaManager extends IgfsManager {
     }
 
     /**
-     * Create the file in DUAL mode.
-     *
-     * @param fs File system.
-     * @param path Path.
-     * @param simpleCreate "Simple create" flag.
-     * @param props Properties..
-     * @param overwrite Overwrite flag.
-     * @param bufSize Buffer size.
-     * @param replication Replication factor.
-     * @param blockSize Block size.
-     * @param affKey Affinity key.
-     * @return Output stream descriptor.
-     * @throws IgniteCheckedException If file creation failed.
-     */
-    public IgfsSecondaryOutputStreamDescriptor createDual(final IgfsSecondaryFileSystem fs,
-        final IgfsPath path,
-        final boolean simpleCreate,
-        @Nullable final Map<String, String> props,
-        final boolean overwrite,
-        final int bufSize,
-        final short replication,
-        final long blockSize,
-        final IgniteUuid affKey)
-        throws IgniteCheckedException
-    {
-        if (busyLock.enterBusy()) {
-            try {
-                assert fs != null;
-                assert path != null;
-
-                // Events to fire (can be done outside of a transaction).
-                final Deque<IgfsEvent> pendingEvts = new LinkedList<>();
-
-                CreateFileSynchronizationTask task = new CreateFileSynchronizationTask(fs, path, simpleCreate, props,
-                    overwrite, bufSize, replication, blockSize, affKey, pendingEvts);
-
-                try {
-                    return synchronizeAndExecute(task, fs, false, path.parent());
-                }
-                finally {
-                    for (IgfsEvent evt : pendingEvts)
-                        evts.record(evt);
-                }
-            }
-            finally {
-                busyLock.leaveBusy();
-            }
-        }
-        else
-            throw new IllegalStateException("Failed to create file in DUAL mode because Grid is stopping: " + path);
-    }
-
-    /**
      * Append to a file in DUAL mode.
      *
      * @param fs File system.
@@ -1847,19 +1817,19 @@ public class IgfsMetaManager extends IgfsManager {
      * @return Output stream descriptor.
      * @throws IgniteCheckedException If output stream open for append has failed.
      */
-    public IgfsSecondaryOutputStreamDescriptor appendDual(final IgfsSecondaryFileSystem fs, final IgfsPath path,
+    public IgfsCreateResult appendDual(final IgfsSecondaryFileSystem fs, final IgfsPath path,
         final int bufSize) throws IgniteCheckedException {
         if (busyLock.enterBusy()) {
             try {
                 assert fs != null;
                 assert path != null;
 
-                SynchronizationTask<IgfsSecondaryOutputStreamDescriptor> task =
-                    new SynchronizationTask<IgfsSecondaryOutputStreamDescriptor>() {
+                SynchronizationTask<IgfsCreateResult> task =
+                    new SynchronizationTask<IgfsCreateResult>() {
                         /** Output stream to the secondary file system. */
                         private OutputStream out;
 
-                        @Override public IgfsSecondaryOutputStreamDescriptor onSuccess(Map<IgfsPath,
+                        @Override public IgfsCreateResult onSuccess(Map<IgfsPath,
                             IgfsEntryInfo> infos) throws Exception {
                             validTxState(true);
 
@@ -1898,10 +1868,10 @@ public class IgfsMetaManager extends IgfsManager {
                             // Set lock and return.
                             IgfsEntryInfo lockedInfo = invokeLock(info.id(), false);
 
-                            return new IgfsSecondaryOutputStreamDescriptor(lockedInfo, out);
+                            return new IgfsCreateResult(lockedInfo, out);
                         }
 
-                        @Override public IgfsSecondaryOutputStreamDescriptor onFailure(@Nullable Exception err)
+                        @Override public IgfsCreateResult onFailure(@Nullable Exception err)
                             throws IgniteCheckedException {
                             U.closeQuiet(out);
 
@@ -2784,8 +2754,8 @@ public class IgfsMetaManager extends IgfsManager {
                         }
                         else {
                             // Create file and parent folders.
-                            IgfsPathsCreateResult res =
-                                createFile(pathIds, lockInfos, dirProps, fileProps, blockSize, affKey, evictExclude);
+                            IgfsPathsCreateResult res = createFile(pathIds, lockInfos, dirProps, fileProps, blockSize,
+                                affKey, evictExclude, null);
 
                             if (res == null)
                                 continue;
@@ -2819,21 +2789,25 @@ public class IgfsMetaManager extends IgfsManager {
      * @param affKey Affinity key.
      * @param evictExclude Evict exclude flag.
      * @param fileProps File properties.
-     * @return @return Resulting info.
+     * @param secondaryCtx Secondary file system create context.
+     * @return @return Operation result.
      * @throws IgniteCheckedException If failed.
      */
-    IgfsEntryInfo create(
+    IgfsCreateResult create(
         final IgfsPath path,
         Map<String, String> dirProps,
         final boolean overwrite,
         final int blockSize,
         final @Nullable IgniteUuid affKey,
         final boolean evictExclude,
-        @Nullable Map<String, String> fileProps) throws IgniteCheckedException {
+        @Nullable Map<String, String> fileProps,
+        @Nullable IgfsSecondaryFileSystemCreateContext secondaryCtx) throws IgniteCheckedException {
         validTxState(false);
 
         while (true) {
             if (busyLock.enterBusy()) {
+                OutputStream secondaryOut = null;
+
                 try {
                     // Prepare path IDs.
                     IgfsPathIds pathIds = pathIds(path);
@@ -2860,6 +2834,9 @@ public class IgfsMetaManager extends IgfsManager {
                     try (IgniteInternalTx tx = startTx()) {
                         Map<IgniteUuid, IgfsEntryInfo> lockInfos = lockIds(lockIds);
 
+                        if (secondaryCtx != null && isRetryForSecondary(pathIds, lockInfos))
+                            continue;
+
                         if (!pathIds.verifyIntegrity(lockInfos, relaxed))
                             // Directory structure changed concurrently. So we simply re-try.
                             continue;
@@ -2882,35 +2859,71 @@ public class IgfsMetaManager extends IgfsManager {
 
                             // At this point file can be re-created safely.
 
-                            // First step: add existing to trash listing.
+                            // Add existing to trash listing.
                             IgniteUuid oldId = pathIds.lastId();
 
                             id2InfoPrj.invoke(trashId, new IgfsMetaDirectoryListingAddProcessor(oldId.toString(),
                                 new IgfsListingEntry(oldInfo)));
 
-                            // Second step: replace ID in parent directory.
+                            // Replace ID in parent directory.
                             String name = pathIds.lastPart();
                             IgniteUuid parentId = pathIds.lastParentId();
 
                             id2InfoPrj.invoke(parentId, new IgfsMetaDirectoryListingReplaceProcessor(name, overwriteId));
 
-                            // Third step: create the file.
-                            long createTime = System.currentTimeMillis();
+                            // Create the file.
+                            IgniteUuid newLockId = createFileLockId(false);
+
+                            long newAccessTime;
+                            long newModificationTime;
+                            Map<String, String> newProps;
+                            long newLen;
+                            int newBlockSize;
+
+                            if (secondaryCtx != null) {
+                                secondaryOut = secondaryCtx.create();
 
-                            IgfsEntryInfo newInfo = invokeAndGet(overwriteId, new IgfsMetaFileCreateProcessor(createTime,
-                                fileProps, blockSize, affKey, createFileLockId(false), evictExclude));
+                                IgfsFile secondaryFile = secondaryCtx.info();
+
+                                if (secondaryFile == null)
+                                    throw fsException("Failed to open output stream to the file created in " +
+                                        "the secondary file system because it no longer exists: " + path);
+                                else if (secondaryFile.isDirectory())
+                                    throw fsException("Failed to open output stream to the file created in " +
+                                        "the secondary file system because the path points to a directory: " + path);
+
+                                newAccessTime = secondaryFile.accessTime();
+                                newModificationTime = secondaryFile.modificationTime();
+                                newProps = secondaryFile.properties();
+                                newLen = secondaryFile.length();
+                                newBlockSize = secondaryFile.blockSize();
+                            }
+                            else {
+                                newAccessTime = System.currentTimeMillis();
+                                newModificationTime = newAccessTime;
+                                newProps = fileProps;
+                                newLen = 0L;
+                                newBlockSize = blockSize;
+                            }
+
+                            IgfsEntryInfo newInfo = invokeAndGet(overwriteId,
+                                new IgfsMetaFileCreateProcessor(newAccessTime, newModificationTime, newProps,
+                                    newBlockSize, affKey, newLockId, evictExclude, newLen));
 
                             // Prepare result and commit.
                             tx.commit();
 
                             IgfsUtils.sendEvents(igfsCtx.kernalContext(), path, EventType.EVT_IGFS_FILE_OPENED_WRITE);
 
-                            return newInfo;
+                            return new IgfsCreateResult(newInfo, secondaryOut);
                         }
                         else {
                             // Create file and parent folders.
-                            IgfsPathsCreateResult res =
-                                createFile(pathIds, lockInfos, dirProps, fileProps, blockSize, affKey, evictExclude);
+                            if (secondaryCtx != null)
+                                secondaryOut = secondaryCtx.create();
+
+                            IgfsPathsCreateResult res = createFile(pathIds, lockInfos, dirProps, fileProps, blockSize,
+                                affKey, evictExclude, secondaryCtx);
 
                             if (res == null)
                                 continue;
@@ -2921,10 +2934,20 @@ public class IgfsMetaManager extends IgfsManager {
                             // Generate events.
                             generateCreateEvents(res.createdPaths(), true);
 
-                            return res.info();
+                            return new IgfsCreateResult(res.info(), secondaryOut);
                         }
                     }
                 }
+                catch (IgniteException | IgniteCheckedException e) {
+                    U.closeQuiet(secondaryOut);
+
+                    throw e;
+                }
+                catch (Exception e) {
+                    U.closeQuiet(secondaryOut);
+
+                    throw new IgniteCheckedException("Create failed due to unexpected exception: " + path, e);
+                }
                 finally {
                     busyLock.leaveBusy();
                 }
@@ -2950,7 +2973,7 @@ public class IgfsMetaManager extends IgfsManager {
             throw new IgfsParentNotDirectoryException("Failed to create directory (parent " +
                 "element is not a directory)");
 
-        return createFileOrDirectory(true, pathIds, lockInfos, dirProps, null, 0, null, false);
+        return createFileOrDirectory(true, pathIds, lockInfos, dirProps, null, 0, null, false, null);
     }
 
     /**
@@ -2963,22 +2986,25 @@ public class IgfsMetaManager extends IgfsManager {
      * @param blockSize Block size.
      * @param affKey Affinity key (optional)
      * @param evictExclude Evict exclude flag.
+     * @param secondaryCtx Secondary file system create context.
      * @return Result or {@code} if the first parent already contained child with the same name.
      * @throws IgniteCheckedException If failed.
      */
     @Nullable private IgfsPathsCreateResult createFile(IgfsPathIds pathIds, Map<IgniteUuid, IgfsEntryInfo> lockInfos,
         Map<String, String> dirProps, Map<String, String> fileProps, int blockSize, @Nullable IgniteUuid affKey,
-        boolean evictExclude) throws IgniteCheckedException{
+        boolean evictExclude, @Nullable IgfsSecondaryFileSystemCreateContext secondaryCtx)
+        throws IgniteCheckedException{
         // Check if entry we are going to write to is directory.
         if (lockInfos.get(pathIds.lastExistingId()).isFile())
             throw new IgfsParentNotDirectoryException("Failed to open file for write " +
                 "(parent element is not a directory): " + pathIds.path());
 
-        return createFileOrDirectory(false, pathIds, lockInfos, dirProps, fileProps, blockSize, affKey, evictExclude);
+        return createFileOrDirectory(false, pathIds, lockInfos, dirProps, fileProps, blockSize, affKey, evictExclude,
+            secondaryCtx);
     }
 
     /**
-     * Ceate file or directory.
+     * Create file or directory.
      *
      * @param dir Directory flag.
      * @param pathIds Path IDs.
@@ -2988,12 +3014,15 @@ public class IgfsMetaManager extends IgfsManager {
      * @param blockSize Block size.
      * @param affKey Affinity key.
      * @param evictExclude Evict exclude flag.
+     * @param secondaryCtx Secondary file system create context.
      * @return Result.
      * @throws IgniteCheckedException If failed.
      */
+    @SuppressWarnings("unchecked")
     private IgfsPathsCreateResult createFileOrDirectory(boolean dir, IgfsPathIds pathIds,
         Map<IgniteUuid, IgfsEntryInfo> lockInfos, Map<String, String> dirProps, Map<String, String> fileProps,
-        int blockSize, @Nullable IgniteUuid affKey, boolean evictExclude) throws IgniteCheckedException {
+        int blockSize, @Nullable IgniteUuid affKey, boolean evictExclude,
+        @Nullable IgfsSecondaryFileSystemCreateContext secondaryCtx) throws IgniteCheckedException {
         // This is our starting point.
         int lastExistingIdx = pathIds.lastExistingIndex();
         IgfsEntryInfo lastExistingInfo = lockInfos.get(pathIds.lastExistingId());
@@ -3009,8 +3038,10 @@ public class IgfsMetaManager extends IgfsManager {
         if (lastExistingInfo.hasChild(curPart))
             return null;
 
+        Map<IgniteUuid, EntryProcessor> procMap = new HashMap<>();
+
         // First step: add new entry to the last existing element.
-        id2InfoPrj.invoke(lastExistingInfo.id(), new IgfsMetaDirectoryListingAddProcessor(curPart,
+        procMap.put(lastExistingInfo.id(), new IgfsMetaDirectoryListingAddProcessor(curPart,
             new IgfsListingEntry(curId, dir || !pathIds.isLastIndex(curIdx))));
 
         // Events support.
@@ -3019,20 +3050,44 @@ public class IgfsMetaManager extends IgfsManager {
         List<IgfsPath> createdPaths = new ArrayList<>(pathIds.count() - curIdx);
 
         // Second step: create middle directories.
-        long createTime = System.currentTimeMillis();
+        long curTime = System.currentTimeMillis();
 
         while (curIdx < pathIds.count() - 1) {
+            lastCreatedPath = new IgfsPath(lastCreatedPath, curPart);
+
             int nextIdx = curIdx + 1;
 
             String nextPart = pathIds.part(nextIdx);
             IgniteUuid nextId = pathIds.surrogateId(nextIdx);
 
-            id2InfoPrj.invoke(curId, new IgfsMetaDirectoryCreateProcessor(createTime, dirProps,
+            long accessTime;
+            long modificationTime;
+            Map<String, String> props;
+
+            if (secondaryCtx != null) {
+                IgfsFile secondaryInfo = secondaryCtx.fileSystem().info(lastCreatedPath);
+
+                if (secondaryInfo == null)
+                    throw new IgfsException("Failed to perform operation because secondary file system path was " +
+                        "modified concurrnetly: " + lastCreatedPath);
+                else if (secondaryInfo.isFile())
+                    throw new IgfsException("Failed to perform operation because secondary file system entity is " +
+                        "not directory: " + lastCreatedPath);
+
+                accessTime = secondaryInfo.accessTime();
+                modificationTime = secondaryInfo.modificationTime();
+                props = secondaryInfo.properties();
+            }
+            else {
+                accessTime = curTime;
+                modificationTime = curTime;
+                props = dirProps;
+            }
+
+            procMap.put(curId, new IgfsMetaDirectoryCreateProcessor(accessTime, modificationTime, props,
                 nextPart, new IgfsListingEntry(nextId, dir || !pathIds.isLastIndex(nextIdx))));
 
             // Save event.
-            lastCreatedPath = new IgfsPath(lastCreatedPath, curPart);
-
             createdPaths.add(lastCreatedPath);
 
             // Advance things further.
@@ -3043,16 +3098,75 @@ public class IgfsMetaManager extends IgfsManager {
         }
 
         // Third step: create leaf.
-        IgfsEntryInfo info;
+        if (dir) {
+            long accessTime;
+            long modificationTime;
+            Map<String, String> props;
 
-        if (dir)
-            info = invokeAndGet(curId, new IgfsMetaDirectoryCreateProcessor(createTime, dirProps));
-        else
-            info = invokeAndGet(curId, new IgfsMetaFileCreateProcessor(createTime, fileProps,
-                blockSize, affKey, createFileLockId(false), evictExclude));
+            if (secondaryCtx != null) {
+                IgfsFile secondaryInfo = secondaryCtx.fileSystem().info(pathIds.path());
+
+                if (secondaryInfo == null)
+                    throw new IgfsException("Failed to perform operation because secondary file system path was " +
+                        "modified concurrnetly: " + pathIds.path());
+                else if (secondaryInfo.isFile())
+                    throw new IgfsException("Failed to perform operation because secondary file system entity is " +
+                        "not directory: " + lastCreatedPath);
+
+                accessTime = secondaryInfo.accessTime();
+                modificationTime = secondaryInfo.modificationTime();
+                props = secondaryInfo.properties();
+            }
+            else {
+                accessTime = curTime;
+                modificationTime = curTime;
+                props = dirProps;
+            }
+
+            procMap.put(curId, new IgfsMetaDirectoryCreateProcessor(accessTime, modificationTime, props));
+        }
+        else {
+            long newAccessTime;
+            long newModificationTime;
+            Map<String, String> newProps;
+            long newLen;
+            int newBlockSize;
+
+            if (secondaryCtx != null) {
+                IgfsFile secondaryFile = secondaryCtx.info();
+
+                if (secondaryFile == null)
+                    throw fsException("Failed to open output stream to the file created in " +
+                        "the secondary file system because it no longer exists: " + pathIds.path());
+                else if (secondaryFile.isDirectory())
+                    throw fsException("Failed to open output stream to the file created in " +
+                        "the secondary file system because the path points to a directory: " + pathIds.path());
+
+                newAccessTime = secondaryFile.accessTime();
+                newModificationTime = secondaryFile.modificationTime();
+                newProps = secondaryFile.properties();
+                newLen = secondaryFile.length();
+                newBlockSize = secondaryFile.blockSize();
+            }
+            else {
+                newAccessTime = curTime;
+                newModificationTime = curTime;
+                newProps = fileProps;
+                newLen = 0L;
+                newBlockSize = blockSize;
+            }
+
+            procMap.put(curId, new IgfsMetaFileCreateProcessor(newAccessTime, newModificationTime, newProps,
+                newBlockSize, affKey, createFileLockId(false), evictExclude, newLen));
+        }
 
         createdPaths.add(pathIds.path());
 
+        // Execute cache operations.
+        Map<Object, EntryProcessorResult> invokeRes = ((IgniteInternalCache)id2InfoPrj).invokeAll(procMap);
+
+        IgfsEntryInfo info = (IgfsEntryInfo)invokeRes.get(curId).get();
+
         return new IgfsPathsCreateResult(createdPaths, info);
     }
 
@@ -3111,182 +3225,4 @@ public class IgfsMetaManager extends IgfsManager {
          */
         public T onFailure(Exception err) throws IgniteCheckedException;
     }
-
-    /**
-     * Synchronization task to create a file.
-     */
-    private class CreateFileSynchronizationTask implements SynchronizationTask<IgfsSecondaryOutputStreamDescriptor> {
-        /** Secondary file system. */
-        private IgfsSecondaryFileSystem fs;
-
-        /** Path. */
-        private IgfsPath path;
-
-        /** Simple create flag. */
-        private boolean simpleCreate;
-
-        /** Properties. */
-        private Map<String, String> props;
-
-        /** Overwrite flag. */
-        private boolean overwrite;
-
-        /** Buffer size. */
-        private int bufSize;
-
-        /** Replication factor. */
-        private short replication;
-
-        /** Block size. */
-        private long blockSize;
-
-        /** Affinity key. */
-        private IgniteUuid affKey;
-
-        /** Pending events. */
-        private Deque<IgfsEvent> pendingEvts;
-
-        /** Output stream to the secondary file system. */
-        private OutputStream out;
-
-        /**
-         * Constructor.
-         *
-         * @param fs Secondary file system.
-         * @param path Path.
-         * @param simpleCreate Simple create flag.
-         * @param props Properties.
-         * @param overwrite Overwrite flag.
-         * @param bufSize Buffer size.
-         * @param replication Replication factor.
-         * @param blockSize Block size.
-         * @param affKey Affinity key.
-         * @param pendingEvts Pending events.
-         */
-        public CreateFileSynchronizationTask(IgfsSecondaryFileSystem fs, IgfsPath path, boolean simpleCreate,
-            @Nullable Map<String, String> props, boolean overwrite, int bufSize, short replication, long blockSize,
-            IgniteUuid affKey, Deque<IgfsEvent> pendingEvts) {
-            this.fs = fs;
-            this.path = path;
-            this.simpleCreate = simpleCreate;
-            this.props = props;
-            this.overwrite = overwrite;
-            this.bufSize = bufSize;
-            this.replication = replication;
-            this.blockSize = blockSize;
-            this.affKey = affKey;
-            this.pendingEvts = pendingEvts;
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsSecondaryOutputStreamDescriptor onSuccess(Map<IgfsPath, IgfsEntryInfo> infos)
-            throws Exception {
-            validTxState(true);
-
-            assert !infos.isEmpty();
-
-            // Determine the first existing parent.
-            IgfsPath parentPath = null;
-
-            for (IgfsPath curPath : infos.keySet()) {
-                if (parentPath == null || curPath.isSubDirectoryOf(parentPath))
-                    parentPath = curPath;
-            }
-
-            assert parentPath != null;
-
-            IgfsEntryInfo parentInfo = infos.get(parentPath);
-
-            // Delegate to the secondary file system.
-            out = simpleCreate ? fs.create(path, overwrite) :
-                fs.create(path, bufSize, overwrite, replication, blockSize, props);
-
-            IgfsPath parent0 = path.parent();
-
-            assert parent0 != null : "path.parent() is null (are we creating ROOT?): " + path;
-
-            // If some of the parent directories were missing, synchronize again.
-            if (!parentPath.equals(parent0)) {
-                parentInfo = synchronize(fs, parentPath, parentInfo, parent0, true, null);
-
-                // Fire notification about missing directories creation.
-                if (evts.isRecordable(EventType.EVT_IGFS_DIR_CREATED)) {
-                    IgfsPath evtPath = parent0;
-
-                    while (!parentPath.equals(evtPath)) {
-                        pendingEvts.addFirst(new IgfsEvent(evtPath, locNode,
-                            EventType.EVT_IGFS_DIR_CREATED));
-
-                        evtPath = evtPath.parent();
-
-                        assert evtPath != null; // If this fails, then ROOT does not exist.
-                    }
-                }
-            }
-
-            // Get created file info.
-            IgfsFile status = fs.info(path);
-
-            if (status == null)
-                throw fsException("Failed to open output stream to the file created in " +
-                    "the secondary file system because it no longer exists: " + path);
-            else if (status.isDirectory())
-                throw fsException("Failed to open output stream to the file created in " +
-                    "the secondary file system because the path points to a directory: " + path);
-
-            IgfsEntryInfo newInfo = IgfsUtils.createFile(
-                IgniteUuid.randomUuid(),
-                status.blockSize(),
-                status.length(),
-                affKey,
-                createFileLockId(false),
-                igfsCtx.igfs().evictExclude(path, false),
-                status.properties(),
-                status.accessTime(),
-                status.modificationTime()
-            );
-
-            // Add new file info to the listing optionally removing the previous one.
-            assert parentInfo != null;
-
-            IgniteUuid oldId = putIfAbsentNonTx(parentInfo.id(), path.name(), newInfo);
-
-            if (oldId != null) {
-                IgfsEntryInfo oldInfo = info(oldId);
-
-                assert oldInfo != null; // Otherwise cache is in inconsistent state.
-
-                // The contact is that we cannot overwrite a file locked for writing:
-                if (oldInfo.lockId() != null)
-                    throw fsException("Failed to overwrite file (file is opened for writing) [path=" +
-                        path + ", fileId=" + oldId + ", lockId=" + oldInfo.lockId() + ']');
-
-                id2InfoPrj.remove(oldId); // Remove the old one.
-                id2InfoPrj.invoke(parentInfo.id(), new IgfsMetaDirectoryListingRemoveProcessor(
-                    path.name(), parentInfo.listing().get(path.name()).fileId()));
-
-                createNewEntry(newInfo, parentInfo.id(), path.name()); // Put new one.
-
-                igfsCtx.data().delete(oldInfo);
-            }
-
-            // Record CREATE event if needed.
-            if (oldId == null && evts.isRecordable(EventType.EVT_IGFS_FILE_CREATED))
-                pendingEvts.add(new IgfsEvent(path, locNode, EventType.EVT_IGFS_FILE_CREATED));
-
-            return new IgfsSecondaryOutputStreamDescriptor(newInfo, out);
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsSecondaryOutputStreamDescriptor onFailure(Exception err) throws IgniteCheckedException {
-            U.closeQuiet(out);
-
-            U.error(log, "File create in DUAL mode failed [path=" + path + ", simpleCreate=" +
-                simpleCreate + ", props=" + props + ", overwrite=" + overwrite + ", bufferSize=" +
-                bufSize + ", replication=" + replication + ", blockSize=" + blockSize + ']', err);
-
-            throw new IgniteCheckedException("Failed to create the file due to secondary file system " +
-                "exception: " + path, err);
-        }
-    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/40e6614f/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryFileSystemCreateContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryFileSystemCreateContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryFileSystemCreateContext.java
new file mode 100644
index 0000000..1c0efd6
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryFileSystemCreateContext.java
@@ -0,0 +1,111 @@
+/*
+ * 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.igfs.IgfsFile;
+import org.apache.ignite.igfs.IgfsPath;
+import org.apache.ignite.igfs.secondary.IgfsSecondaryFileSystem;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.OutputStream;
+import java.util.Map;
+
+/**
+ * Context for secondary file system create request.
+ */
+public class IgfsSecondaryFileSystemCreateContext {
+    /** File system. */
+    private final IgfsSecondaryFileSystem fs;
+
+    /** Path. */
+    private final IgfsPath path;
+
+    /** Overwrite flag. */
+    private final boolean overwrite;
+
+    /** Simple create flag. */
+    private final boolean simpleCreate;
+
+    /** Properties. */
+    private final Map<String, String> props;
+
+    /** Replication. */
+    private final short replication;
+
+    /** Block size. */
+    private final long blockSize;
+
+    /** Buffer size. */
+    private final int bufSize;
+
+    /**
+     * Constructor.
+     *
+     * @param fs File system.
+     * @param path Path.
+     * @param overwrite Overwrite flag.
+     * @param simpleCreate Simple create flag.
+     * @param props Properties.
+     * @param replication Replication.
+     * @param blockSize Block size.
+     * @param bufSize Buffer size.
+     */
+    public IgfsSecondaryFileSystemCreateContext(IgfsSecondaryFileSystem fs, IgfsPath path, boolean overwrite,
+        boolean simpleCreate, @Nullable Map<String, String> props, short replication, long blockSize, int bufSize) {
+        this.fs = fs;
+        this.path = path;
+        this.overwrite = overwrite;
+        this.simpleCreate = simpleCreate;
+        this.props = props;
+        this.replication = replication;
+        this.blockSize = blockSize;
+        this.bufSize = bufSize;
+    }
+
+    /**
+     * Create file in the secondary file system.
+     *
+     * @return Output stream.
+     */
+    public OutputStream create() {
+        return simpleCreate ? fs.create(path, overwrite) :
+            fs.create(path, bufSize, overwrite, replication, blockSize, props);
+    }
+
+    /**
+     * Get file info.
+     *
+     * @return File.
+     */
+    public IgfsFile info() {
+        return fs.info(path);
+    }
+
+    /**
+     * @return Secondary file system.
+     */
+    public IgfsSecondaryFileSystem fileSystem() {
+        return fs;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(IgfsSecondaryFileSystemCreateContext.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/40e6614f/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryOutputStreamDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryOutputStreamDescriptor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryOutputStreamDescriptor.java
deleted file mode 100644
index 6bbc2c0..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsSecondaryOutputStreamDescriptor.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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 java.io.OutputStream;
-
-/**
- * Descriptor of an output stream opened to the secondary file system.
- */
-public class IgfsSecondaryOutputStreamDescriptor {
-    /** File info in the primary file system. */
-    private final IgfsEntryInfo info;
-
-    /** Output stream to the secondary file system. */
-    private final OutputStream out;
-
-    /**
-     * Constructor.
-     *
-     * @param info File info in the primary file system.
-     * @param out Output stream to the secondary file system.
-     */
-    IgfsSecondaryOutputStreamDescriptor(IgfsEntryInfo info, OutputStream out) {
-        assert info != null;
-        assert out != null;
-
-        this.info = info;
-        this.out = out;
-    }
-
-    /**
-     * @return File info in the primary file system.
-     */
-    IgfsEntryInfo info() {
-        return info;
-    }
-
-    /**
-     * @return Output stream to the secondary file system.
-     */
-    OutputStream out() {
-        return out;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/40e6614f/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/meta/IgfsMetaDirectoryCreateProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/meta/IgfsMetaDirectoryCreateProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/meta/IgfsMetaDirectoryCreateProcessor.java
index eee9300..b016633 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/meta/IgfsMetaDirectoryCreateProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/meta/IgfsMetaDirectoryCreateProcessor.java
@@ -48,8 +48,11 @@ public class IgfsMetaDirectoryCreateProcessor implements EntryProcessor<IgniteUu
     /** */
     private static final long serialVersionUID = 0L;
 
-    /** Create time. */
-    private long createTime;
+    /** Access time. */
+    private long accessTime;
+
+    /** Modification time. */
+    private long modificationTime;
 
     /** Properties. */
     private Map<String, String> props;
@@ -70,24 +73,27 @@ public class IgfsMetaDirectoryCreateProcessor implements EntryProcessor<IgniteUu
     /**
      * Constructor.
      *
-     * @param createTime Create time.
+     * @param accessTime Create time.
+     * @param modificationTime Modification time.
      * @param props Properties.
      */
-    public IgfsMetaDirectoryCreateProcessor(long createTime, Map<String, String> props) {
-        this(createTime, props, null, null);
+    public IgfsMetaDirectoryCreateProcessor(long accessTime, long modificationTime, Map<String, String> props) {
+        this(accessTime, modificationTime, props, null, null);
     }
 
     /**
      * Constructor.
      *
-     * @param createTime Create time.
+     * @param accessTime Create time.
+     * @param modificationTime Modification time.
      * @param props Properties.
      * @param childName Child name.
      * @param childEntry Child entry.
      */
-    public IgfsMetaDirectoryCreateProcessor(long createTime, Map<String, String> props, String childName,
-        IgfsListingEntry childEntry) {
-        this.createTime = createTime;
+    public IgfsMetaDirectoryCreateProcessor(long accessTime, long modificationTime, Map<String, String> props,
+        String childName, IgfsListingEntry childEntry) {
+        this.accessTime = accessTime;
+        this.modificationTime = modificationTime;
         this.props = props;
         this.childName = childName;
         this.childEntry = childEntry;
@@ -101,8 +107,8 @@ public class IgfsMetaDirectoryCreateProcessor implements EntryProcessor<IgniteUu
             entry.getKey(),
             null,
             props,
-            createTime,
-            createTime
+            accessTime,
+            modificationTime
         );
 
         if (childName != null)
@@ -115,7 +121,8 @@ public class IgfsMetaDirectoryCreateProcessor implements EntryProcessor<IgniteUu
 
     /** {@inheritDoc} */
     @Override public void writeExternal(ObjectOutput out) throws IOException {
-        out.writeLong(createTime);
+        out.writeLong(accessTime);
+        out.writeLong(modificationTime);
 
         IgfsUtils.writeProperties(out, props);
 
@@ -127,7 +134,8 @@ public class IgfsMetaDirectoryCreateProcessor implements EntryProcessor<IgniteUu
 
     /** {@inheritDoc} */
     @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
-        createTime = in.readLong();
+        accessTime = in.readLong();
+        modificationTime = in.readLong();
 
         props = IgfsUtils.readProperties(in);
 
@@ -141,7 +149,8 @@ public class IgfsMetaDirectoryCreateProcessor implements EntryProcessor<IgniteUu
     @Override public void writeBinary(BinaryWriter writer) throws BinaryObjectException {
         BinaryRawWriter out = writer.rawWriter();
 
-        out.writeLong(createTime);
+        out.writeLong(accessTime);
+        out.writeLong(modificationTime);
 
         IgfsUtils.writeProperties(out, props);
 
@@ -155,7 +164,8 @@ public class IgfsMetaDirectoryCreateProcessor implements EntryProcessor<IgniteUu
     @Override public void readBinary(BinaryReader reader) throws BinaryObjectException {
         BinaryRawReader in = reader.rawReader();
 
-        createTime = in.readLong();
+        accessTime = in.readLong();
+        modificationTime = in.readLong();
 
         props = IgfsUtils.readProperties(in);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/40e6614f/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/meta/IgfsMetaFileCreateProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/meta/IgfsMetaFileCreateProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/meta/IgfsMetaFileCreateProcessor.java
index 8c4c296..a3e9d48 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/meta/IgfsMetaFileCreateProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/meta/IgfsMetaFileCreateProcessor.java
@@ -49,7 +49,10 @@ public class IgfsMetaFileCreateProcessor implements EntryProcessor<IgniteUuid, I
     private static final long serialVersionUID = 0L;
 
     /** Create time. */
-    private long createTime;
+    private long accessTime;
+
+    /** Modification time. */
+    private long modificationTime;
 
     /** Properties. */
     private Map<String, String> props;
@@ -66,6 +69,9 @@ public class IgfsMetaFileCreateProcessor implements EntryProcessor<IgniteUuid, I
     /** Evict exclude flag. */
     private boolean evictExclude;
 
+    /** File length. */
+    private long len;
+
     /**
      * Constructor.
      */
@@ -76,21 +82,25 @@ public class IgfsMetaFileCreateProcessor implements EntryProcessor<IgniteUuid, I
     /**
      * Constructor.
      *
-     * @param createTime Create time.
+     * @param accessTime Access time.
+     * @param modificationTime Modification time.
      * @param props Properties.
      * @param blockSize Block size.
      * @param affKey Affinity key.
      * @param lockId Lock ID.
      * @param evictExclude Evict exclude flag.
+     * @param len File length.
      */
-    public IgfsMetaFileCreateProcessor(long createTime, Map<String, String> props, int blockSize,
-        @Nullable IgniteUuid affKey, IgniteUuid lockId, boolean evictExclude) {
-        this.createTime = createTime;
+    public IgfsMetaFileCreateProcessor(long accessTime, long modificationTime, Map<String, String> props,
+        int blockSize, @Nullable IgniteUuid affKey, IgniteUuid lockId, boolean evictExclude, long len) {
+        this.accessTime = accessTime;
+        this.modificationTime = modificationTime;
         this.props = props;
         this.blockSize = blockSize;
         this.affKey = affKey;
         this.lockId = lockId;
         this.evictExclude = evictExclude;
+        this.len = len;
     }
 
     /** {@inheritDoc} */
@@ -99,13 +109,13 @@ public class IgfsMetaFileCreateProcessor implements EntryProcessor<IgniteUuid, I
         IgfsEntryInfo info = IgfsUtils.createFile(
             entry.getKey(),
             blockSize,
-            0L,
+            len,
             affKey,
             lockId,
             evictExclude,
             props,
-            createTime,
-            createTime
+            accessTime,
+            modificationTime
         );
 
         entry.setValue(info);
@@ -115,7 +125,8 @@ public class IgfsMetaFileCreateProcessor implements EntryProcessor<IgniteUuid, I
 
     /** {@inheritDoc} */
     @Override public void writeExternal(ObjectOutput out) throws IOException {
-        out.writeLong(createTime);
+        out.writeLong(accessTime);
+        out.writeLong(modificationTime);
 
         IgfsUtils.writeProperties(out, props);
 
@@ -123,11 +134,14 @@ public class IgfsMetaFileCreateProcessor implements EntryProcessor<IgniteUuid, I
         U.writeGridUuid(out, affKey);
         U.writeGridUuid(out, lockId);
         out.writeBoolean(evictExclude);
+
+        out.writeLong(len);
     }
 
     /** {@inheritDoc} */
     @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
-        createTime = in.readLong();
+        accessTime = in.readLong();
+        modificationTime = in.readLong();
 
         props = IgfsUtils.readProperties(in);
 
@@ -135,13 +149,16 @@ public class IgfsMetaFileCreateProcessor implements EntryProcessor<IgniteUuid, I
         affKey = U.readGridUuid(in);
         lockId = U.readGridUuid(in);
         evictExclude = in.readBoolean();
+
+        len = in.readLong();
     }
 
     /** {@inheritDoc} */
     @Override public void writeBinary(BinaryWriter writer) throws BinaryObjectException {
         BinaryRawWriter out = writer.rawWriter();
 
-        out.writeLong(createTime);
+        out.writeLong(accessTime);
+        out.writeLong(modificationTime);
 
         IgfsUtils.writeProperties(out, props);
 
@@ -149,13 +166,16 @@ public class IgfsMetaFileCreateProcessor implements EntryProcessor<IgniteUuid, I
         BinaryUtils.writeIgniteUuid(out, affKey);
         BinaryUtils.writeIgniteUuid(out, lockId);
         out.writeBoolean(evictExclude);
+
+        out.writeLong(len);
     }
 
     /** {@inheritDoc} */
     @Override public void readBinary(BinaryReader reader) throws BinaryObjectException {
         BinaryRawReader in = reader.rawReader();
 
-        createTime = in.readLong();
+        accessTime = in.readLong();
+        modificationTime = in.readLong();
 
         props = IgfsUtils.readProperties(in);
 
@@ -163,6 +183,8 @@ public class IgfsMetaFileCreateProcessor implements EntryProcessor<IgniteUuid, I
         affKey = BinaryUtils.readIgniteUuid(in);
         lockId = BinaryUtils.readIgniteUuid(in);
         evictExclude = in.readBoolean();
+
+        len = in.readLong();
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/40e6614f/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 8b88157..6053d3b 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
@@ -142,7 +142,7 @@ public class IgfsMetaManagerSelfTest extends IgfsCommonAbstractTest {
         assertEmpty(mgr.directoryListing(ROOT_ID));
 
         assertTrue(mgr.mkdirs(new IgfsPath("/dir"), IgfsImpl.DFLT_DIR_META));
-        assertNotNull(mgr.create(new IgfsPath("/file"), null, false, 400, null, false, null));
+        assertNotNull(mgr.create(new IgfsPath("/file"), null, false, 400, null, false, null, null));
 
         IgfsListingEntry dirEntry = mgr.directoryListing(ROOT_ID).get("dir");
         assertNotNull(dirEntry);
@@ -214,7 +214,7 @@ public class IgfsMetaManagerSelfTest extends IgfsCommonAbstractTest {
     private IgfsEntryInfo createFileAndGetInfo(String path) throws IgniteCheckedException {
         IgfsPath p = path(path);
 
-        IgfsEntryInfo res = mgr.create(p, null, false, 400, null, false, null);
+        IgfsEntryInfo res = mgr.create(p, null, false, 400, null, false, null, null).info();
 
         assert res != null;
         assert !res.isDirectory();