Search in sources :

Example 1 with IgfsConcurrentModificationException

use of org.apache.ignite.igfs.IgfsConcurrentModificationException in project ignite by apache.

the class IgfsMetaManager method synchronizeAndExecute.

/**
     * Synchronize file system structure and then execute provided task. All these actions are performed withing
     * the transaction.
     *
     * @param task Task to execute.
     * @param fs File system.
     * @param strict Whether paths must be re-created strictly.
     * @param extraLockIds Additional IDs to lock (optional).
     * @param paths Paths to synchronize.
     * @return Result of task execution.
     * @throws IgniteCheckedException If failed.
     */
@SuppressWarnings({ "Contract", "ConstantConditions" })
private <T> T synchronizeAndExecute(SynchronizationTask<T> task, IgfsSecondaryFileSystem fs, boolean strict, @Nullable Collection<IgniteUuid> extraLockIds, IgfsPath... paths) throws IgniteCheckedException {
    assert task != null;
    assert fs != null;
    assert paths != null && paths.length > 0;
    // Sort paths so that we know in which order to synchronize them.
    if (paths.length > 1)
        Arrays.sort(paths);
    boolean finished = false;
    T res = null;
    while (!finished) {
        // Obtain existing IDs outside the transaction.
        List<List<IgniteUuid>> pathIds = new ArrayList<>(paths.length);
        for (IgfsPath path : paths) pathIds.add(idsForPath(path));
        // Start pessimistic.
        try (GridNearTxLocal tx = startTx()) {
            // Lock the very first existing parents and possibly the leaf as well.
            Map<IgfsPath, IgfsPath> pathToParent = new HashMap<>();
            Map<IgfsPath, IgniteUuid> pathToId = new HashMap<>();
            for (int i = 0; i < paths.length; i++) {
                IgfsPath path = paths[i];
                // Determine the very first existing parent
                List<IgniteUuid> ids = pathIds.get(i);
                if (ids.size() > 1) {
                    // The path is not root.
                    IgfsPath parentPath = path.parent();
                    IgniteUuid parentId = ids.get(ids.size() - 2);
                    for (int j = ids.size() - 3; j >= 0; j--) {
                        if (parentId != null)
                            break;
                        else {
                            parentPath = parentPath.parent();
                            parentId = ids.get(j);
                        }
                    }
                    assert parentPath != null && parentId != null;
                    pathToParent.put(path, parentPath);
                    pathToId.put(parentPath, parentId);
                }
                IgniteUuid pathId = ids.get(ids.size() - 1);
                if (pathId != null)
                    pathToId.put(path, pathId);
            }
            IgniteUuid[] lockArr = new IgniteUuid[extraLockIds == null ? pathToId.size() : pathToId.size() + extraLockIds.size()];
            int idx = 0;
            for (IgniteUuid id : pathToId.values()) lockArr[idx++] = id;
            if (extraLockIds != null) {
                for (IgniteUuid id : extraLockIds) lockArr[idx++] = id;
            }
            Map<IgniteUuid, IgfsEntryInfo> idToInfo = lockIds(lockArr);
            if (extraLockIds != null) {
                for (IgniteUuid id : extraLockIds) idToInfo.remove(id);
            }
            // Ensure that locked IDs still point to expected paths.
            IgfsPath changed = null;
            for (Map.Entry<IgfsPath, IgniteUuid> entry : pathToId.entrySet()) {
                if (!idToInfo.containsKey(entry.getValue()) || !F.eq(entry.getValue(), fileId(entry.getKey(), true))) {
                    changed = entry.getKey();
                    break;
                }
            }
            if (changed != null) {
                finished = true;
                throw fsException(new IgfsConcurrentModificationException("File system entry has been " + "modified concurrently: " + changed));
            } else {
                boolean newParents = false;
                // Check whether any new parents appeared before we have obtained the locks.
                for (int i = 0; i < paths.length; i++) {
                    List<IgniteUuid> newIds = fileIds(paths[i], true);
                    if (!pathIds.get(i).equals(newIds)) {
                        newParents = true;
                        break;
                    }
                }
                if (newParents)
                    // Release all locks and try again.
                    continue;
                else {
                    // Perform synchronization.
                    Map<IgfsPath, IgfsEntryInfo> infos = new HashMap<>();
                    TreeMap<IgfsPath, IgfsEntryInfo> created = new TreeMap<>();
                    for (IgfsPath path : paths) {
                        IgfsPath parentPath = path.parent();
                        if (pathToId.containsKey(path)) {
                            infos.put(path, info(pathToId.get(path)));
                            if (parentPath != null)
                                infos.put(parentPath, info(pathToId.get(parentPath)));
                        } else {
                            IgfsPath firstParentPath = pathToParent.get(path);
                            assert firstParentPath != null;
                            assert pathToId.get(firstParentPath) != null;
                            IgfsEntryInfo info = synchronize(fs, firstParentPath, idToInfo.get(pathToId.get(firstParentPath)), path, strict, created);
                            assert strict && info != null || !strict;
                            if (info != null)
                                infos.put(path, info);
                            if (parentPath != null) {
                                if (parentPath.equals(firstParentPath))
                                    infos.put(firstParentPath, idToInfo.get(pathToId.get(firstParentPath)));
                                else {
                                    assert strict && created.get(parentPath) != null || !strict;
                                    if (created.get(parentPath) != null)
                                        infos.put(parentPath, created.get(parentPath));
                                    else {
                                        // Put the last created path.
                                        infos.put(created.lastKey(), created.get(created.lastKey()));
                                    }
                                }
                            }
                        }
                    }
                    // Finally, execute the task.
                    finished = true;
                    try {
                        res = task.onSuccess(infos);
                    } catch (Exception e) {
                        res = task.onFailure(e);
                    }
                }
            }
            tx.commit();
        } catch (IgniteCheckedException e) {
            if (!finished) {
                finished = true;
                res = task.onFailure(e);
            } else
                throw e;
        }
    }
    return res;
}
Also used : HashMap(java.util.HashMap) IgfsConcurrentModificationException(org.apache.ignite.igfs.IgfsConcurrentModificationException) ArrayList(java.util.ArrayList) GridNearTxLocal(org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal) TreeMap(java.util.TreeMap) IgfsPathAlreadyExistsException(org.apache.ignite.igfs.IgfsPathAlreadyExistsException) IgfsParentNotDirectoryException(org.apache.ignite.igfs.IgfsParentNotDirectoryException) IgfsPathIsDirectoryException(org.apache.ignite.igfs.IgfsPathIsDirectoryException) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) IgniteException(org.apache.ignite.IgniteException) ClusterTopologyException(org.apache.ignite.cluster.ClusterTopologyException) IgniteInterruptedException(org.apache.ignite.IgniteInterruptedException) IgniteInterruptedCheckedException(org.apache.ignite.internal.IgniteInterruptedCheckedException) IgfsDirectoryNotEmptyException(org.apache.ignite.igfs.IgfsDirectoryNotEmptyException) IgfsException(org.apache.ignite.igfs.IgfsException) IgfsConcurrentModificationException(org.apache.ignite.igfs.IgfsConcurrentModificationException) IgfsPathIsNotDirectoryException(org.apache.ignite.igfs.IgfsPathIsNotDirectoryException) IgfsPathNotFoundException(org.apache.ignite.igfs.IgfsPathNotFoundException) GridClosureException(org.apache.ignite.internal.util.lang.GridClosureException) IgfsPath(org.apache.ignite.igfs.IgfsPath) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) IgniteUuid(org.apache.ignite.lang.IgniteUuid) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) Map(java.util.Map) HashMap(java.util.HashMap) GridLeanMap(org.apache.ignite.internal.util.GridLeanMap) TreeMap(java.util.TreeMap)

