Search in sources :

Example 46 with GridNearTxLocal

use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal in project ignite by apache.

the class IgfsMetaManager method delete.

/**
     * Remove entry from the metadata listing.
     * Used solely by IgfsDeleteWorker.
     *
     * @param parentId Parent ID.
     * @param name Name.
     * @param id ID.
     * @return {@code True} in case the entry really was removed from the cache by this call.
     * @throws IgniteCheckedException If failed.
     */
boolean delete(IgniteUuid parentId, String name, IgniteUuid id) throws IgniteCheckedException {
    if (busyLock.enterBusy()) {
        try {
            validTxState(false);
            try (GridNearTxLocal tx = startTx()) {
                Map<IgniteUuid, IgfsEntryInfo> infos = lockIds(parentId, id);
                IgfsEntryInfo victim = infos.get(id);
                if (victim == null)
                    return false;
                assert victim.isDirectory() || IgfsUtils.DELETE_LOCK_ID.equals(victim.lockId()) : " isDir: " + victim.isDirectory() + ", lockId: " + victim.lockId();
                // Proceed only in case both parent and child exist.
                if (infos.containsKey(parentId) && infos.containsKey(id)) {
                    IgfsEntryInfo parentInfo = infos.get(parentId);
                    assert parentInfo != null;
                    IgfsListingEntry childEntry = parentInfo.listing().get(name);
                    if (childEntry != null)
                        id2InfoPrj.invoke(parentId, new IgfsMetaDirectoryListingRemoveProcessor(name, id));
                    id2InfoPrj.remove(id);
                    tx.commit();
                    return true;
                }
                return false;
            }
        } finally {
            busyLock.leaveBusy();
        }
    } else
        throw new IllegalStateException("Failed to perform delete because Grid is stopping [parentId=" + parentId + ", name=" + name + ", id=" + id + ']');
}
Also used : IgniteUuid(org.apache.ignite.lang.IgniteUuid) IgfsMetaDirectoryListingRemoveProcessor(org.apache.ignite.internal.processors.igfs.meta.IgfsMetaDirectoryListingRemoveProcessor) GridNearTxLocal(org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal)

Example 47 with GridNearTxLocal

use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal 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)

Example 48 with GridNearTxLocal

use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal in project ignite by apache.

the class IgfsMetaManager method move.

/**
     * Move routine.
     *
     * @param srcPath Source path.
     * @param dstPath Destination path.
     * @throws IgniteCheckedException In case of exception.
     */
