/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.hadoop.hdfs.server.namenode;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.fs.permission.PermissionStatus;
import org.apache.hadoop.hdfs.protocol.Block;
import org.apache.hadoop.hdfs.server.namenode.BlocksMap.BlockInfo;
import org.apache.hadoop.hdfs.server.namenode.FSImageFormat.FSImageLoadingContext;
public class INodeHardLinkFile extends INodeFile{
private final HardLinkFileInfo hardLinkFileInfo;
protected INodeHardLinkFile(INodeFile inodeFile, long hardLinkID) throws IOException {
super(inodeFile);
hardLinkFileInfo = new HardLinkFileInfo(hardLinkID);
}
protected INodeHardLinkFile(INodeHardLinkFile inodeHardLinkFile) {
super(inodeHardLinkFile);
this.hardLinkFileInfo = inodeHardLinkFile.getHardLinkFileInfo();
}
protected INodeHardLinkFile(long id, PermissionStatus permissions, BlockInfo[] blocks,
short replication, long modificationTime,
long atime, long preferredBlockSize,
HardLinkFileInfo hardLinkFileInfo) {
super(id,
permissions,
blocks,
replication,
modificationTime,
atime,
preferredBlockSize,
null);
this.hardLinkFileInfo = hardLinkFileInfo;
}
public HardLinkFileInfo getHardLinkFileInfo() {
return hardLinkFileInfo;
}
public void incReferenceCnt() {
this.hardLinkFileInfo.addLinkedFile(this);
}
public int getReferenceCnt() {
return this.hardLinkFileInfo.getReferenceCnt();
}
public long getHardLinkID() {
return this.hardLinkFileInfo.getHardLinkID();
}
@Override
public boolean isHardlinkFile() {
return true;
}
@Override
int collectSubtreeBlocksAndClear(List<BlockInfo> v,
int blocksLimit,
List<INode> removedINodes) {
parent = null;
this.hardLinkFileInfo.removeLinkedFile(this);
name = null;
removedINodes.add(this);
return 1;
}
public Set<INode> getAncestorSet() {
return this.hardLinkFileInfo.getAncestorSet(null);
}
private Set<INode> getAncestorSetWithoutCurrentINode() {
return this.hardLinkFileInfo.getAncestorSet(this);
}
public int getStartPosForQuoteUpdate() {
int commonAncestorNum = 0;
INode current = this;
Set<INode> commonAncestorExclusiveSet = getAncestorSetWithoutCurrentINode();
while ((current = current.parent) != null) {
if (!commonAncestorExclusiveSet.contains(current)) {
commonAncestorNum ++;
}
}
return commonAncestorNum;
}
/**
* Set the PermissionSatus for all the linked files
* @param ps
*/
@Override
protected void setPermissionStatus(PermissionStatus ps) {
setPermissionStatus(ps, true);
}
protected void setPermissionStatus(PermissionStatus ps, boolean recursive) {
super.setPermissionStatus(ps);
if (this.hardLinkFileInfo != null && recursive) {
this.hardLinkFileInfo.setPermissionStatus(ps);
}
}
/**
* Set the user name for all the linked files
* @param user
*/
@Override
protected void setUser(String user) {
this.setUser(user, true);
}
protected void setUser(String user, boolean recursive) {
super.setUser(user);
if (this.hardLinkFileInfo != null && recursive) {
this.hardLinkFileInfo.setUser(user);
}
}
/**
* Set the group name for all the linked files
* @param group
*/
@Override
protected void setGroup(String group) {
this.setGroup(group, true);
}
protected void setGroup(String group, boolean recursive) {
super.setGroup(group);
if (this.hardLinkFileInfo != null && recursive) {
this.hardLinkFileInfo.setGroup(group);
}
}
/**
* Set the permission for all the linked files
* @param permission
*/
@Override
protected void setPermission(FsPermission permission) {
this.setPermission(permission, true);
}
protected void setPermission(FsPermission permission, boolean recursive) {
super.setPermission(permission);
if (this.hardLinkFileInfo != null && recursive) {
this.hardLinkFileInfo.setPermission(permission);
}
}
/**
* Set the modtime for all the linked files
* @param modtime
*/
@Override
protected void setModificationTime(long modtime) {
this.setModificationTime(modtime, true);
}
protected void setModificationTime(long modtime, boolean recursive) {
super.setModificationTimeForce(modtime);
if (this.hardLinkFileInfo != null && recursive) {
this.hardLinkFileInfo.setModificationTime(modtime);
}
}
/**
* Always set the last modification time of inode.
* @param modtime
*/
@Override
protected void setModificationTimeForce(long modtime) {
this.setModificationTimeForce(modtime, true);
}
protected void setModificationTimeForce(long modtime, boolean recursive) {
super.setModificationTimeForce(modtime);
if (this.hardLinkFileInfo != null && recursive) {
this.hardLinkFileInfo.setModificationTimeForce(modtime);
}
}
/**
* Set the atime for all the linked files
* @param modtime
*/
@Override
protected void setAccessTime(long atime) {
this.setAccessTime(atime, true);
}
protected void setAccessTime(long atime, boolean recursive) {
super.setAccessTime(atime);
if (this.hardLinkFileInfo != null && recursive) {
this.hardLinkFileInfo.setAccessTime(atime);
}
}
/**
* Set the replication factor for all the linked files
* @param replication
*/
@Override
public void setReplication(short replication) {
this.setReplication(replication, true);
}
protected void setReplication(short replication, boolean recursive) {
super.setReplication(replication);
if (this.hardLinkFileInfo != null && recursive) {
this.hardLinkFileInfo.setReplication(replication);
}
}
/**
* Create a HardLink file info if necessary and register to the hardLinkINodeIDToFileInfoMap
* And return the hardLinkFileInfo which is registered in the hardLinkINodeIDToFileInfoMap
*
* This function is not thread safe.
* @param inodeID
* @param context The context when loading the fsImage
* @return hardLinkFileInfo registered in the hardLinkINodeIDToFileInfoMap
*/
public static HardLinkFileInfo loadHardLinkFileInfo(long hardLinkID,
FSImageLoadingContext context) {
// update the latest hard link ID
context.getFSDirectory().resetLastHardLinkIDIfLarge(hardLinkID);
// create the hard link file info if necessary
HardLinkFileInfo fileInfo = context.getHardLinkFileInfo(hardLinkID);
if (fileInfo == null) {
fileInfo = new HardLinkFileInfo(hardLinkID);
context.associateHardLinkIDWithFileInfo(hardLinkID, fileInfo);
}
return fileInfo;
}
}