Search in sources :

Example 1 with Scoped

use of alluxio.util.interfaces.Scoped in project alluxio by Alluxio.

the class InodeTree method syncPersistExistingDirectory.

/**
 * Synchronously persists an inode directory to the UFS. If concurrent calls are made, only
 * one thread will persist to UFS, and the others will wait until it is persisted.
 *
 * @param context journal context supplier
 * @param dir the inode directory to persist
 * @throws InvalidPathException if the path for the inode is invalid
 * @throws FileDoesNotExistException if the path for the inode is invalid
 */
public void syncPersistExistingDirectory(Supplier<JournalContext> context, InodeDirectoryView dir) throws IOException, InvalidPathException, FileDoesNotExistException {
    RetryPolicy retry = new ExponentialBackoffRetry(PERSIST_WAIT_BASE_SLEEP_MS, PERSIST_WAIT_MAX_SLEEP_MS, PERSIST_WAIT_MAX_RETRIES);
    while (retry.attempt()) {
        if (dir.getPersistenceState() == PersistenceState.PERSISTED) {
            // The directory is persisted
            return;
        }
        Optional<Scoped> persisting = mInodeLockManager.tryAcquirePersistingLock(dir.getId());
        if (!persisting.isPresent()) {
            // Someone else is doing this persist. Continue and wait for them to finish.
            continue;
        }
        try (Scoped s = persisting.get()) {
            if (dir.getPersistenceState() == PersistenceState.PERSISTED) {
                // The directory is persisted
                return;
            }
            mState.applyAndJournal(context, UpdateInodeEntry.newBuilder().setId(dir.getId()).setPersistenceState(PersistenceState.TO_BE_PERSISTED.name()).build());
            UpdateInodeEntry.Builder entry = UpdateInodeEntry.newBuilder().setId(dir.getId());
            syncPersistDirectory(dir).ifPresent(status -> {
                if (isRootId(dir.getId())) {
                    // Don't load the root dir metadata from UFS
                    return;
                }
                entry.setOwner(status.getOwner()).setGroup(status.getGroup()).setMode(status.getMode());
                Map<String, byte[]> xattr = status.getXAttr();
                if (xattr != null) {
                    entry.putAllXAttr(CommonUtils.convertToByteString(xattr));
                }
                Long lastModificationTime = status.getLastModifiedTime();
                if (lastModificationTime != null) {
                    entry.setLastModificationTimeMs(lastModificationTime).setOverwriteModificationTime(true);
                }
            });
            entry.setPersistenceState(PersistenceState.PERSISTED.name());
            mState.applyAndJournal(context, entry.build());
            return;
        }
    }
    throw new IOException(ExceptionMessage.FAILED_UFS_CREATE.getMessage(dir.getName()));
}
Also used : UpdateInodeEntry(alluxio.proto.journal.File.UpdateInodeEntry) ExponentialBackoffRetry(alluxio.retry.ExponentialBackoffRetry) Scoped(alluxio.util.interfaces.Scoped) IOException(java.io.IOException) RetryPolicy(alluxio.retry.RetryPolicy)

Example 2 with Scoped

use of alluxio.util.interfaces.Scoped in project alluxio by Alluxio.

the class InodeSyncStream method syncExistingInodeMetadata.

/**
 * Sync inode metadata with the UFS state.
 *
 * This method expects the {@code inodePath} to already exist in the inode tree.
 */
