001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hdfs.server.namenode.snapshot; 019 020import java.io.DataOutput; 021import java.io.IOException; 022import java.util.Arrays; 023import java.util.List; 024 025import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoContiguous; 026import org.apache.hadoop.hdfs.server.blockmanagement.BlockStoragePolicySuite; 027import org.apache.hadoop.hdfs.server.namenode.FSImageSerialization; 028import org.apache.hadoop.hdfs.server.namenode.INode; 029import org.apache.hadoop.hdfs.server.namenode.INode.BlocksMapUpdateInfo; 030import org.apache.hadoop.hdfs.server.namenode.INodeFile; 031import org.apache.hadoop.hdfs.server.namenode.INodeFileAttributes; 032import org.apache.hadoop.hdfs.server.namenode.QuotaCounts; 033import org.apache.hadoop.hdfs.server.namenode.snapshot.SnapshotFSImageFormat.ReferenceMap; 034 035/** 036 * The difference of an {@link INodeFile} between two snapshots. 037 */ 038public class FileDiff extends 039 AbstractINodeDiff<INodeFile, INodeFileAttributes, FileDiff> { 040 041 /** The file size at snapshot creation time. */ 042 private final long fileSize; 043 /** A copy of the INodeFile block list. Used in truncate. */ 044 private BlockInfoContiguous[] blocks; 045 046 FileDiff(int snapshotId, INodeFile file) { 047 super(snapshotId, null, null); 048 fileSize = file.computeFileSize(); 049 blocks = null; 050 } 051 052 /** Constructor used by FSImage loading */ 053 FileDiff(int snapshotId, INodeFileAttributes snapshotINode, 054 FileDiff posteriorDiff, long fileSize) { 055 super(snapshotId, snapshotINode, posteriorDiff); 056 this.fileSize = fileSize; 057 blocks = null; 058 } 059 060 /** @return the file size in the snapshot. */ 061 public long getFileSize() { 062 return fileSize; 063 } 064 065 /** 066 * Copy block references into the snapshot 067 * up to the current {@link #fileSize}. 068 * Should be done only once. 069 */ 070 public void setBlocks(BlockInfoContiguous[] blocks) { 071 if(this.blocks != null) 072 return; 073 int numBlocks = 0; 074 for(long s = 0; numBlocks < blocks.length && s < fileSize; numBlocks++) 075 s += blocks[numBlocks].getNumBytes(); 076 this.blocks = Arrays.copyOf(blocks, numBlocks); 077 } 078 079 public BlockInfoContiguous[] getBlocks() { 080 return blocks; 081 } 082 083 @Override 084 QuotaCounts combinePosteriorAndCollectBlocks( 085 BlockStoragePolicySuite bsps, INodeFile currentINode, 086 FileDiff posterior, BlocksMapUpdateInfo collectedBlocks, 087 final List<INode> removedINodes) { 088 FileWithSnapshotFeature sf = currentINode.getFileWithSnapshotFeature(); 089 assert sf != null : "FileWithSnapshotFeature is null"; 090 return sf.updateQuotaAndCollectBlocks( 091 bsps, currentINode, posterior, collectedBlocks, removedINodes); 092 } 093 094 @Override 095 public String toString() { 096 return super.toString() + " fileSize=" + fileSize + ", rep=" 097 + (snapshotINode == null? "?": snapshotINode.getFileReplication()); 098 } 099 100 @Override 101 void write(DataOutput out, ReferenceMap referenceMap) throws IOException { 102 writeSnapshot(out); 103 out.writeLong(fileSize); 104 105 // write snapshotINode 106 if (snapshotINode != null) { 107 out.writeBoolean(true); 108 FSImageSerialization.writeINodeFileAttributes(snapshotINode, out); 109 } else { 110 out.writeBoolean(false); 111 } 112 } 113 114 @Override 115 QuotaCounts destroyDiffAndCollectBlocks(BlockStoragePolicySuite bsps, INodeFile currentINode, 116 BlocksMapUpdateInfo collectedBlocks, final List<INode> removedINodes) { 117 return currentINode.getFileWithSnapshotFeature() 118 .updateQuotaAndCollectBlocks(bsps, currentINode, this, collectedBlocks, 119 removedINodes); 120 } 121 122 public void destroyAndCollectSnapshotBlocks( 123 BlocksMapUpdateInfo collectedBlocks) { 124 if(blocks == null || collectedBlocks == null) 125 return; 126 for(BlockInfoContiguous blk : blocks) 127 collectedBlocks.addDeleteBlock(blk); 128 blocks = null; 129 } 130}