ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From voze...@apache.org
Subject ignite git commit: Implemented mkdirs.
Date Thu, 17 Mar 2016 21:38:14 GMT
Repository: ignite
Updated Branches:
  refs/heads/ignite-igfs-refactoring 182cc36de -> 8b093a7f6


Implemented mkdirs.


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

Branch: refs/heads/ignite-igfs-refactoring
Commit: 8b093a7f679664cdd5bd93dabf593527ea6ed404
Parents: 182cc36
Author: thatcoach <ppozerov@list.ru>
Authored: Fri Mar 18 00:32:46 2016 +0300
Committer: thatcoach <ppozerov@list.ru>
Committed: Fri Mar 18 00:32:46 2016 +0300

----------------------------------------------------------------------
 .../processors/igfs/IgfsMetaManager.java        | 123 ++++++++++++-------
 .../internal/processors/igfs/IgfsPathIds.java   |  79 ++++++++++++
 2 files changed, 156 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/8b093a7f/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 e419117..233cb13 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
@@ -1635,74 +1635,111 @@ public class IgfsMetaManager extends IgfsManager {
      *
      * @param path The path to create.
      * @param props The properties to use for created directories.
-     * @return True iff a directory was created during the operation.
+     * @return True if a directory was created during the operation.
      * @throws IgniteCheckedException If a non-directory file exists on the requested path,
and in case of other errors.
      */
     boolean mkdirs(final IgfsPath path, final Map<String, String> props) throws IgniteCheckedException
{
         assert props != null;
         validTxState(false);
 
-        DirectoryChainBuilder b = null;
-
         while (true) {
             if (busyLock.enterBusy()) {
                 try {
-                    b = new DirectoryChainBuilder(path, props);
+                    // Prepare path IDs.
+                    IgfsPathIds pathIds = pathIds(path);
+
+                    // Prepare lock IDs. Essentially, they consist of two parts: existing
IDs and potential new IDs.
+                    Set<IgniteUuid> lockIds = new TreeSet<>(PATH_ID_SORTING_COMPARATOR);
+
+                    pathIds.addExistingIds(lockIds);
+                    pathIds.addSurrogateIds(lockIds);
+
+                    assert lockIds.size() == pathIds.count();
 
                     // Start TX.
                     IgniteInternalTx tx = startTx();
 
                     try {
-                        final Map<IgniteUuid, IgfsFileInfo> lockedInfos = lockIds(b.idSet);
+                        final Map<IgniteUuid, IgfsFileInfo> lockInfos = lockIds(lockIds);
 
-                        // If the path was changed, we close the current Tx and repeat the
procedure again
-                        // starting from taking the path ids.
-                        if (verifyPathIntegrity(b.existingPath, b.idList, lockedInfos)) {
-                            // Locked path okay, trying to proceed with the remainder creation.
-                            IgfsFileInfo lowermostExistingInfo = lockedInfos.get(b.lowermostExistingId);
+                        if (!pathIds.verifyIntergrity(lockInfos))
+                            // Directory structure changed concurrently. So we simply re-try.
+                            continue;
 
-                            // Check only the lowermost directory in the existing directory
chain
-                            // because others are already checked in #verifyPathIntegrity()
above.
-                            if (!lowermostExistingInfo.isDirectory())
+                        // This is our starting point.
+                        int lastExistingIdx = pathIds.lastExistingIndex();
+                        IgfsFileInfo lastExistingInfo = lockInfos.get(pathIds.lastExistingId());
+
+                        // Check if the whole structure is already in place.
+                        if (pathIds.allPartsFound()) {
+                            if (lastExistingInfo.isDirectory())
+                                return false;
+                            else
                                 throw new IgfsParentNotDirectoryException("Failed to create
directory (parent " +
                                     "element is not a directory)");
+                        }
 
-                            if (b.existingIdCnt == b.components.size() + 1) {
-                                assert b.existingPath.equals(path);
-                                assert lockedInfos.size() == b.existingIdCnt;
+                        // Check if entry we are going to write to is directory.
+                        if (lastExistingInfo.isFile())
+                            throw new IgfsParentNotDirectoryException("Failed to create directory
(parent " +
+                                "element is not a directory)");
 
-                                // The target directory already exists, nothing to do.
-                                // (The fact that all the path consisns of directories is
already checked above).
-                                // Note that properties are not updated in this case.
-                                return false;
-                            }
+                        // 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;
 
-                            Map<String, IgfsListingEntry> parentListing = lowermostExistingInfo.listing();
+                        String curPart = pathIds.part(curIdx);
+                        IgniteUuid curId = pathIds.surrogateId(curIdx);
 
-                            String shortName = b.components.get(b.existingIdCnt - 1);
+                        if (lastExistingInfo.hasChild(curPart))
+                            continue;
 
-                            IgfsListingEntry entry = parentListing.get(shortName);
+                        // First step: add new entry to the last existing element.
+                        id2InfoPrj.invoke(lastExistingInfo.id(),
+                            new ListingAddProcessor(curPart, new IgfsListingEntry(curId,
true)));
 
-                            if (entry == null) {
-                                b.doBuild();
+                        // Events support.
+                        IgfsPath lastCreatedPath = pathIds.lastExistingPath();
 
-                                tx.commit();
+                        Collection<IgfsPath> createdPaths = new ArrayList<>(pathIds.count()
- curIdx);
 
-                                break;
-                            }
-                            else {
-                                // Another thread created file or directory with the same
name.
-                                if (!entry.isDirectory()) {
-                                    // Entry exists, and it is not a directory:
-                                    throw new IgfsParentNotDirectoryException("Failed to
create directory (parent " +
-                                        "element is not a directory)");
-                                }
+                        // Second step: create middle directories.
+                        long createTime = System.currentTimeMillis();
 
-                                // If this is a directory, we continue the repeat loop,
-                                // because we cannot lock this directory without
-                                // lock ordering rule violation.
-                            }
+                        while (curIdx < pathIds.count() - 1) {
+                            String nextPart = pathIds.part(curIdx + 1);
+                            IgniteUuid nextId = pathIds.surrogateId(curIdx + 1);
+
+                            id2InfoPrj.invoke(curId, new DirectoryCreateProcessor(createTime,
props,
+                                nextPart, new IgfsListingEntry(nextId, true)));
+
+                            // Save event.
+                            lastCreatedPath = new IgfsPath(lastCreatedPath, curPart);
+
+                            createdPaths.add(lastCreatedPath);
+
+                            // Advance things further.
+                            curIdx++;
+
+                            curPart = nextPart;
+                            curId = nextId;
                         }
+
+                        // Third step: create leaf directory.
+                        id2InfoPrj.invoke(curId, new DirectoryCreateProcessor(createTime,
props));
+
+                        // Commit TX.
+                        tx.commit();
+
+                        // Generate events.
+                        if (evts.isRecordable(EVT_IGFS_DIR_CREATED)) {
+                            for (IgfsPath createdPath : createdPaths)
+                                IgfsUtils.sendEvents(igfsCtx.kernalContext(), createdPath,
EVT_IGFS_DIR_CREATED);
+                        }
+
+                        // We are done.
+                        return true;
                     }
                     finally {
                         tx.close();
@@ -1715,12 +1752,6 @@ public class IgfsMetaManager extends IgfsManager {
             else
                 throw new IllegalStateException("Failed to mkdir because Grid is stopping.
[path=" + path + ']');
         }
-
-        assert b != null;
-
-        b.sendEvents();
-
-        return true;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/8b093a7f/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsPathIds.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsPathIds.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsPathIds.java
index 8d0bf5c..ce72aae 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsPathIds.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsPathIds.java
@@ -37,6 +37,9 @@ public class IgfsPathIds {
     /** IDs. */
     private final IgniteUuid[] ids;
 
+    /** Surrogate IDs for paths which doesn't exist yet. Initialized on demand. */
+    private IgniteUuid[] surrogateIds;
+
     /** Index of last existing ID. */
     private final int lastExistingIdx;
 
@@ -115,6 +118,13 @@ public class IgfsPathIds {
     }
 
     /**
+     * @return Index of the last existing element.
+     */
+    public int lastExistingIndex() {
+        return lastExistingIdx;
+    }
+
+    /**
      * @return Whether last existing path part has parent.
      */
     public boolean lastExistingHasParent() {
@@ -154,6 +164,23 @@ public class IgfsPathIds {
     }
 
     /**
+     * Add surrogate IDs to provided collection potentially creating them on demand.
+     *
+     * @param col Collection.
+     */
+    public void addSurrogateIds(Collection<IgniteUuid> col) {
+        if (surrogateIds == null) {
+            surrogateIds = new IgniteUuid[ids.length];
+
+            for (int i = lastExistingIdx + 1; i < surrogateIds.length; i++)
+                surrogateIds[i] = IgniteUuid.randomUuid();
+        }
+
+        for (int i = lastExistingIdx + 1; i < surrogateIds.length; i++)
+            col.add(surrogateIds[i]);
+    }
+
+    /**
      * Verify that observed paths are found in provided infos in the right order.
      *
      * @param infos Info.
@@ -197,4 +224,56 @@ public class IgfsPathIds {
 
         return new IgfsPathIds(path.parent(), parentParts, parentIds);
     }
+
+    /**
+     * @return ID count.
+     */
+    public int count() {
+        return ids.length;
+    }
+
+    /**
+     * @return Existing ID count.
+     */
+    public int existingCount() {
+        return lastExistingIdx + 1;
+    }
+
+    /**
+     *
+     * @param idx
+     * @return
+     */
+    public String part(int idx) {
+        assert idx < parts.length;
+
+        return parts[idx];
+    }
+
+    /**
+     *
+     * @param idx
+     * @return
+     */
+    public IgniteUuid surrogateId(int idx) {
+        assert surrogateIds != null;
+
+        assert idx > lastExistingIdx;
+        assert idx < surrogateIds.length;
+
+        return surrogateIds[idx];
+    }
+
+    /**
+     *
+     * @return
+     */
+    public IgfsPath lastExistingPath() {
+        IgfsPath path = new IgfsPath();
+
+        for (int i = 1; i <= lastExistingIdx; i++)
+            path = new IgfsPath(path, parts[i]);
+
+        return path;
+    }
 }


Mime
View raw message