private void syncExistingInodeMetadata(LockedInodePath inodePath, boolean skipLoad) throws AccessControlException, BlockInfoException, FileAlreadyCompletedException, FileDoesNotExistException, InvalidFileSizeException, InvalidPathException, IOException, InterruptedException {
    if (inodePath.getLockPattern() != LockPattern.WRITE_EDGE && !mLoadOnly) {
        throw new RuntimeException(String.format("syncExistingInodeMetadata was called on d%s when only locked with %s. Load metadata" + " only was not specified.", inodePath.getUri(), inodePath.getLockPattern()));
    }
    // Set to true if the given inode was deleted.
    boolean deletedInode = false;
    // whether we need to load metadata for the current path
    boolean loadMetadata = mLoadOnly;
    LOG.trace("Syncing inode metadata {}", inodePath.getUri());
    // The requested path already exists in Alluxio.
    Inode inode = inodePath.getInode();
    // initialize sync children to true if it is a listStatus call on a directory
    boolean syncChildren = inode.isDirectory() && !mIsGetFileInfo && !mDescendantType.equals(DescendantType.NONE);
    if (inodePath.getLockPattern() == LockPattern.WRITE_EDGE && !mLoadOnly) {
        if (inode instanceof InodeFile && !inode.asFile().isCompleted()) {
            // Do not sync an incomplete file, since the UFS file is expected to not exist.
            return;
        }
        Optional<Scoped> persistingLock = mInodeLockManager.tryAcquirePersistingLock(inode.getId());
        if (!persistingLock.isPresent()) {
            // written.
            return;
        }
        persistingLock.get().close();
        UfsStatus cachedStatus = null;
        boolean fileNotFound = false;
        try {
            cachedStatus = mStatusCache.getStatus(inodePath.getUri());
        } catch (FileNotFoundException e) {
            fileNotFound = true;
        }
        MountTable.Resolution resolution = mMountTable.resolve(inodePath.getUri());
        AlluxioURI ufsUri = resolution.getUri();
        try (CloseableResource<UnderFileSystem> ufsResource = resolution.acquireUfsResource()) {
            UnderFileSystem ufs = ufsResource.get();
            String ufsFingerprint;
            Fingerprint ufsFpParsed;
            // When the status is not cached and it was not due to file not found, we retry
            if (fileNotFound) {
                ufsFingerprint = Constants.INVALID_UFS_FINGERPRINT;
                ufsFpParsed = Fingerprint.parse(ufsFingerprint);
            } else if (cachedStatus == null) {
                // TODO(david): change the interface so that getFingerprint returns a parsed fingerprint
                ufsFingerprint = (String) getFromUfs(() -> ufs.getFingerprint(ufsUri.toString()));
                ufsFpParsed = Fingerprint.parse(ufsFingerprint);
            } else {
                // When the status is cached
                Pair<AccessControlList, DefaultAccessControlList> aclPair = (Pair<AccessControlList, DefaultAccessControlList>) getFromUfs(() -> ufs.getAclPair(ufsUri.toString()));
                if (aclPair == null || aclPair.getFirst() == null || !aclPair.getFirst().hasExtended()) {
                    ufsFpParsed = Fingerprint.create(ufs.getUnderFSType(), cachedStatus);
                } else {
                    ufsFpParsed = Fingerprint.create(ufs.getUnderFSType(), cachedStatus, aclPair.getFirst());
                }
                ufsFingerprint = ufsFpParsed.serialize();
            }
            boolean containsMountPoint = mMountTable.containsMountPoint(inodePath.getUri(), true);
            UfsSyncUtils.SyncPlan syncPlan = UfsSyncUtils.computeSyncPlan(inode, ufsFpParsed, containsMountPoint);
            if (syncPlan.toUpdateMetaData()) {
                // It works by calling SetAttributeInternal on the inodePath.
                if (ufsFpParsed != null && ufsFpParsed.isValid()) {
                    short mode = Short.parseShort(ufsFpParsed.getTag(Fingerprint.Tag.MODE));
                    long opTimeMs = System.currentTimeMillis();
                    SetAttributePOptions.Builder builder = SetAttributePOptions.newBuilder().setMode(new Mode(mode).toProto());
                    String owner = ufsFpParsed.getTag(Fingerprint.Tag.OWNER);
                    if (!owner.equals(Fingerprint.UNDERSCORE)) {
                        // Only set owner if not empty
                        builder.setOwner(owner);
                    }
                    String group = ufsFpParsed.getTag(Fingerprint.Tag.GROUP);
                    if (!group.equals(Fingerprint.UNDERSCORE)) {
                        // Only set group if not empty
                        builder.setGroup(group);
                    }
                    SetAttributeContext ctx = SetAttributeContext.mergeFrom(builder).setUfsFingerprint(ufsFingerprint);
                    mFsMaster.setAttributeSingleFile(mRpcContext, inodePath, false, opTimeMs, ctx);
                }
            }
            if (syncPlan.toDelete()) {
                deletedInode = true;
                try {
                    // The options for deleting.
                    DeleteContext syncDeleteContext = DeleteContext.mergeFrom(DeletePOptions.newBuilder().setRecursive(true).setAlluxioOnly(true).setUnchecked(true));
                    mFsMaster.deleteInternal(mRpcContext, inodePath, syncDeleteContext);
                } catch (DirectoryNotEmptyException | IOException e) {
                    // Should not happen, since it is an unchecked delete.
                    LOG.error("Unexpected error for unchecked delete.", e);
                }
            }
            if (syncPlan.toLoadMetadata()) {
                loadMetadata = true;
            }
            syncChildren = syncPlan.toSyncChildren();
        }
    }
    // if DescendantType.ONE we only sync children if we are syncing root of this stream
    if (mDescendantType == DescendantType.ONE) {
        syncChildren = syncChildren && mRootScheme.getPath().equals(inodePath.getUri());
    }
    Map<String, Inode> inodeChildren = new HashMap<>();
    if (syncChildren) {
        // maps children name to inode
        mInodeStore.getChildren(inode.asDirectory()).forEach(child -> inodeChildren.put(child.getName(), child));
        // Fetch and populate children into the cache
        mStatusCache.prefetchChildren(inodePath.getUri(), mMountTable);
        Collection<UfsStatus> listStatus = mStatusCache.fetchChildrenIfAbsent(mRpcContext, inodePath.getUri(), mMountTable);
        // Iterate over UFS listings and process UFS children.
        if (listStatus != null) {
            for (UfsStatus ufsChildStatus : listStatus) {
                if (!inodeChildren.containsKey(ufsChildStatus.getName()) && !PathUtils.isTemporaryFileName(ufsChildStatus.getName())) {
                    // Ufs child exists, but Alluxio child does not. Must load metadata.
                    loadMetadata = true;
                    break;
                }
            }
        }
    }
    // locked path
    if (deletedInode) {
        inodePath.removeLastInode();
    }
    // load metadata if necessary.
    if (loadMetadata && !skipLoad) {
        loadMetadataForPath(inodePath);
    }
    if (syncChildren) {
        // Iterate over Alluxio children and process persisted children.
        mInodeStore.getChildren(inode.asDirectory()).forEach(childInode -> {
            // its children.
            if (mLoadOnly && inodeChildren.containsKey(childInode.getName()) && childInode.isFile()) {
                return;
            }
            // If we're performing a recursive sync, add each child of our current Inode to the queue
            AlluxioURI child = inodePath.getUri().joinUnsafe(childInode.getName());
            mPendingPaths.add(child);
            // This asynchronously schedules a job to pre-fetch the statuses into the cache.
            if (childInode.isDirectory() && mDescendantType == DescendantType.ALL) {
                mStatusCache.prefetchChildren(child, mMountTable);
            }
        });
    }
}
Also used : AccessControlList(alluxio.security.authorization.AccessControlList) DefaultAccessControlList(alluxio.security.authorization.DefaultAccessControlList) SetAttributeContext(alluxio.master.file.contexts.SetAttributeContext) DeleteContext(alluxio.master.file.contexts.DeleteContext) HashMap(java.util.HashMap) FileNotFoundException(java.io.FileNotFoundException) InodeFile(alluxio.master.file.meta.InodeFile) MutableInodeFile(alluxio.master.file.meta.MutableInodeFile) DirectoryNotEmptyException(alluxio.exception.DirectoryNotEmptyException) MountTable(alluxio.master.file.meta.MountTable) DefaultAccessControlList(alluxio.security.authorization.DefaultAccessControlList) UnderFileSystem(alluxio.underfs.UnderFileSystem) Pair(alluxio.collections.Pair) Fingerprint(alluxio.underfs.Fingerprint) UfsStatus(alluxio.underfs.UfsStatus) Mode(alluxio.security.authorization.Mode) IOException(java.io.IOException) UfsSyncUtils(alluxio.master.file.meta.UfsSyncUtils) Inode(alluxio.master.file.meta.Inode) SetAttributePOptions(alluxio.grpc.SetAttributePOptions) Scoped(alluxio.util.interfaces.Scoped) AlluxioURI(alluxio.AlluxioURI)

