/*
* Copyright (C) 2015 hops.io.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.hops.common;
import io.hops.exception.StorageException;
import io.hops.exception.TransactionContextException;
import org.apache.hadoop.hdfs.DFSUtil;
import org.apache.hadoop.hdfs.protocol.UnresolvedPathException;
import org.apache.hadoop.hdfs.server.namenode.INode;
import org.apache.hadoop.hdfs.server.namenode.INodeDirectory;
import org.apache.hadoop.hdfs.server.namenode.INodeSymlink;
import org.apache.hadoop.hdfs.server.namenode.NameNode;
import java.util.NoSuchElementException;
public class INodeResolver {
private final byte[][] components;
private final boolean resolveLink;
private final boolean transactional;
private INode currentInode;
private int count = 0;
private int depth = INodeDirectory.ROOT_DIR_DEPTH;
public INodeResolver(byte[][] components, INode baseINode,
boolean resolveLink, boolean transactional) {
this.components = components;
currentInode = baseINode;
this.resolveLink = resolveLink;
this.transactional = transactional;
}
public INodeResolver(byte[][] components, INode baseINode,
boolean resolveLink, boolean transactional, int initialCount) {
this(components, baseINode, resolveLink, transactional);
this.count = initialCount;
this.depth = INodeDirectory.ROOT_DIR_DEPTH + (initialCount);
}
public boolean hasNext() {
if (currentInode == null) {
return false;
}
if (currentInode.isFile()) {
return false;
}
return count + 1 < components.length;
}
public INode next() throws UnresolvedPathException, StorageException,
TransactionContextException {
boolean lastComp = (count == components.length - 1);
if (currentInode.isSymlink() && (!lastComp || (lastComp && resolveLink))) {
final String symPath =
INodeUtil.constructPath(components, 0, components.length);
final String preceding = INodeUtil.constructPath(components, 0, count);
final String remainder =
INodeUtil.constructPath(components, count + 1, components.length);
final String link = DFSUtil.bytes2String(components[count]);
final String target = ((INodeSymlink) currentInode).getLinkValue();
if (NameNode.stateChangeLog.isDebugEnabled()) {
NameNode.stateChangeLog.debug(
"UnresolvedPathException " + " path: " + symPath + " preceding: " +
preceding + " count: " + count + " link: " + link +
" target: " + target + " remainder: " + remainder);
}
throw new UnresolvedPathException(symPath, preceding, remainder, target);
}
if (!hasNext()) {
throw new NoSuchElementException(
"Trying to read more components than available");
}
depth++;
count++;
int partitionId = INode.calculatePartitionId(currentInode.getId(), DFSUtil.bytes2String(components[count]), (short) depth);
currentInode = INodeUtil
.getNode(components[count], currentInode.getId(), partitionId, transactional);
return currentInode;
}
public int getCount() {
return count;
}
}