[HDFS] 파일 을 휴지통 에 넣 기 - rename 작업
전편 에 서 는 휴지통 이 구체 적 으로 어떻게 일 하 는 지 언급 하지 않 았 으 니 이어서 보 세 요.
if(!skipTrash) {
try {
Trash trashTmp = new Trash(srcFs, getConf());
if (trashTmp.moveToTrash(src)) {//new trash,
System.out.println("Moved to trash: " + src);
return;
}
} catch (IOException e) {
Exception cause = (Exception) e.getCause();
String msg = "";
if(cause != null) {
msg = cause.getLocalizedMessage();
}
System.err.println("Problem with Trash." + msg +". Consider using -skipTrash option");
throw e;
}
}
파일 을 삭제 할 때 보통 Trash 를 거 칩 니 다. FsShell 의 코드 를 보면 new Trash 대상 이 고 삭제 할 파일 경 로 를 전달 하 는 것 이 간단 합 니 다.들 어가 서 휴지통 이 뭔 지 볼 까요?
private final FileSystem fs;
private final Path trash;//private static final Path TRASH = new Path(".Trash/");
private final Path current;
private final long interval;
public Trash(FileSystem fs, Configuration conf) throws IOException {
super(conf);
this.fs = fs;
this.trash = new Path(fs.getHomeDirectory(), TRASH);
this.current = new Path(trash, CURRENT);//private static final Path CURRENT = new Path("Current");
this.interval = conf.getLong("fs.trash.interval", 60) * MSECS_PER_MINUTE;// trash 1 , , Trash, 2 。
}
휴지통 대상 이 초기 화 될 때 hdfs 파일 시스템 핸들 을 전달 하 는 것 을 볼 수 있 습 니 다. 그 안에 Path 대상 이 trash 라 고 합 니 다. 이 Path 는 사용자 의 집 디 렉 터 리 를 가리 키 는 'Trash 디 렉 터 리' 입 니 다.집 목록 이 무엇 인지 한 번 보면 알 수 있다.
public Path getHomeDirectory() {
return new Path("/user/"+System.getProperty("user.name"))
.makeQualified(this);
}
홈 디 렉 터 리 는 hdfs 상 / user / 사용자 이름 이 디 렉 터 리 를 말 합 니 다. 사용자 이름 은 클 라 이언 트 가 사용 하 는 사용자 이름 입 니 다.
Kerbose 통일 인증 은 여기 서 안 할 게 요.아무튼 집 디 렉 터 리 가 어디 인지 알 면 됩 니 다. Liux 와 같은 / home / username / 디 렉 터 리 입 니 다.
movetoTrash 방법의 세 션 을 다시 봅 니 다:
Path trashPath = makeTrashRelativePath(current, path);
Path baseTrashPath = makeTrashRelativePath(current, path.getParent());
무슨 뜻 이에 요?private Path makeTrashRelativePath(Path basePath, Path rmFilePath) {
return new Path(basePath + rmFilePath.toUri().getPath());
}
무슨 뜻 이에 요?예 를 들 어 제 가 파일 을 만 들 었 습 니 다: / hadop dfs - touchz / hello / World / o / ca / 123원래
/ hello / World / wo / ca / 123 이 잖 아 요. 지금 rm 을 떨 어 뜨리 면 이 파일 / user / username /. Trash / current / hello / World / wo / ca / 123 을 발견 할 수 있어 요.
즉, / user / username /. Trash / current / 새로운 쓰레기 뿌리 입 니 다.
그 다음 에 rename 작업 을 수행 하면 원래 파일 rename 을 앞쪽 에 / user / username /. Trash / current 접 두 사 를 붙 이 는 것 입 니 다.그 러 니까 휴지통 에서 지 우 는 게 파일 이름 바 꾸 는 거 야.
rename 에 대해 서 는 한 걸음 한 걸음 추적 하지 않 고 namenode 에 들 어가 보 세 요.
private synchronized boolean renameToInternal(String src, String dst
) throws IOException {
NameNode.stateChangeLog.debug("DIR* NameSystem.renameTo: " + src + " to " + dst);
if (isInSafeMode())
throw new SafeModeException("Cannot rename " + src, safeMode);
if (!DFSUtil.isValidName(dst)) {
throw new IOException("Invalid name: " + dst);
}// !
if (isPermissionEnabled) {
//We should not be doing this. This is move() not renameTo().
//but for now,
String actualdst = dir.isDir(dst)?// , , , :/a/b/c /1/2/, /1/2/a/b/c
dst + Path.SEPARATOR + new Path(src).getName(): dst;
checkParentAccess(src, FsAction.WRITE);
checkAncestorAccess(actualdst, FsAction.WRITE);// inode , renameTo
}
HdfsFileStatus dinfo = dir.getFileInfo(dst);
if (dir.renameTo(src, dst)) {
changeLease(src, dst, dinfo); // update lease with new filename
return true;
}
return false;
}
dir FSDirectory , renameTo , log ,
boolean unprotectedRenameTo(String src, String dst, long timestamp)
throws QuotaExceededException {
synchronized (rootDir) {
INode[] srcInodes = rootDir.getExistingPathINodes(src);// inode
//http://blog.csdn.net/tracymkgld/article/details/17553173
// check the validation of the source
if (srcInodes[srcInodes.length-1] == null) {// inode, inode
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
+ "failed to rename " + src + " to " + dst
+ " because source does not exist");
return false;
}
if (srcInodes.length == 1) {
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
+"failed to rename "+src+" to "+dst+ " because source is the root");
return false;//root
}
if (isDir(dst)) {
dst += Path.SEPARATOR + new Path(src).getName();
}
//
// check the validity of the destination
if (dst.equals(src)) {
return true;
}// , ?
// dst cannot be directory or a file under src
if (dst.startsWith(src) && //
dst.charAt(src.length()) == Path.SEPARATOR_CHAR) {
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
+ "failed to rename " + src + " to " + dst
+ " because destination starts with src");
return false;
}
byte[][] dstComponents = INode.getPathComponents(dst);
INode[] dstInodes = new INode[dstComponents.length];
rootDir.getExistingPathINodes(dstComponents, dstInodes);
if (dstInodes[dstInodes.length-1] != null) {// , , src inode dst inode
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
+"failed to rename "+src+" to "+dst+
" because destination exists");
return false;
}
if (dstInodes[dstInodes.length-2] == null) {
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
+"failed to rename "+src+" to "+dst+
" because destination's parent does not exist");
return false;
}
// Ensure dst has quota to accommodate rename
verifyQuotaForRename(srcInodes,dstInodes);//quota , 。
INode dstChild = null;
INode srcChild = null;
String srcChildName = null;
try {
// remove src
srcChild = removeChild(srcInodes, srcInodes.length-1);// ,
if (srcChild == null) {
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
+ "failed to rename " + src + " to " + dst
+ " because the source can not be removed");
return false;
}
srcChildName = srcChild.getLocalName();
srcChild.setLocalName(dstComponents[dstInodes.length-1]);
// add src to the destination
dstChild = addChildNoQuotaCheck(dstInodes, dstInodes.length - 1,
srcChild, -1, false);// dst inode ,add dst Inode children (List) , quota ,mtime 。
if (dstChild != null) {
srcChild = null;
if (NameNode.stateChangeLog.isDebugEnabled()) {
NameNode.stateChangeLog.debug("DIR* FSDirectory.unprotectedRenameTo: " + src
+ " is renamed to " + dst);
}
// update modification time of dst and the parent of src
srcInodes[srcInodes.length-2].setModificationTime(timestamp);// mtime
dstInodes[dstInodes.length-2].setModificationTime(timestamp);
return true;
}
} finally {
if (dstChild == null && srcChild != null) {
// put it back
srcChild.setLocalName(srcChildName);
addChildNoQuotaCheck(srcInodes, srcInodes.length - 1, srcChild, -1,
false);
}
}
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
+"failed to rename "+src+" to "+dst);
return false;
}
소결:파일 을 삭제 할 때 파일 을 trash 에 넣 으 면 rename 작업 을 수행 하고 / user / username /. Trash / Current / 디 렉 터 리 에 넣 은 다음 namenode 에서 원본 파일 을 namespace 작업 을 합 니 다.
1. 아버지 로부터 벗 어 나 아버지 inodeDirectory 의 children 목록 에서 지 웁 니 다.
2, add 목적 inodeDirectory 의 children 목록 에
3. 원본 디 렉 터 리 의 mtime 를 수정 하 는 동시에 원본 디 렉 터 리 의 quota 점용 을 줄 이 고 dst 의 quota 점용 을 증가 합 니 다.
trash 는 언제 실행 합 니까?http://blog.csdn.net/tracymkgld/article/details/17552189이 6 단계 삭제 작업 이나 trash 를 자동 으로 청소 하 는 방법 은 다음 과 같 습 니 다.http://blog.csdn.net/tracymkgld/article/details/17557655
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.