public void move(IgfsPath srcPath, IgfsPath dstPath) throws IgniteCheckedException {
    if (busyLock.enterBusy()) {
        try {
            validTxState(false);
            // Prepare path IDs.
            IgfsPathIds srcPathIds = pathIds(srcPath);
            IgfsPathIds dstPathIds = pathIds(dstPath);
            // Source path must exists.
            if (!srcPathIds.allExists())
                throw new IgfsPathNotFoundException("Failed to perform move because source path is not " + "found: " + srcPath);
            // At this point we need to understand name of resulting entry. It will be either destination leaf
            // or source leaf depending on existence.
            String dstName;
            if (dstPathIds.lastExists())
                //  Full destination path exists -> use source name.
                dstName = srcPathIds.lastPart();
            else {
                if (dstPathIds.lastParentExists()) {
                    // Destination path doesn't exists -> use destination name.
                    dstName = dstPathIds.lastPart();
                    dstPathIds = dstPathIds.parent();
                } else
                    // Destination parent is not found either -> exception.
                    throw new IgfsPathNotFoundException("Failed to perform move because destination path is not " + "found: " + dstPath.parent());
            }
            // Lock participating IDs.
            final Set<IgniteUuid> lockIds = new TreeSet<>(PATH_ID_SORTING_COMPARATOR);
            srcPathIds.addExistingIds(lockIds, relaxed);
            dstPathIds.addExistingIds(lockIds, relaxed);
            try (GridNearTxLocal tx = startTx()) {
                // Obtain the locks.
                final Map<IgniteUuid, IgfsEntryInfo> lockInfos = lockIds(lockIds);
                // Verify integrity of source and destination paths.
                if (!srcPathIds.verifyIntegrity(lockInfos, relaxed))
                    throw new IgfsPathNotFoundException("Failed to perform move because source directory " + "structure changed concurrently [src=" + srcPath + ", dst=" + dstPath + ']');
                if (!dstPathIds.verifyIntegrity(lockInfos, relaxed))
                    throw new IgfsPathNotFoundException("Failed to perform move because destination directory " + "structure changed concurrently [src=" + srcPath + ", dst=" + dstPath + ']');
                // Addiional check: is destination directory?
                IgfsEntryInfo dstParentInfo = lockInfos.get(dstPathIds.lastId());
                if (dstParentInfo.isFile())
                    throw new IgfsPathAlreadyExistsException("Failed to perform move because destination points " + "to existing file [src=" + srcPath + ", dst=" + dstPath + ']');
                // 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 + ']');
                // Actual move: remove from source parent and add to destination target.
                IgfsEntryInfo srcParentInfo = lockInfos.get(srcPathIds.lastParentId());
                IgfsEntryInfo srcInfo = lockInfos.get(srcPathIds.lastId());
                String srcName = srcPathIds.lastPart();
                IgfsListingEntry srcEntry = srcParentInfo.listing().get(srcName);
                transferEntry(srcEntry, srcParentInfo.id(), srcName, dstParentInfo.id(), dstName);
                tx.commit();
                // Fire events.
                IgfsPath newPath = new IgfsPath(dstPathIds.path(), dstName);
                IgfsUtils.sendEvents(igfsCtx.kernalContext(), srcPath, newPath, srcInfo.isFile() ? EVT_IGFS_FILE_RENAMED : EVT_IGFS_DIR_RENAMED);
            }
        } finally {
            busyLock.leaveBusy();
        }
    } else
        throw new IllegalStateException("Failed to perform move because Grid is stopping [srcPath=" + srcPath + ", dstPath=" + dstPath + ']');
}
Also used : GridNearTxLocal(org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal) IgfsPathNotFoundException(org.apache.ignite.igfs.IgfsPathNotFoundException) IgfsPathAlreadyExistsException(org.apache.ignite.igfs.IgfsPathAlreadyExistsException) IgfsPath(org.apache.ignite.igfs.IgfsPath) TreeSet(java.util.TreeSet) IgniteUuid(org.apache.ignite.lang.IgniteUuid)

Aggregations

GridNearTxLocal (org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal)48 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)20 IgniteUuid (org.apache.ignite.lang.IgniteUuid)10 IgniteException (org.apache.ignite.IgniteException)9 Map (java.util.Map)8 HashMap (java.util.HashMap)7 GridClosureException (org.apache.ignite.internal.util.lang.GridClosureException)7 TreeSet (java.util.TreeSet)6 UUID (java.util.UUID)6 Callable (java.util.concurrent.Callable)6 Nullable (org.jetbrains.annotations.Nullable)6 ClusterNode (org.apache.ignite.cluster.ClusterNode)5 IgfsException (org.apache.ignite.igfs.IgfsException)5 IgfsPathNotFoundException (org.apache.ignite.igfs.IgfsPathNotFoundException)5 IgniteInternalFuture (org.apache.ignite.internal.IgniteInternalFuture)5 ArrayList (java.util.ArrayList)4 HashSet (java.util.HashSet)4 IgfsPathAlreadyExistsException (org.apache.ignite.igfs.IgfsPathAlreadyExistsException)4 IgfsPathIsDirectoryException (org.apache.ignite.igfs.IgfsPathIsDirectoryException)4 IgniteInterruptedCheckedException (org.apache.ignite.internal.IgniteInterruptedCheckedException)4