ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From voze...@apache.org
Subject [11/12] ignite git commit: Merge branch 'ignite-2834' into ignite-2813
Date Fri, 18 Mar 2016 14:07:25 GMT
Merge branch 'ignite-2834' into ignite-2813

# Conflicts:
#	modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
#	modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsMetaManager.java
#	modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsUtils.java
#	modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsAbstractSelfTest.java
#	modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMetaManagerSelfTest.java


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

Branch: refs/heads/ignite-2813
Commit: 7a41eda213fcd93e470efe0dbbd7a0d974b3ff0f
Parents: faa897f 1b10643
Author: vozerov-gridgain <vozerov@gridgain.com>
Authored: Fri Mar 18 17:01:48 2016 +0300
Committer: vozerov-gridgain <vozerov@gridgain.com>
Committed: Fri Mar 18 17:01:48 2016 +0300

----------------------------------------------------------------------
 .../configuration/FileSystemConfiguration.java  |   47 +
 .../java/org/apache/ignite/igfs/IgfsPath.java   |    9 +
 .../apache/ignite/internal/IgniteKernal.java    |    2 +-
 .../org/apache/ignite/internal/IgnitionEx.java  |   10 +-
 .../managers/communication/GridIoManager.java   |   10 +
 .../GridCachePartitionExchangeManager.java      |    3 +
 .../processors/cache/GridCacheUtils.java        |   14 +-
 .../IgfsColocatedMetadataAffinityKeyMapper.java |   47 +
 .../internal/processors/igfs/IgfsImpl.java      |   59 +-
 .../processors/igfs/IgfsMetaManager.java        | 1014 +++++++++---------
 .../internal/processors/igfs/IgfsPathIds.java   |  291 +++++
 .../processors/igfs/IgfsPathsCreateResult.java  |   77 ++
 .../internal/processors/igfs/IgfsUtils.java     |   79 +-
 .../util/nio/GridNioRecoveryDescriptor.java     |   21 +-
 .../ignite/internal/util/nio/GridNioServer.java |   52 +-
 .../communication/tcp/TcpCommunicationSpi.java  |    8 +
 .../tcp/TcpCommunicationSpiMBean.java           |    8 +-
 .../ComputeJobCancelWithServiceSelfTest.java    |  154 +++
 .../processors/igfs/IgfsAbstractSelfTest.java   |   39 +-
 .../igfs/IgfsMetaManagerSelfTest.java           |   31 +-
 .../processors/igfs/IgfsProcessorSelfTest.java  |   26 +-
 .../processors/igfs/IgfsStartCacheTest.java     |    7 +-
 .../ignite/testsuites/IgniteCacheTestSuite.java |    3 +-
 .../testsuites/IgniteKernalSelfTestSuite.java   |    2 +
 .../apache/ignite/igfs/IgfsEventsTestSuite.java |   10 +-
 25 files changed, 1415 insertions(+), 608 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/7a41eda2/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
index 7fea118,9ec583c..398428a
--- 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
@@@ -1033,8 -1034,15 +1034,15 @@@ public final class IgfsImpl implements 
                  else
                      dirProps = fileProps = new HashMap<>(props);
  
