package org.apache.hadoop.raid; import java.util.LinkedList; import java.util.List; import org.apache.hadoop.hdfs.protocol.LocatedBlockWithMetaInfo; /** * Collection of blocks in a stripe with their locations, and information * about how to reconstructed lost blocks (if any) in this stripe. <br> * <br> * Data blocks and parity blocks are sequentially numbered from 0 to * (stripeLen+parityLen+1) consecutively, with data blocks in the first part * * @author star * */ public class Stripe { final private int stripeLen; // data blocks number in a code stripe private int dataSize; // data blocks number present, // note that a stripe doesn't need to be full final private int parityLen; // data blocks number in a code stripe private int paritySize; // parity blocks number in a code stripe private List<Integer> toReconstructList; // indexes of blocks need to be reconstruct private List<Integer> notToReadList; // indexes of blocks // that should not be read when reconstructing private LocatedBlockWithMetaInfo[] blocks; // blocks present in the stripe, // data blocks is put in the first part public Stripe(int stripeLen, int parityLen) { super(); this.stripeLen = stripeLen; this.parityLen = parityLen; this.dataSize = 0; this.paritySize = 0; this.toReconstructList = null; this.notToReadList = null; this.blocks = new LocatedBlockWithMetaInfo[this.stripeLen + this.parityLen]; } /** * Add block that need to be reconstruct * @param index * the index of block needed to be reconstructed * @return */ final public boolean addToReconstructe(int index) { if(toReconstructList != null && toReconstructList.size() >= (stripeLen+parityLen)) return false; if(toReconstructList == null) toReconstructList = new LinkedList<Integer>(); if(toReconstructList.contains(index)) { return true; } else { return toReconstructList.add(index); } } /** * Add block that should not to be read when reconstructing * @param index * the index of block that should not to be read * @return */ final public boolean addNotToRead(int index) { if(notToReadList != null && notToReadList.size() >= (stripeLen+parityLen)) return false; if(notToReadList == null) notToReadList = new LinkedList<Integer>(); if(notToReadList.contains(index)) { return true; } else { return notToReadList.add(index); } } /** * Add data block into stripe. * * @param block * the block to add * @return * true is returned if operation succeed, * otherwise false is returned */ final public boolean addDataBlock(LocatedBlockWithMetaInfo block) { if(dataSize >= stripeLen) return false; blocks[dataSize] = block; dataSize++; return true; } /** * Get a data block. * The data blocks are numbered from 0 to [dataSize-1] * @param index * the number of data block, which should be less than dataSize * @return * the block(when succeed) or null(when index out of bound) */ final public LocatedBlockWithMetaInfo getDataBlock(int index) { if(index < dataSize) return blocks[index]; return null; } /** * Add parity block into stripe. * * @param block * the block to add * @return * true is returned if operation succeed, * otherwise false is returned */ final public boolean addParityBlock(LocatedBlockWithMetaInfo block) { if(paritySize >= parityLen) return false; blocks[paritySize + stripeLen] = block; paritySize++; return true; } /** * Get a parity block. * The parity blocks are numbered from 0 to [paritySize-1] * @param index * the number of parity block, which should be less than paritySize * @return * the block(when succeed) or null(when index out of bound) */ final public LocatedBlockWithMetaInfo getParityBlock(int index) { if(index < paritySize) return blocks[stripeLen + index]; return null; } /** * Does there exists block(s) present need to be reconstructed * * @return */ final public boolean hasErasures() { if(toReconstructList != null && toReconstructList.size() > 0) return true; else return false; } /** * Return the indexes of blocks that need to be reconstructed */ public int[] getErasures() { if(hasErasures()) { int erasureNumber = toReconstructList.size(); int[] erasures = new int[erasureNumber]; Integer[] elements = toReconstructList.toArray(new Integer[0]); for(int i = 0; i < erasureNumber; i++) erasures[i] = elements[i].intValue(); return erasures; } return new int[0]; } /** * Return the indexes of blocks that should not to be read when reconstructing * * @return */ public int[] getNotToRead() { if(notToReadList != null && notToReadList.size() > 0) { int notToReadNumber = notToReadList.size(); int[] notToRead = new int[notToReadNumber]; Integer[] elements = notToReadList.toArray(new Integer[0]); for(int i = 0; i < notToReadNumber; i++) notToRead[i] = elements[i].intValue(); return notToRead; } return new int[0]; } final public int getStripeLen() { return stripeLen; } final public int getParityLen() { return parityLen; } final public int getDataSize() { return dataSize; } final public int getParitySize() { return paritySize; } final public LocatedBlockWithMetaInfo[] getBlocks() { return blocks; } }