Example 3 with Scoped

use of alluxio.util.interfaces.Scoped in project alluxio by Alluxio.

the class AbstractPrimarySelectorTest method onStateChange.

@Test(timeout = TIMEOUT)
public void onStateChange() {
    AtomicInteger primaryCounter = new AtomicInteger(0);
    AtomicInteger standbyCounter = new AtomicInteger(0);
    Scoped listener = mSelector.onStateChange(state -> {
        if (state.equals(State.PRIMARY)) {
            primaryCounter.incrementAndGet();
        } else {
            standbyCounter.incrementAndGet();
        }
    });
    for (int i = 0; i < 10; i++) {
        mSelector.setState(State.PRIMARY);
        mSelector.setState(State.STANDBY);
    }
    assertEquals(10, primaryCounter.get());
    assertEquals(10, standbyCounter.get());
    listener.close();
    mSelector.setState(State.PRIMARY);
    mSelector.setState(State.STANDBY);
    assertEquals(10, primaryCounter.get());
    assertEquals(10, standbyCounter.get());
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Scoped(alluxio.util.interfaces.Scoped) Test(org.junit.Test)

Example 4 with Scoped

use of alluxio.util.interfaces.Scoped in project alluxio by Alluxio.

the class FaultTolerantAlluxioMasterProcess method gainPrimacy.

/**
 * Upgrades the master to primary mode.
 *
 * If the master loses primacy during the journal upgrade, this method will clean up the partial
 * upgrade, leaving the master in standby mode.
 *
 * @return whether the master successfully upgraded to primary
 */
private boolean gainPrimacy() throws Exception {
    LOG.info("Becoming a leader.");
    // Don't upgrade if this master's primacy is unstable.
    AtomicBoolean unstable = new AtomicBoolean(false);
    try (Scoped scoped = mLeaderSelector.onStateChange(state -> unstable.set(true))) {
        if (mLeaderSelector.getState() != State.PRIMARY) {
            LOG.info("Lost leadership while becoming a leader.");
            unstable.set(true);
        }
        stopMasters();
        LOG.info("Standby stopped");
        try (Timer.Context ctx = MetricsSystem.timer(MetricKey.MASTER_JOURNAL_GAIN_PRIMACY_TIMER.getName()).time()) {
            mJournalSystem.gainPrimacy();
        }
        // We only check unstable here because mJournalSystem.gainPrimacy() is the only slow method
        if (unstable.get()) {
            LOG.info("Terminating an unstable attempt to become a leader.");
            if (ServerConfiguration.getBoolean(PropertyKey.MASTER_JOURNAL_EXIT_ON_DEMOTION)) {
                stop();
            } else {
                losePrimacy();
            }
            return false;
        }
    }
    try {
        startMasters(true);
    } catch (UnavailableException e) {
        LOG.warn("Error starting masters: {}", e.toString());
        stopMasters();
        return false;
    }
    mServingThread = new Thread(() -> {
        try {
            startCommonServices();
            startLeaderServing(" (gained leadership)", " (lost leadership)");
        } catch (Throwable t) {
            Throwable root = Throwables.getRootCause(t);
            if ((root != null && (root instanceof InterruptedException)) || Thread.interrupted()) {
                return;
            }
            ProcessUtils.fatalError(LOG, t, "Exception thrown in main serving thread");
        }
    }, "MasterServingThread");
    LOG.info("Starting a server thread.");
    mServingThread.start();
    if (!waitForReady(10 * Constants.MINUTE_MS)) {
        ThreadUtils.logAllThreads();
        throw new RuntimeException("Alluxio master failed to come up");
    }
    LOG.info("Primary started");
    return true;
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Timer(com.codahale.metrics.Timer) UnavailableException(alluxio.exception.status.UnavailableException) Scoped(alluxio.util.interfaces.Scoped)

Aggregations

Scoped (alluxio.util.interfaces.Scoped)4 IOException (java.io.IOException)2 AlluxioURI (alluxio.AlluxioURI)1 Pair (alluxio.collections.Pair)1 DirectoryNotEmptyException (alluxio.exception.DirectoryNotEmptyException)1 UnavailableException (alluxio.exception.status.UnavailableException)1 SetAttributePOptions (alluxio.grpc.SetAttributePOptions)1 DeleteContext (alluxio.master.file.contexts.DeleteContext)1 SetAttributeContext (alluxio.master.file.contexts.SetAttributeContext)1 Inode (alluxio.master.file.meta.Inode)1 InodeFile (alluxio.master.file.meta.InodeFile)1 MountTable (alluxio.master.file.meta.MountTable)1 MutableInodeFile (alluxio.master.file.meta.MutableInodeFile)1 UfsSyncUtils (alluxio.master.file.meta.UfsSyncUtils)1 UpdateInodeEntry (alluxio.proto.journal.File.UpdateInodeEntry)1 ExponentialBackoffRetry (alluxio.retry.ExponentialBackoffRetry)1 RetryPolicy (alluxio.retry.RetryPolicy)1 AccessControlList (alluxio.security.authorization.AccessControlList)1 DefaultAccessControlList (alluxio.security.authorization.DefaultAccessControlList)1 Mode (alluxio.security.authorization.Mode)1