-                 IgniteBiTuple<IgfsEntryInfo, IgniteUuid> t2 = meta.create(path, false/*append*/,
overwrite, dirProps,
-                     cfg.getBlockSize(), affKey, evictExclude(path, true), fileProps);
 -                IgniteBiTuple<IgfsFileInfo, IgniteUuid> t2 = meta.create(
++                IgniteBiTuple<IgfsEntryInfo, IgniteUuid> t2 = meta.create(
+                     path,
+                     dirProps,
+                     overwrite,
+                     cfg.getBlockSize(),
+                     affKey,
+                     evictExclude(path, true),
+                     fileProps
+                 );
  
                  assert t2 != null;
  
@@@ -1104,8 -1112,15 +1112,15 @@@
                  else
                      dirProps = fileProps = new HashMap<>(props);
  
-                 IgniteBiTuple<IgfsEntryInfo, IgniteUuid> t2 = meta.create(path, true/*append*/,
false/*overwrite*/,
-                     dirProps, cfg.getBlockSize(), null/*affKey*/, evictExclude(path, true),
fileProps);
 -                IgniteBiTuple<IgfsFileInfo, IgniteUuid> t2 = meta.append(
++                IgniteBiTuple<IgfsEntryInfo, IgniteUuid> t2 = meta.append(
+                     path,
+                     dirProps,
+                     create,
+                     cfg.getBlockSize(),
+                     null/*affKey*/,
+                     evictExclude(path, true),
+                     fileProps
+                 );
  
                  assert t2 != null;
  

http://git-wip-us.apache.org/repos/asf/ignite/blob/7a41eda2/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsMetaManager.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsMetaManager.java
index 67ca475,d91b0bc..d7d6048
--- 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
@@@ -845,82 -901,46 +903,46 @@@ public class IgfsMetaManager extends Ig
                  IgniteInternalTx tx = startTx();
  
                  try {
-                     // 3. Obtain the locks.
-                     final Map<IgniteUuid, IgfsEntryInfo> allInfos = lockIds(allIds);
+                     // Obtain the locks.
 -                    final Map<IgniteUuid, IgfsFileInfo> lockInfos = lockIds(lockIds);
++                    final Map<IgniteUuid, IgfsEntryInfo> lockInfos = lockIds(lockIds);
  
-                     // 4. Verify integrity of source directory.
-                     if (!verifyPathIntegrity(srcPath, srcPathIds, allInfos)) {
+                     // Verify integrity of source and destination paths.
+                     if (!srcPathIds.verifyIntegrity(lockInfos))
                          throw new IgfsPathNotFoundException("Failed to perform move because
source directory " +
                              "structure changed concurrently [src=" + srcPath + ", dst="
+ dstPath + ']');
-                     }
- 
-                     // 5. Verify integrity of destination directory.
-                     final IgfsPath dstDirPath = dstLeafId != null ? dstPath : dstPath.parent();
  
-                     if (!verifyPathIntegrity(dstDirPath, dstPathIds, allInfos)) {
+                     if (!dstPathIds.verifyIntegrity(lockInfos))
                          throw new IgfsPathNotFoundException("Failed to perform move because
destination directory " +
                              "structure changed concurrently [src=" + srcPath + ", dst="
+ dstPath + ']');
-                     }
- 
-                     // 6. Calculate source and destination targets which will be changed.
-                     IgniteUuid srcTargetId = srcPathIds.get(srcPathIds.size() - 2);
-                     IgfsEntryInfo srcTargetInfo = allInfos.get(srcTargetId);
-                     String srcName = srcPath.name();
- 
-                     IgniteUuid dstTargetId;
-                     IgfsEntryInfo dstTargetInfo;
-                     String dstName;
- 
-                     if (dstLeafId != null) {
-                         // Destination leaf exists. Check if it is an empty directory.
-                         IgfsEntryInfo dstLeafInfo = allInfos.get(dstLeafId);
  
-                         assert dstLeafInfo != null;
+                     // Addiional check: is destination directory?
 -                    IgfsFileInfo dstParentInfo = lockInfos.get(dstPathIds.lastId());
++                    IgfsEntryInfo dstParentInfo = lockInfos.get(dstPathIds.lastId());
  
-                         if (dstLeafInfo.isDirectory()) {
-                             // Destination is a directory.
-                             dstTargetId = dstLeafId;
-                             dstTargetInfo = dstLeafInfo;
-                             dstName = srcPath.name();
-                         }
-                         else {
-                             // Error, destination is existing file.
-                             throw new IgfsPathAlreadyExistsException("Failed to perform
move " +
-                                 "because destination points to " +
-                                 "existing file [src=" + srcPath + ", dst=" + dstPath + ']');
-                         }
-                     }
-                     else {
-                         // Destination leaf doesn't exist, so we operate on parent.
-                         dstTargetId = dstPathIds.get(dstPathIds.size() - 1);
-                         dstTargetInfo = allInfos.get(dstTargetId);
-                         dstName = dstPath.name();
-                     }
- 
-                     assert dstTargetInfo != null;
-                     assert dstTargetInfo.isDirectory();
+                     if (dstParentInfo.isFile())
+                         throw new IgfsPathAlreadyExistsException("Failed to perform move
because destination points " +
+                             "to existing file [src=" + srcPath + ", dst=" + dstPath + ']');
  
-                     // 7. Last check: does destination target already have listing entry
with the same name?
-                     if (dstTargetInfo.hasChild(dstName)) {
+                     // Additional check: does destination already has child with the same
name?
+                     if (dstParentInfo.hasChild(dstName))
                          throw new IgfsPathAlreadyExistsException("Failed to perform move
because destination already " +
                              "contains entry with the same name existing file [src=" + srcPath
+
                              ", dst=" + dstPath + ']');
-                     }
  
-                     // 8. Actual move: remove from source parent and add to destination
target.
-                     IgfsListingEntry entry = srcTargetInfo.listing().get(srcName);
+                     // Actual move: remove from source parent and add to destination target.
+                     IgfsFileInfo srcParentInfo = lockInfos.get(srcPathIds.lastParentId());
  
-                     transferEntry(entry, srcTargetId, srcName, dstTargetId, dstName);
+                     IgfsFileInfo srcInfo = lockInfos.get(srcPathIds.lastId());
+                     String srcName = srcPathIds.lastPart();
+                     IgfsListingEntry srcEntry = srcParentInfo.listing().get(srcName);
  
-                     tx.commit();
+                     transferEntry(srcEntry, srcParentInfo.id(), srcName, dstParentInfo.id(),
dstName);
  
-                     IgfsPath realNewPath = new IgfsPath(dstDirPath, dstName);
+                     tx.commit();
  
-                     IgfsEntryInfo moved = allInfos.get(srcPathIds.get(srcPathIds.size()
- 1));
+                     IgfsPath newPath = new IgfsPath(dstPathIds.path(), dstName);
  
                      // Set the new path to the info to simplify event creation:
-                     return moved.path(realNewPath);
 -                    return IgfsFileInfo.builder(srcInfo).path(newPath).build();
++                    return IgfsEntryInfo.builder(srcInfo).path(newPath).build();
                  }
                  finally {
                      tx.close();
@@@ -1153,37 -1172,19 +1178,19 @@@
                          throw new IgfsDirectoryNotEmptyException("Failed to remove directory
(directory is not " +
                              "empty and recursive flag is not set).");
  
-                     IgfsEntryInfo destInfo = infoMap.get(trashId);
- 
-                     assert destInfo != null;
- 
-                     final String srcFileName = path.name();
- 
-                     final String destFileName = victimId.toString();
- 
-                     assert !destInfo.hasChild(destFileName) : "Failed to add file name into
the " +
-                         "destination directory (file already exists) [destName=" + destFileName
+ ']';
- 
-                     IgfsEntryInfo srcParentInfo = infoMap.get(pathIdList.get(pathIdList.size()
- 2));
+                     // Prepare trash data.
+                     IgfsFileInfo trashInfo = lockInfos.get(trashId);
+                     final String trashName = victimId.toString();
  
-                     assert srcParentInfo != null;
+                     assert !trashInfo.hasChild(trashName) : "Failed to add file name into
the " +
+                         "destination directory (file already exists) [destName=" + trashName
+ ']';
  
-                     IgniteUuid srcParentId = srcParentInfo.id();
-                     assert srcParentId.equals(pathIdList.get(pathIdList.size() - 2));
+                     IgniteUuid parentId = pathIds.lastParentId();
 -                    IgfsFileInfo parentInfo = lockInfos.get(parentId);
++                    IgfsEntryInfo parentInfo = lockInfos.get(parentId);
  
-                     IgfsListingEntry srcEntry = srcParentInfo.listing().get(srcFileName);
- 
-                     assert srcEntry != null : "Deletion victim not found in parent listing
[path=" + path +
-                         ", name=" + srcFileName + ", listing=" + srcParentInfo.listing()
+ ']';
- 
-                     assert victimId.equals(srcEntry.fileId());
- 
-                     transferEntry(srcEntry, srcParentId, srcFileName, trashId, destFileName);
+                     transferEntry(parentInfo.listing().get(victimName), parentId, victimName,
trashId, trashName);
  
                      if (victimInfo.isFile())
-                         // Update a file info of the removed file with a file path,
-                         // which will be used by delete worker for event notifications.
                          invokeUpdatePath(victimId, path);
  
                      tx.commit();
@@@ -3219,19 -3179,10 +3212,10 @@@
              this.entry = entry;
          }
  
-         /**
-          * Empty constructor required for {@link Externalizable}.
-          *
-          */
-         public ListingAddProcessor() {
-             // No-op.
-         }
- 
          /** {@inheritDoc} */
 -        @Override public Void process(MutableEntry<IgniteUuid, IgfsFileInfo> e, Object...
args) {
 -            IgfsFileInfo fileInfo = e.getValue();
 +        @Override public Void process(MutableEntry<IgniteUuid, IgfsEntryInfo> e, Object...
args) {
 +            IgfsEntryInfo fileInfo = e.getValue();
  
-             assert fileInfo != null : "File info not found for the child: " + entry.fileId();
              assert fileInfo.isDirectory();
  
              Map<String, IgfsListingEntry> listing = new HashMap<>(fileInfo.listing());
@@@ -3508,219 -3438,286 +3473,286 @@@
          }
      }
  
-     /** File chain builder. */
-     private class DirectoryChainBuilder {
-         /** The requested path to be created. */
-         private final IgfsPath path;
+     /**
+      * Create a new file.
+      *
+      * @param path Path.
+      * @param bufSize Buffer size.
+      * @param overwrite Overwrite flag.
+      * @param affKey Affinity key.
+      * @param replication Replication factor.
+      * @param props Properties.
+      * @param simpleCreate Whether new file should be created in secondary FS using create(Path,
boolean) method.
+      * @return Tuple containing the created file info and its parent id.
+      */
 -    IgniteBiTuple<IgfsFileInfo, IgniteUuid> create(
++    IgniteBiTuple<IgfsEntryInfo, IgniteUuid> 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 {
+         validTxState(false);
  
-         /** Full path components. */
-         private final List<String> components;
+         while (true) {
+             if (busyLock.enterBusy()) {
+                 try {
+                     // Prepare path IDs.
+                     IgfsPathIds pathIds = pathIds(path);
  
-         /** The list of ids. */
-         private final List<IgniteUuid> idList;
+                     // Prepare lock IDs.
+                     Set<IgniteUuid> lockIds = new TreeSet<>(PATH_ID_SORTING_COMPARATOR);
  
-         /** The set of ids. */
-         private final SortedSet<IgniteUuid> idSet = new TreeSet<IgniteUuid>(PATH_ID_SORTING_COMPARATOR);
+                     pathIds.addExistingIds(lockIds);
+                     pathIds.addSurrogateIds(lockIds);
  
-         /** The middle node properties. */
-         private final Map<String, String> props;
+                     // In overwrite mode we also lock ID of potential replacement as well
as trash ID.
+                     IgniteUuid overwriteId = IgniteUuid.randomUuid();
+                     IgniteUuid trashId = IgfsUtils.randomTrashId();
  
-         /** The leaf node properties. */
-         private final Map<String, String> leafProps;
+                     if (overwrite) {
+                         lockIds.add(overwriteId);
  
-         /** The lowermost exsiting path id. */
-         private final IgniteUuid lowermostExistingId;
+                         // Trash ID is only added if we suspect conflict.
+                         if (pathIds.allExists())
+                             lockIds.add(trashId);
+                     }
  
-         /** The existing path. */
-         private final IgfsPath existingPath;
+                     // Start TX.
+                     IgniteInternalTx tx = startTx();
  
-         /** The created leaf info. */
-         private IgfsEntryInfo leafInfo;
+                     try {
+                         Map<IgniteUuid, IgfsFileInfo> lockInfos = lockIds(lockIds);
  
-         /** The leaf parent id. */
-         private IgniteUuid leafParentId;
+                         if (!pathIds.verifyIntegrity(lockInfos))
+                             // Directory structure changed concurrently. So we simply re-try.
+                             continue;
  
-         /** The number of existing ids. */
-         private final int existingIdCnt;
+                         if (pathIds.allExists()) {
+                             // All participants found.
+                             IgfsFileInfo oldInfo = lockInfos.get(pathIds.lastId());
  
-         /** Whether laef is directory. */
-         private final boolean leafDir;
+                             // Check: is it a file?
+                             if (!oldInfo.isFile())
+                                 throw new IgfsPathIsDirectoryException("Failed to create
a file: " + path);
  
-         /** Block size. */
-         private final int blockSize;
+                             // Check: can we overwrite it?
+                             if (!overwrite)
+                                 throw new IgfsPathAlreadyExistsException("Failed to create
a file: " + path);
  
-         /** Affinity key. */
-         private final IgniteUuid affKey;
+                             // Check if file already opened for write.
+                             if (oldInfo.lockId() != null)
+                                 throw new IgfsException("File is already opened for write:
" + path);
  
-         /** Evict exclude flag. */
-         private final boolean evictExclude;
+                             // At this point file can be re-created safely.
  
-         /**
-          * Constructor for directories.
-          *
-          * @param path Path.
-          * @param props Properties.
-          * @throws IgniteCheckedException If failed.
-          */
-         protected DirectoryChainBuilder(IgfsPath path, Map<String, String> props)
throws IgniteCheckedException {
-             this(path, props, props, true, 0, null, false);
-         }
+                             // First step: add existing to trash listing.
+                             IgniteUuid oldId = pathIds.lastId();
  
-         /**
-          * Constructor for files.
-          *
-          * @param path Path.
-          * @param dirProps Directory properties.
-          * @param fileProps File properties.
-          * @param blockSize Block size.
-          * @param affKey Affinity key (optional).
-          * @param evictExclude Evict exclude flag.
-          * @throws IgniteCheckedException If failed.
-          */
-         protected DirectoryChainBuilder(IgfsPath path, Map<String, String> dirProps,
Map<String, String> fileProps,
-             int blockSize, @Nullable IgniteUuid affKey, boolean evictExclude)
-             throws IgniteCheckedException {
-             this(path, dirProps, fileProps, false, blockSize, affKey, evictExclude);
-         }
+                             id2InfoPrj.invoke(trashId, new ListingAddProcessor(oldId.toString(),
+                                 new IgfsListingEntry(oldId, true)));
  
-         /**
-          * Constructor.
-          *
-          * @param path Path.
-          * @param props Middle properties.
-          * @param leafProps Leaf properties.
-          * @param leafDir Whether leaf is directory or file.
-          * @param blockSize Block size.
-          * @param affKey Affinity key (optional).
-          * @param evictExclude Evict exclude flag.
-          * @throws IgniteCheckedException If failed.
-          */
-         private DirectoryChainBuilder(IgfsPath path, Map<String,String> props, Map<String,String>
leafProps,
-             boolean leafDir, int blockSize, @Nullable IgniteUuid affKey, boolean evictExclude)
-             throws IgniteCheckedException {
-             this.path = path;
-             this.components = path.components();
-             this.idList = fileIds(path);
-             this.props = props;
-             this.leafProps = leafProps;
-             this.leafDir = leafDir;
-             this.blockSize = blockSize;
-             this.affKey = affKey;
-             this.evictExclude = evictExclude;
+                             // Second step: replace ID in parent directory.
+                             String name = pathIds.lastPart();
+                             IgniteUuid parentId = pathIds.lastParentId();
+ 
+                             id2InfoPrj.invoke(parentId, new ListingReplaceProcessor(name,
overwriteId));
+ 
+                             // Third step: create the file.
+                             long createTime = System.currentTimeMillis();
  
-             // Store all the non-null ids in the set & construct existing path in one
loop:
-             IgfsPath existingPath = path.root();
+                             IgfsFileInfo newInfo = invokeAndGet(overwriteId, new FileCreateProcessor(createTime,
+                                 fileProps, blockSize, affKey, createFileLockId(false), evictExclude));
  
-             assert idList.size() == components.size() + 1;
+                             // Fourth step: update path of remove file.
+                             invokeUpdatePath(oldId, path);
  
-             // Find the lowermost existing id:
-             IgniteUuid lowermostExistingId = null;
+                             // Prepare result and commit.
+                             IgniteBiTuple<IgfsFileInfo, IgniteUuid> t2 = new T2<>(newInfo,
parentId);
  
-             int idIdx = 0;
+                             tx.commit();
  
-             for (IgniteUuid id : idList) {
-                 if (id == null)
-                     break;
+                             IgfsUtils.sendEvents(igfsCtx.kernalContext(), path, EventType.EVT_IGFS_FILE_OPENED_WRITE);
  
-                 lowermostExistingId = id;
+                             return t2;
+                         }
+                         else {
+                             // Create file and parent folders.
+                             IgfsPathsCreateResult res =
+                                 createFile(pathIds, lockInfos, dirProps, fileProps, blockSize,
affKey, evictExclude);
  
-                 boolean added = idSet.add(id);
+                             if (res == null)
+                                 continue;
  
-                 assert added : "Not added id = " + id;
+                             // Commit.
+                             tx.commit();
  
-                 if (idIdx >= 1) // skip root.
-                     existingPath = new IgfsPath(existingPath, components.get(idIdx - 1));
+                             // Generate events.
+                             generateCreateEvents(res.createdPaths(), true);
  
-                 idIdx++;
+                             return new T2<>(res.info(), res.parentId());
+                         }
+                     }
+                     finally {
+                         tx.close();
+                     }
+                 }
+                 finally {
+                     busyLock.leaveBusy();
+                 }
              }
+             else
+                 throw new IllegalStateException("Failed to mkdir because Grid is stopping.
[path=" + path + ']');
+         }
+     }
  
-             assert idSet.contains(IgfsUtils.ROOT_ID);
+     /**
+      * Create directory and it's parents.
+      *
+      * @param pathIds Path IDs.
+      * @param lockInfos Lock infos.
+      * @param dirProps Directory properties.
+      * @return Result or {@code} if the first parent already contained child with the same
name.
+      * @throws IgniteCheckedException If failed.
+      */
+     @Nullable IgfsPathsCreateResult createDirectory(IgfsPathIds pathIds, Map<IgniteUuid,
IgfsFileInfo> lockInfos,
+         Map<String, String> dirProps) throws IgniteCheckedException {
+         // Check if entry we are going to write to is directory.
+         if (lockInfos.get(pathIds.lastExistingId()).isFile())
+             throw new IgfsParentNotDirectoryException("Failed to create directory (parent
" +
+                 "element is not a directory)");
  
-             this.lowermostExistingId = lowermostExistingId;
+         return createFileOrDirectory(true, pathIds, lockInfos, dirProps, null, 0, null,
false);
+     }
  
-             this.existingPath = existingPath;
+     /**
+      * Create file and all it's parents.
+      *
+      * @param pathIds Paths IDs.
+      * @param lockInfos Lock infos.
+      * @param dirProps Directory properties.
+      * @param fileProps File propertris.
+      * @param blockSize Block size.
+      * @param affKey Affinity key (optional)
+      * @param evictExclude Evict exclude flag.
+      * @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,
IgfsFileInfo> lockInfos,
+         Map<String, String> dirProps, Map<String, String> fileProps, int blockSize,
@Nullable IgniteUuid affKey,
+         boolean evictExclude) 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());
  
-             this.existingIdCnt = idSet.size();
-         }
+         return createFileOrDirectory(false, pathIds, lockInfos, dirProps, fileProps, blockSize,
affKey, evictExclude);
+     }
  
-         /**
-          * Does the main portion of job building the renmaining path.
-          */
-         public final void doBuild() throws IgniteCheckedException {
-             // Fix current time. It will be used in all created entities.
-             long createTime = System.currentTimeMillis();
+     /**
+      * Ceate file or directory.
+      *
+      * @param dir Directory flag.
+      * @param pathIds Path IDs.
+      * @param lockInfos Lock infos.
+      * @param dirProps Directory properties.
+      * @param fileProps File properties.
+      * @param blockSize Block size.
+      * @param affKey Affinity key.
+      * @param evictExclude Evict exclude flag.
+      * @return Result.
+      * @throws IgniteCheckedException If failed.
+      */
+     private IgfsPathsCreateResult createFileOrDirectory(boolean dir, IgfsPathIds pathIds,
+         Map<IgniteUuid, IgfsFileInfo> lockInfos, Map<String, String> dirProps,
Map<String, String> fileProps,
+         int blockSize, @Nullable IgniteUuid affKey, boolean evictExclude) throws IgniteCheckedException
{
+         // This is our starting point.
+         int lastExistingIdx = pathIds.lastExistingIndex();
+         IgfsFileInfo lastExistingInfo = lockInfos.get(pathIds.lastExistingId());
  
-             IgfsListingEntry childInfo = null;
-             String childName = null;
+         // If current info already contains entry with the same name as it's child, then
something
+         // has changed concurrently. We must re-try because we cannot get info of this unexpected
+         // element due to possible deadlocks.
+         int curIdx = lastExistingIdx + 1;
  
-             IgniteUuid parentId = null;
+         String curPart = pathIds.part(curIdx);
+         IgniteUuid curId = pathIds.surrogateId(curIdx);
+         IgniteUuid curParentId = lastExistingInfo.id();
  
-             // This loop creates the missing directory chain from the bottom to the top:
-             for (int i = components.size() - 1; i >= existingIdCnt - 1; i--) {
-                 IgniteUuid childId = IgniteUuid.randomUuid();
-                 boolean childDir;
+         if (lastExistingInfo.hasChild(curPart))
+             return null;
  
-                 if (childName == null) {
-                     assert childInfo == null;
+         // First step: add new entry to the last existing element.
+         id2InfoPrj.invoke(lastExistingInfo.id(), new ListingAddProcessor(curPart,
+             new IgfsListingEntry(curId, dir || !pathIds.isLastIndex(curIdx))));
  
-                     if (leafDir) {
-                         childDir = true;
+         // Events support.
+         IgfsPath lastCreatedPath = pathIds.lastExistingPath();
  
-                         leafInfo = invokeAndGet(childId, new DirectoryCreateProcessor(createTime,
leafProps));
-                     }
-                     else {
-                         childDir = false;
+         List<IgfsPath> createdPaths = new ArrayList<>(pathIds.count() - curIdx);
  
-                         leafInfo = invokeAndGet(childId, new FileCreateProcessor(createTime,
leafProps, blockSize,
-                             affKey, createFileLockId(false), evictExclude));
-                     }
-                 }
-                 else {
-                     assert childInfo != null;
+         // Second step: create middle directories.
+         long createTime = System.currentTimeMillis();
  
-                     childDir = true;
+         while (curIdx < pathIds.count() - 1) {
+             int nextIdx = curIdx + 1;
  
-                     id2InfoPrj.invoke(childId, new DirectoryCreateProcessor(createTime,
props, childName, childInfo));
+             String nextPart = pathIds.part(nextIdx);
+             IgniteUuid nextId = pathIds.surrogateId(nextIdx);
  
-                     if (parentId == null)
-                         parentId = childId;
-                 }
+             id2InfoPrj.invoke(curId, new DirectoryCreateProcessor(createTime, dirProps,
+                 nextPart, new IgfsListingEntry(nextId, dir || !pathIds.isLastIndex(nextIdx))));
  
-                 childInfo = new IgfsListingEntry(childId, childDir);
+             // Save event.
+             lastCreatedPath = new IgfsPath(lastCreatedPath, curPart);
  
-                 childName = components.get(i);
-             }
+             createdPaths.add(lastCreatedPath);
  
-             if (parentId == null)
-                 parentId = lowermostExistingId;
+             // Advance things further.
+             curIdx++;
  
-             leafParentId = parentId;
+             curParentId = curId;
  
-             // Now link the newly created directory chain to the lowermost existing parent:
-             id2InfoPrj.invoke(lowermostExistingId, new ListingAddProcessor(childName, childInfo));
+             curPart = nextPart;
+             curId = nextId;
          }
  
-         /**
-          * Sends events.
-          */
-         public final void sendEvents() {
-             if (evts.isRecordable(EVT_IGFS_DIR_CREATED)) {
-                 IgfsPath createdPath = existingPath;
+         // Third step: create leaf.
+         IgfsFileInfo info;
  
-                 for (int i = existingPath.components().size(); i < components.size()
- 1; i++) {
-                     createdPath = new IgfsPath(createdPath, components.get(i));
+         if (dir)
+             info = invokeAndGet(curId, new DirectoryCreateProcessor(createTime, dirProps));
+         else
+             info = invokeAndGet(curId, new FileCreateProcessor(createTime, fileProps,
+                 blockSize, affKey, createFileLockId(false), evictExclude));
  
-                     IgfsUtils.sendEvents(igfsCtx.kernalContext(), createdPath, EVT_IGFS_DIR_CREATED);
-                 }
-             }
+         createdPaths.add(pathIds.path());
  
-             if (leafDir)
-                 IgfsUtils.sendEvents(igfsCtx.kernalContext(), path, EVT_IGFS_DIR_CREATED);
-             else {
-                 IgfsUtils.sendEvents(igfsCtx.kernalContext(), path, EVT_IGFS_FILE_CREATED);
-                 IgfsUtils.sendEvents(igfsCtx.kernalContext(), path, EVT_IGFS_FILE_OPENED_WRITE);
-             }
+         return new IgfsPathsCreateResult(createdPaths, info, curParentId);
+     }
+ 
+     /**
+      * Generate events for created file or directory.
+      *
+      * @param createdPaths Created paths.
+      * @param file Whether file was created.
+      */
+     private void generateCreateEvents(List<IgfsPath> createdPaths, boolean file) {
+         if (evts.isRecordable(EventType.EVT_IGFS_DIR_CREATED)) {
+             for (int i = 0; i < createdPaths.size() - 1; i++)
+                 IgfsUtils.sendEvents(igfsCtx.kernalContext(), createdPaths.get(i),
+                     EventType.EVT_IGFS_DIR_CREATED);
          }
+ 
+         IgfsPath leafPath = createdPaths.get(createdPaths.size() - 1);
+ 
+         if (file) {
+             IgfsUtils.sendEvents(igfsCtx.kernalContext(), leafPath, EventType.EVT_IGFS_FILE_CREATED);
+             IgfsUtils.sendEvents(igfsCtx.kernalContext(), leafPath, EventType.EVT_IGFS_FILE_OPENED_WRITE);
+         }
+         else
+             IgfsUtils.sendEvents(igfsCtx.kernalContext(), leafPath, EventType.EVT_IGFS_DIR_CREATED);
      }
  
      /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/7a41eda2/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsUtils.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsUtils.java
index bd3c0b8,ef7d5c7..6844d42
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsUtils.java
@@@ -256,69 -269,56 +269,123 @@@ public class IgfsUtils 
      }
  
      /**
+      * @param cfg Grid configuration.
+      * @param cacheName Cache name.
+      * @return {@code True} in this is IGFS data or meta cache.
+      */
+     public static boolean isIgfsCache(IgniteConfiguration cfg, @Nullable String cacheName)
{
+         FileSystemConfiguration[] igfsCfgs = cfg.getFileSystemConfiguration();
+ 
+         if (igfsCfgs != null) {
+             for (FileSystemConfiguration igfsCfg : igfsCfgs) {
+                 // IGFS config probably has not been validated yet => possible NPE, so
we check for null.
+                 if (igfsCfg != null) {
+                     if (F.eq(cacheName, igfsCfg.getDataCacheName()) || F.eq(cacheName, igfsCfg.getMetaCacheName()))
+                         return true;
+                 }
+             }
+         }
+ 
+         return false;
+     }
+ 
+     /**
+      * Prepare cache configuration if this is IGFS meta or data cache.
+      *
+      * @param cfg Configuration.
+      * @param ccfg Cache configuration.
+      */
+     public static void prepareCacheConfiguration(IgniteConfiguration cfg, CacheConfiguration
ccfg) {
+         FileSystemConfiguration[] igfsCfgs = cfg.getFileSystemConfiguration();
+ 
+         if (igfsCfgs != null) {
+             for (FileSystemConfiguration igfsCfg : igfsCfgs) {
+                 if (igfsCfg != null) {
+                     if (F.eq(ccfg.getName(), igfsCfg.getMetaCacheName())) {
+                         ccfg.setCopyOnRead(false);
+ 
+                         // Set co-located affinity mapper if needed.
+                         if (igfsCfg.isColocateMetadata() && ccfg.getCacheMode()
== CacheMode.REPLICATED &&
+                             ccfg.getAffinityMapper() == null)
+                             ccfg.setAffinityMapper(new IgfsColocatedMetadataAffinityKeyMapper());
+ 
+                         return;
+                     }
+ 
+                     if (F.eq(ccfg.getName(), igfsCfg.getDataCacheName())) {
+                         ccfg.setCopyOnRead(false);
+ 
+                         return;
+                     }
+                 }
+             }
+         }
+     }
++
++    /**
 +     * Create empty directory with the given ID.
 +     *
 +     * @param id ID.
 +     * @return File info.
 +     */
 +    public static IgfsDirectoryInfo createDirectory(IgniteUuid id) {
 +        return createDirectory(id, null, null);
 +    }
 +
 +    /**
 +     * Create directory.
 +     *
 +     * @param id ID.
 +     * @param listing Listing.
 +     * @param props Properties.
 +     * @return File info.
 +     */
 +    public static IgfsDirectoryInfo createDirectory(
 +        IgniteUuid id,
 +        @Nullable Map<String, IgfsListingEntry> listing,
 +        @Nullable Map<String, String> props) {
 +        long time = System.currentTimeMillis();
 +
 +        return createDirectory(id, listing, props, time, time);
 +    }
 +
 +    /**
 +     * Create directory.
 +     *
 +     * @param id ID.
 +     * @param listing Listing.
 +     * @param props Properties.
 +     * @param createTime Create time.
 +     * @param modificationTime Modification time.
 +     * @return File info.
 +     */
 +    public static IgfsDirectoryInfo createDirectory(
 +        IgniteUuid id,
 +        @Nullable Map<String, IgfsListingEntry> listing,
 +        @Nullable Map<String,String> props,
 +        long createTime,
 +        long modificationTime) {
 +        return new IgfsDirectoryInfo(id, listing, props, createTime, modificationTime);
 +    }
 +
 +    /**
 +     * Create file.
 +     *
 +     * @param id File ID.
 +     * @param blockSize Block size.
 +     * @param len Length.
 +     * @param affKey Affinity key.
 +     * @param lockId Lock ID.
 +     * @param evictExclude Evict exclude flag.
 +     * @param props Properties.
 +     * @param accessTime Access time.
 +     * @param modificationTime Modification time.
 +     * @return File info.
 +     */
 +    public static IgfsFileInfo createFile(IgniteUuid id, int blockSize, long len, @Nullable
IgniteUuid affKey,
 +        @Nullable IgniteUuid lockId, boolean evictExclude, @Nullable Map<String, String>
props, long accessTime,
 +        long modificationTime) {
 +        return new IgfsFileInfo(id, blockSize, len, affKey, props, null, lockId, accessTime,
modificationTime,
 +            evictExclude);
 +    }
  }

http://git-wip-us.apache.org/repos/asf/ignite/blob/7a41eda2/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsAbstractSelfTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/7a41eda2/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMetaManagerSelfTest.java
----------------------------------------------------------------------
diff --cc modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMetaManagerSelfTest.java
index a42471d,26424f0..3dc2791
--- 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
@@@ -209,10 -211,10 +211,10 @@@ public class IgfsMetaManagerSelfTest ex
          return info;
      }
  
 -    private IgfsFileInfo createFileAndGetInfo(String path) throws IgniteCheckedException
{
 +    private IgfsEntryInfo createFileAndGetInfo(String path) throws IgniteCheckedException
{
          IgfsPath p = path(path);
  
-         IgniteBiTuple<IgfsEntryInfo, IgniteUuid> t2 = mgr.create(p, false, false,
null, 400, null, false, null);
 -        IgniteBiTuple<IgfsFileInfo, IgniteUuid> t2 = mgr.create(p, null, false, 400,
null, false, null);
++        IgniteBiTuple<IgfsEntryInfo, IgniteUuid> t2 = mgr.create(p, null, false, 400,
null, false, null);
  
          assert t2 != null;
          assert !t2.get1().isDirectory();

http://git-wip-us.apache.org/repos/asf/ignite/blob/7a41eda2/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsProcessorSelfTest.java
----------------------------------------------------------------------


Mime
View raw message