Aggregations

ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 Map (java.util.Map)1 TreeMap (java.util.TreeMap)1 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)1 IgniteException (org.apache.ignite.IgniteException)1 IgniteInterruptedException (org.apache.ignite.IgniteInterruptedException)1 ClusterTopologyException (org.apache.ignite.cluster.ClusterTopologyException)1 IgfsConcurrentModificationException (org.apache.ignite.igfs.IgfsConcurrentModificationException)1 IgfsDirectoryNotEmptyException (org.apache.ignite.igfs.IgfsDirectoryNotEmptyException)1 IgfsException (org.apache.ignite.igfs.IgfsException)1 IgfsParentNotDirectoryException (org.apache.ignite.igfs.IgfsParentNotDirectoryException)1 IgfsPath (org.apache.ignite.igfs.IgfsPath)1 IgfsPathAlreadyExistsException (org.apache.ignite.igfs.IgfsPathAlreadyExistsException)1 IgfsPathIsDirectoryException (org.apache.ignite.igfs.IgfsPathIsDirectoryException)1 IgfsPathIsNotDirectoryException (org.apache.ignite.igfs.IgfsPathIsNotDirectoryException)1 IgfsPathNotFoundException (org.apache.ignite.igfs.IgfsPathNotFoundException)1 IgniteInterruptedCheckedException (org.apache.ignite.internal.IgniteInterruptedCheckedException)1