/**
* 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 org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hdfs.protocol.Block;
import org.apache.hadoop.hdfs.server.namenode.BlocksMap.BlockInfo;
import org.apache.hadoop.raid.RaidCodec;
/**
* Define Raid File Format
* In RS(10, 4), the 14n, 14n+1, ... 14n+3th blocks in the blocks array
* are parity blocks, the 14n+4,...,14n+13th blocks are data blocks.
* The last stripe could have partial data blocks
*/
public class INodeRaidStorage extends INodeStorage {
private final RaidCodec codec;
public static final Log LOG = LogFactory.getLog(INodeRaidStorage.class);
/**
* Raid Block Info records the index of the block in the blocks array
* for fast lookup
*/
static public class RaidBlockInfo extends BlockInfo {
private int index = -1;
public RaidBlockInfo(Block blk, int replication, int newIndex) {
super(blk, replication);
this.index = newIndex;
}
public RaidBlockInfo(int replication, int newIndex) {
super();
this.setReplication(replication);
this.index = newIndex;
}
public int getIndex() {
return this.index;
}
}
public INodeRaidStorage(BlockInfo[] blkList, RaidCodec newCodec)
throws IOException {
super(blkList);
if (newCodec == null) {
throw new IOException("codec shouldn't be null for raid storage");
}
this.codec = newCodec;
}
@Override
public StorageType getStorageType() {
return StorageType.RAID_STORAGE;
}
@Override
public BlockInfo[] getBlocks() {
return this.blocks;
}
// Return only the source blocks of the raided file
public BlockInfo[] getSourceBlocks() {
return codec.getSourceBlocks(blocks);
}
@Override
public Block getLastBlock() {
return codec.getLastBlock(blocks);
}
@Override
public long getFileSize() {
return codec.getFileSize(blocks);
}
@Override
public long diskspaceConsumed(INodeFile inode) {
return diskspaceConsumed(this.blocks, inode);
}
@Override
public long diskspaceConsumed(Block[] blocks, INodeFile inode) {
return codec.diskspaceConsumed(blocks, inode.isUnderConstruction(),
inode.getPreferredBlockSize(), inode.getReplication());
}
@Override
public void checkLastBlockId(long blockId) throws IOException {
notSupported("checkLastBlockId");
}
@Override
public void setLastBlock(BlockInfo newblock) throws IOException {
notSupported("setLastBlock");
}
@Override
public void appendBlocks(INodeFile [] inodes, int totalAddedBlocks
, INodeFile inode) throws IOException {
notSupported("appendBlocks");
}
@Override
public Block getPenultimateBlock() throws IOException {
return (Block)notSupported("getPenultimateBlock");
}
@Override
public void addBlock(BlockInfo newblock) throws IOException {
notSupported("addBlock");
}
@Override
public boolean isSourceBlock(BlockInfo block) {
int index = 0;
if (block instanceof RaidBlockInfo) {
RaidBlockInfo rbi = (RaidBlockInfo)block;
index = rbi.index;
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("block: " + block + " is not raid block info");
}
for (index = 0; index < blocks.length; index++) {
if (blocks[index].equals(block)) {
break;
}
}
if (index == blocks.length) {
return false;
}
}
return index % codec.numStripeBlocks >= codec.numParityBlocks;
}
@Override
public void removeBlock(Block oldblock) throws IOException {
notSupported("removeBlock");
}
@Override
public RaidBlockInfo getFirstBlockInStripe(Block block, int index) throws IOException{
for (int i = 0; i < blocks.length; i+= codec.numStripeBlocks) {
if (i + codec.numStripeBlocks > index ) {
// the first block must be a parity block
return new RaidBlockInfo(blocks[i], codec.parityReplication, i);
}
}
return null;
}
@Override
public INodeRaidStorage convertToRaidStorage(BlockInfo[] parityBlocks,
RaidCodec codec, int[] checksums, BlocksMap blocksMap, short replication,
INodeFile inode) throws IOException {
return (INodeRaidStorage)notSupported("convertToRaidStorage");
}
public RaidCodec getCodec() {
return codec;
}
}