/*
* The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
* (the "License"). You may not use this work except in compliance with the License, which is
* available at www.apache.org/licenses/LICENSE-2.0
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied, as more fully set forth in the License.
*
* See the NOTICE file distributed with this work for information regarding copyright ownership.
*/
package alluxio.master.file.meta;
import alluxio.AlluxioURI;
import alluxio.exception.ExceptionMessage;
import alluxio.exception.FileDoesNotExistException;
import alluxio.exception.InvalidPathException;
import alluxio.util.io.PathUtils;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.concurrent.ThreadSafe;
/**
* This class represents a path of locked {@link Inode}, starting from the root.
*/
@ThreadSafe
public abstract class LockedInodePath implements AutoCloseable {
protected final AlluxioURI mUri;
protected final String[] mPathComponents;
protected final ArrayList<Inode<?>> mInodes;
protected final InodeLockList mLockList;
protected final InodeTree.LockMode mLockMode;
LockedInodePath(AlluxioURI uri, List<Inode<?>> inodes, InodeLockList lockList,
InodeTree.LockMode lockMode)
throws InvalidPathException {
Preconditions.checkArgument(!inodes.isEmpty());
mUri = uri;
mPathComponents = PathUtils.getPathComponents(mUri.getPath());
mInodes = new ArrayList<>(inodes);
mLockList = lockList;
mLockMode = lockMode;
}
LockedInodePath(LockedInodePath inodePath) {
Preconditions.checkArgument(!inodePath.mInodes.isEmpty());
mUri = inodePath.mUri;
mPathComponents = inodePath.mPathComponents;
mInodes = inodePath.mInodes;
mLockList = inodePath.mLockList;
mLockMode = inodePath.mLockMode;
}
/**
* @return the full uri of the path
*/
public synchronized AlluxioURI getUri() {
return mUri;
}
/**
* @return the target inode
* @throws FileDoesNotExistException if the target inode does not exist
*/
public synchronized Inode<?> getInode() throws FileDoesNotExistException {
if (!fullPathExists()) {
throw new FileDoesNotExistException(ExceptionMessage.PATH_DOES_NOT_EXIST.getMessage(mUri));
}
return mInodes.get(mInodes.size() - 1);
}
/**
* @return the target inode as an {@link InodeFile}
* @throws FileDoesNotExistException if the target inode does not exist, or it is not a file
*/
public synchronized InodeFile getInodeFile() throws FileDoesNotExistException {
Inode<?> inode = getInode();
if (!inode.isFile()) {
throw new FileDoesNotExistException(ExceptionMessage.PATH_MUST_BE_FILE.getMessage(mUri));
}
return (InodeFile) inode;
}
/**
* @return the parent of the target inode
* @throws InvalidPathException if the parent inode is not a directory
* @throws FileDoesNotExistException if the parent of the target does not exist
*/
public synchronized InodeDirectory getParentInodeDirectory()
throws InvalidPathException, FileDoesNotExistException {
if (mPathComponents.length < 2 || mInodes.size() < (mPathComponents.length - 1)) {
// The path is only the root, or the list of inodes is not long enough to contain the parent
throw new FileDoesNotExistException(
ExceptionMessage.PATH_DOES_NOT_EXIST.getMessage(mUri.getParent()));
}
Inode<?> inode = mInodes.get(mPathComponents.length - 2);
if (!inode.isDirectory()) {
throw new InvalidPathException(ExceptionMessage.PATH_MUST_HAVE_VALID_PARENT.getMessage(mUri));
}
return (InodeDirectory) inode;
}
/**
* @return a copy of the list of existing inodes, from the root
*/
public synchronized List<Inode<?>> getInodeList() {
return Lists.newArrayList(mInodes);
}
/**
* @return true if the entire path of inodes exists, false otherwise
*/
public synchronized boolean fullPathExists() {
return mInodes.size() == mPathComponents.length;
}
/**
* @return the {@link InodeTree.LockMode} of this path
*/
public synchronized InodeTree.LockMode getLockMode() {
return mLockMode;
}
@Override
public synchronized void close() {
mLockList.close();
}
}