NamenodeFsck.java
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:26k
源码类别:

网格计算

开发平台:

Java

  1. /**
  2.  * Licensed to the Apache Software Foundation (ASF) under one
  3.  * or more contributor license agreements.  See the NOTICE file
  4.  * distributed with this work for additional information
  5.  * regarding copyright ownership.  The ASF licenses this file
  6.  * to you under the Apache License, Version 2.0 (the
  7.  * "License"); you may not use this file except in compliance
  8.  * with the License.  You may obtain a copy of the License at
  9.  *
  10.  *     http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing, software
  13.  * distributed under the License is distributed on an "AS IS" BASIS,
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.  * See the License for the specific language governing permissions and
  16.  * limitations under the License.
  17.  */
  18. package org.apache.hadoop.hdfs.server.namenode;
  19. import java.io.IOException;
  20. import java.io.OutputStream;
  21. import java.io.PrintWriter;
  22. import java.net.InetSocketAddress;
  23. import java.net.Socket;
  24. import java.util.ArrayList;
  25. import java.util.Iterator;
  26. import java.util.Map;
  27. import java.util.Random;
  28. import java.util.TreeSet;
  29. import javax.servlet.http.HttpServletResponse;
  30. import org.apache.commons.logging.Log;
  31. import org.apache.commons.logging.LogFactory;
  32. import org.apache.hadoop.conf.Configuration;
  33. import org.apache.hadoop.net.NetUtils;
  34. import org.apache.hadoop.net.NodeBase;
  35. import org.apache.hadoop.hdfs.DFSClient;
  36. import org.apache.hadoop.hdfs.protocol.Block;
  37. import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
  38. import org.apache.hadoop.hdfs.protocol.LocatedBlock;
  39. import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
  40. import org.apache.hadoop.hdfs.protocol.FSConstants.DatanodeReportType;
  41. import org.apache.hadoop.hdfs.server.common.HdfsConstants;
  42. import org.apache.hadoop.fs.FileStatus;
  43. import org.apache.hadoop.fs.permission.PermissionStatus;
  44. /**
  45.  * This class provides rudimentary checking of DFS volumes for errors and
  46.  * sub-optimal conditions.
  47.  * <p>The tool scans all files and directories, starting from an indicated
  48.  *  root path. The following abnormal conditions are detected and handled:</p>
  49.  * <ul>
  50.  * <li>files with blocks that are completely missing from all datanodes.<br/>
  51.  * In this case the tool can perform one of the following actions:
  52.  *  <ul>
  53.  *      <li>none ({@link #FIXING_NONE})</li>
  54.  *      <li>move corrupted files to /lost+found directory on DFS
  55.  *      ({@link #FIXING_MOVE}). Remaining data blocks are saved as a
  56.  *      block chains, representing longest consecutive series of valid blocks.</li>
  57.  *      <li>delete corrupted files ({@link #FIXING_DELETE})</li>
  58.  *  </ul>
  59.  *  </li>
  60.  *  <li>detect files with under-replicated or over-replicated blocks</li>
  61.  *  </ul>
  62.  *  Additionally, the tool collects a detailed overall DFS statistics, and
  63.  *  optionally can print detailed statistics on block locations and replication
  64.  *  factors of each file.
  65.  */
  66. public class NamenodeFsck {
  67.   public static final Log LOG = LogFactory.getLog(NameNode.class.getName());
  68.   
  69.   // return string marking fsck status
  70.   public static final String CORRUPT_STATUS = "is CORRUPT";
  71.   public static final String HEALTHY_STATUS = "is HEALTHY";
  72.   public static final String NONEXISTENT_STATUS = "does not exist";
  73.   public static final String FAILURE_STATUS = "FAILED";
  74.   
  75.   /** Don't attempt any fixing . */
  76.   public static final int FIXING_NONE = 0;
  77.   /** Move corrupted files to /lost+found . */
  78.   public static final int FIXING_MOVE = 1;
  79.   /** Delete corrupted files. */
  80.   public static final int FIXING_DELETE = 2;
  81.   
  82.   private NameNode nn;
  83.   private String lostFound = null;
  84.   private boolean lfInited = false;
  85.   private boolean lfInitedOk = false;
  86.   private boolean showFiles = false;
  87.   private boolean showOpenFiles = false;
  88.   private boolean showBlocks = false;
  89.   private boolean showLocations = false;
  90.   private boolean showRacks = false;
  91.   private int fixing = FIXING_NONE;
  92.   private String path = "/";
  93.   
  94.   private Configuration conf;
  95.   private PrintWriter out;
  96.   
  97.   /**
  98.    * Filesystem checker.
  99.    * @param conf configuration (namenode config)
  100.    * @param nn namenode that this fsck is going to use
  101.    * @param pmap key=value[] map that is passed to the http servlet as url parameters
  102.    * @param response the object into which  this servelet writes the url contents
  103.    * @throws IOException
  104.    */
  105.   public NamenodeFsck(Configuration conf,
  106.                       NameNode nn,
  107.                       Map<String,String[]> pmap,
  108.                       HttpServletResponse response) throws IOException {
  109.     this.conf = conf;
  110.     this.nn = nn;
  111.     this.out = response.getWriter();
  112.     for (Iterator<String> it = pmap.keySet().iterator(); it.hasNext();) {
  113.       String key = it.next();
  114.       if (key.equals("path")) { this.path = pmap.get("path")[0]; }
  115.       else if (key.equals("move")) { this.fixing = FIXING_MOVE; }
  116.       else if (key.equals("delete")) { this.fixing = FIXING_DELETE; }
  117.       else if (key.equals("files")) { this.showFiles = true; }
  118.       else if (key.equals("blocks")) { this.showBlocks = true; }
  119.       else if (key.equals("locations")) { this.showLocations = true; }
  120.       else if (key.equals("racks")) { this.showRacks = true; }
  121.       else if (key.equals("openforwrite")) {this.showOpenFiles = true; }
  122.     }
  123.   }
  124.   
  125.   /**
  126.    * Check files on DFS, starting from the indicated path.
  127.    * @throws Exception
  128.    */
  129.   public void fsck() throws IOException {
  130.     try {
  131.       FileStatus[] files = nn.namesystem.dir.getListing(path);
  132.       FsckResult res = new FsckResult();
  133.       res.totalRacks = nn.getNetworkTopology().getNumOfRacks();
  134.       res.totalDatanodes = nn.namesystem.getNumberOfDatanodes(
  135.           DatanodeReportType.LIVE);
  136.       res.setReplication((short) conf.getInt("dfs.replication", 3));
  137.       if (files != null) {
  138.         for (int i = 0; i < files.length; i++) {
  139.           check(files[i], res);
  140.         }
  141.         out.println(res);
  142.         // DFSck client scans for the string HEALTHY/CORRUPT to check the status
  143.         // of file system and return appropriate code. Changing the output string
  144.         // might break testcases. 
  145.         if (res.isHealthy()) {
  146.           out.print("nnThe filesystem under path '" + path + "' " + HEALTHY_STATUS);
  147.         }  else {
  148.           out.print("nnThe filesystem under path '" + path + "' " + CORRUPT_STATUS);
  149.         }
  150.       } else {
  151.         out.print("nnPath '" + path + "' " + NONEXISTENT_STATUS);
  152.       }
  153.     } catch (Exception e) {
  154.       String errMsg = "Fsck on path '" + path + "' " + FAILURE_STATUS;
  155.       LOG.warn(errMsg, e);
  156.       out.println(e.getMessage());
  157.       out.print("nn"+errMsg);
  158.     } finally {
  159.       out.close();
  160.     }
  161.   }
  162.   
  163.   private void check(FileStatus file, FsckResult res) throws IOException {
  164.     int minReplication = nn.namesystem.getMinReplication();
  165.     String path = file.getPath().toString();
  166.     boolean isOpen = false;
  167.     if (file.isDir()) {
  168.       FileStatus[] files = nn.namesystem.dir.getListing(path);
  169.       if (files == null) {
  170.         return;
  171.       }
  172.       if (showFiles) {
  173.         out.println(path + " <dir>");
  174.       }
  175.       res.totalDirs++;
  176.       for (int i = 0; i < files.length; i++) {
  177.         check(files[i], res);
  178.       }
  179.       return;
  180.     }
  181.     long fileLen = file.getLen();
  182.     LocatedBlocks blocks = nn.namesystem.getBlockLocations(path, 0, fileLen);
  183.     if (blocks == null) { // the file is deleted
  184.       return;
  185.     }
  186.     isOpen = blocks.isUnderConstruction();
  187.     if (isOpen && !showOpenFiles) {
  188.       // We collect these stats about open files to report with default options
  189.       res.totalOpenFilesSize += fileLen;
  190.       res.totalOpenFilesBlocks += blocks.locatedBlockCount();
  191.       res.totalOpenFiles++;
  192.       return;
  193.     }
  194.     res.totalFiles++;
  195.     res.totalSize += fileLen;
  196.     res.totalBlocks += blocks.locatedBlockCount();
  197.     if (showOpenFiles && isOpen) {
  198.       out.print(path + " " + fileLen + " bytes, " +
  199.         blocks.locatedBlockCount() + " block(s), OPENFORWRITE: ");
  200.     } else if (showFiles) {
  201.       out.print(path + " " + fileLen + " bytes, " +
  202.         blocks.locatedBlockCount() + " block(s): ");
  203.     } else {
  204.       out.print('.');
  205.     }
  206.     if (res.totalFiles % 100 == 0) { out.println(); out.flush(); }
  207.     int missing = 0;
  208.     int corrupt = 0;
  209.     long missize = 0;
  210.     int underReplicatedPerFile = 0;
  211.     int misReplicatedPerFile = 0;
  212.     StringBuffer report = new StringBuffer();
  213.     int i = 0;
  214.     for (LocatedBlock lBlk : blocks.getLocatedBlocks()) {
  215.       Block block = lBlk.getBlock();
  216.       boolean isCorrupt = lBlk.isCorrupt();
  217.       String blkName = block.toString();
  218.       DatanodeInfo[] locs = lBlk.getLocations();
  219.       res.totalReplicas += locs.length;
  220.       short targetFileReplication = file.getReplication();
  221.       if (locs.length > targetFileReplication) {
  222.         res.excessiveReplicas += (locs.length - targetFileReplication);
  223.         res.numOverReplicatedBlocks += 1;
  224.       }
  225.       // Check if block is Corrupt
  226.       if (isCorrupt) {
  227.         corrupt++;
  228.         res.corruptBlocks++;
  229.         out.print("n" + path + ": CORRUPT block " + block.getBlockName()+"n");
  230.       }
  231.       if (locs.length >= minReplication)
  232.         res.numMinReplicatedBlocks++;
  233.       if (locs.length < targetFileReplication && locs.length > 0) {
  234.         res.missingReplicas += (targetFileReplication - locs.length);
  235.         res.numUnderReplicatedBlocks += 1;
  236.         underReplicatedPerFile++;
  237.         if (!showFiles) {
  238.           out.print("n" + path + ": ");
  239.         }
  240.         out.println(" Under replicated " + block +
  241.                     ". Target Replicas is " +
  242.                     targetFileReplication + " but found " +
  243.                     locs.length + " replica(s).");
  244.       }
  245.       // verify block placement policy
  246.       int missingRacks = ReplicationTargetChooser.verifyBlockPlacement(
  247.                     lBlk, targetFileReplication, nn.getNetworkTopology());
  248.       if (missingRacks > 0) {
  249.         res.numMisReplicatedBlocks++;
  250.         misReplicatedPerFile++;
  251.         if (!showFiles) {
  252.           if(underReplicatedPerFile == 0)
  253.             out.println();
  254.           out.print(path + ": ");
  255.         }
  256.         out.println(" Replica placement policy is violated for " + 
  257.                     block +
  258.                     ". Block should be additionally replicated on " + 
  259.                     missingRacks + " more rack(s).");
  260.       }
  261.       report.append(i + ". " + blkName + " len=" + block.getNumBytes());
  262.       if (locs.length == 0) {
  263.         report.append(" MISSING!");
  264.         res.addMissing(block.toString(), block.getNumBytes());
  265.         missing++;
  266.         missize += block.getNumBytes();
  267.       } else {
  268.         report.append(" repl=" + locs.length);
  269.         if (showLocations || showRacks) {
  270.           StringBuffer sb = new StringBuffer("[");
  271.           for (int j = 0; j < locs.length; j++) {
  272.             if (j > 0) { sb.append(", "); }
  273.             if (showRacks)
  274.               sb.append(NodeBase.getPath(locs[j]));
  275.             else
  276.               sb.append(locs[j]);
  277.           }
  278.           sb.append(']');
  279.           report.append(" " + sb.toString());
  280.         }
  281.       }
  282.       report.append('n');
  283.       i++;
  284.     }
  285.     if ((missing > 0) || (corrupt > 0)) {
  286.       if (!showFiles && (missing > 0)) {
  287.         out.print("n" + path + ": MISSING " + missing
  288.             + " blocks of total size " + missize + " B.");
  289.       }
  290.       res.corruptFiles++;
  291.       switch(fixing) {
  292.       case FIXING_NONE:
  293.         break;
  294.       case FIXING_MOVE:
  295.         if (!isOpen)
  296.           lostFoundMove(file, blocks);
  297.         break;
  298.       case FIXING_DELETE:
  299.         if (!isOpen)
  300.           nn.namesystem.deleteInternal(path, false);
  301.       }
  302.     }
  303.     if (showFiles) {
  304.       if (missing > 0) {
  305.         out.print(" MISSING " + missing + " blocks of total size " + missize + " Bn");
  306.       }  else if (underReplicatedPerFile == 0 && misReplicatedPerFile == 0) {
  307.         out.print(" OKn");
  308.       }
  309.       if (showBlocks) {
  310.         out.print(report.toString() + "n");
  311.       }
  312.     }
  313.   }
  314.   
  315.   private void lostFoundMove(FileStatus file, LocatedBlocks blocks)
  316.     throws IOException {
  317.     DFSClient dfs = new DFSClient(conf);
  318.     try {
  319.     if (!lfInited) {
  320.       lostFoundInit(dfs);
  321.     }
  322.     if (!lfInitedOk) {
  323.       return;
  324.     }
  325.     String target = lostFound + file.getPath();
  326.     String errmsg = "Failed to move " + file.getPath() + " to /lost+found";
  327.     try {
  328.       PermissionStatus ps = new PermissionStatus(
  329.           file.getOwner(), file.getGroup(), file.getPermission()); 
  330.       if (!nn.namesystem.dir.mkdirs(target, ps, false, FSNamesystem.now())) {
  331.         LOG.warn(errmsg);
  332.         return;
  333.       }
  334.       // create chains
  335.       int chain = 0;
  336.       OutputStream fos = null;
  337.       for (LocatedBlock lBlk : blocks.getLocatedBlocks()) {
  338.         LocatedBlock lblock = lBlk;
  339.         DatanodeInfo[] locs = lblock.getLocations();
  340.         if (locs == null || locs.length == 0) {
  341.           if (fos != null) {
  342.             fos.flush();
  343.             fos.close();
  344.             fos = null;
  345.           }
  346.           continue;
  347.         }
  348.         if (fos == null) {
  349.           fos = dfs.create(target + "/" + chain, true);
  350.           if (fos != null) chain++;
  351.           else {
  352.             LOG.warn(errmsg + ": could not store chain " + chain);
  353.             // perhaps we should bail out here...
  354.             // return;
  355.             continue;
  356.           }
  357.         }
  358.         
  359.         // copy the block. It's a pity it's not abstracted from DFSInputStream ...
  360.         try {
  361.           copyBlock(dfs, lblock, fos);
  362.         } catch (Exception e) {
  363.           e.printStackTrace();
  364.           // something went wrong copying this block...
  365.           LOG.warn(" - could not copy block " + lblock.getBlock() + " to " + target);
  366.           fos.flush();
  367.           fos.close();
  368.           fos = null;
  369.         }
  370.       }
  371.       if (fos != null) fos.close();
  372.       LOG.warn("n - moved corrupted file " + file.getPath() + " to /lost+found");
  373.       dfs.delete(file.getPath().toString(), true);
  374.     }  catch (Exception e) {
  375.       e.printStackTrace();
  376.       LOG.warn(errmsg + ": " + e.getMessage());
  377.     }
  378.     } finally {
  379.       dfs.close();
  380.     }
  381.   }
  382.       
  383.   /*
  384.    * XXX (ab) Bulk of this method is copied verbatim from {@link DFSClient}, which is
  385.    * bad. Both places should be refactored to provide a method to copy blocks
  386.    * around.
  387.    */
  388.   private void copyBlock(DFSClient dfs, LocatedBlock lblock,
  389.                          OutputStream fos) throws Exception {
  390.     int failures = 0;
  391.     InetSocketAddress targetAddr = null;
  392.     TreeSet<DatanodeInfo> deadNodes = new TreeSet<DatanodeInfo>();
  393.     Socket s = null;
  394.     DFSClient.BlockReader blockReader = null; 
  395.     Block block = lblock.getBlock(); 
  396.     while (s == null) {
  397.       DatanodeInfo chosenNode;
  398.       
  399.       try {
  400.         chosenNode = bestNode(dfs, lblock.getLocations(), deadNodes);
  401.         targetAddr = NetUtils.createSocketAddr(chosenNode.getName());
  402.       }  catch (IOException ie) {
  403.         if (failures >= DFSClient.MAX_BLOCK_ACQUIRE_FAILURES) {
  404.           throw new IOException("Could not obtain block " + lblock);
  405.         }
  406.         LOG.info("Could not obtain block from any node:  " + ie);
  407.         try {
  408.           Thread.sleep(10000);
  409.         }  catch (InterruptedException iex) {
  410.         }
  411.         deadNodes.clear();
  412.         failures++;
  413.         continue;
  414.       }
  415.       try {
  416.         s = new Socket();
  417.         s.connect(targetAddr, HdfsConstants.READ_TIMEOUT);
  418.         s.setSoTimeout(HdfsConstants.READ_TIMEOUT);
  419.         
  420.         blockReader = 
  421.           DFSClient.BlockReader.newBlockReader(s, targetAddr.toString() + ":" + 
  422.                                                block.getBlockId(), 
  423.                                                block.getBlockId(), 
  424.                                                block.getGenerationStamp(), 
  425.                                                0, -1,
  426.                                                conf.getInt("io.file.buffer.size", 4096));
  427.         
  428.       }  catch (IOException ex) {
  429.         // Put chosen node into dead list, continue
  430.         LOG.info("Failed to connect to " + targetAddr + ":" + ex);
  431.         deadNodes.add(chosenNode);
  432.         if (s != null) {
  433.           try {
  434.             s.close();
  435.           } catch (IOException iex) {
  436.           }
  437.         }
  438.         s = null;
  439.       }
  440.     }
  441.     if (blockReader == null) {
  442.       throw new Exception("Could not open data stream for " + lblock.getBlock());
  443.     }
  444.     byte[] buf = new byte[1024];
  445.     int cnt = 0;
  446.     boolean success = true;
  447.     long bytesRead = 0;
  448.     try {
  449.       while ((cnt = blockReader.read(buf, 0, buf.length)) > 0) {
  450.         fos.write(buf, 0, cnt);
  451.         bytesRead += cnt;
  452.       }
  453.       if ( bytesRead != block.getNumBytes() ) {
  454.         throw new IOException("Recorded block size is " + block.getNumBytes() + 
  455.                               ", but datanode returned " +bytesRead+" bytes");
  456.       }
  457.     } catch (Exception e) {
  458.       e.printStackTrace();
  459.       success = false;
  460.     } finally {
  461.       try {s.close(); } catch (Exception e1) {}
  462.     }
  463.     if (!success)
  464.       throw new Exception("Could not copy block data for " + lblock.getBlock());
  465.   }
  466.       
  467.   /*
  468.    * XXX (ab) See comment above for copyBlock().
  469.    *
  470.    * Pick the best node from which to stream the data.
  471.    * That's the local one, if available.
  472.    */
  473.   Random r = new Random();
  474.   private DatanodeInfo bestNode(DFSClient dfs, DatanodeInfo[] nodes,
  475.                                 TreeSet<DatanodeInfo> deadNodes) throws IOException {
  476.     if ((nodes == null) ||
  477.         (nodes.length - deadNodes.size() < 1)) {
  478.       throw new IOException("No live nodes contain current block");
  479.     }
  480.     DatanodeInfo chosenNode;
  481.     do {
  482.       chosenNode = nodes[r.nextInt(nodes.length)];
  483.     } while (deadNodes.contains(chosenNode));
  484.     return chosenNode;
  485.   }
  486.   
  487.   private void lostFoundInit(DFSClient dfs) {
  488.     lfInited = true;
  489.     try {
  490.       String lfName = "/lost+found";
  491.       // check that /lost+found exists
  492.       if (!dfs.exists(lfName)) {
  493.         lfInitedOk = dfs.mkdirs(lfName);
  494.         lostFound = lfName;
  495.       } else        if (!dfs.isDirectory(lfName)) {
  496.         LOG.warn("Cannot use /lost+found : a regular file with this name exists.");
  497.         lfInitedOk = false;
  498.       }  else { // exists and isDirectory
  499.         lostFound = lfName;
  500.         lfInitedOk = true;
  501.       }
  502.     }  catch (Exception e) {
  503.       e.printStackTrace();
  504.       lfInitedOk = false;
  505.     }
  506.     if (lostFound == null) {
  507.       LOG.warn("Cannot initialize /lost+found .");
  508.       lfInitedOk = false;
  509.     }
  510.   }
  511.   
  512.   /**
  513.    * @param args
  514.    */
  515.   public int run(String[] args) throws Exception {
  516.     
  517.     return 0;
  518.   }
  519.   
  520.   /**
  521.    * FsckResult of checking, plus overall DFS statistics.
  522.    *
  523.    */
  524.   public static class FsckResult {
  525.     private ArrayList<String> missingIds = new ArrayList<String>();
  526.     private long missingSize = 0L;
  527.     private long corruptFiles = 0L;
  528.     private long corruptBlocks = 0L;
  529.     private long excessiveReplicas = 0L;
  530.     private long missingReplicas = 0L;
  531.     private long numOverReplicatedBlocks = 0L;
  532.     private long numUnderReplicatedBlocks = 0L;
  533.     private long numMisReplicatedBlocks = 0L;  // blocks that do not satisfy block placement policy
  534.     private long numMinReplicatedBlocks = 0L;  // minimally replicatedblocks
  535.     private int replication = 0;
  536.     private long totalBlocks = 0L;
  537.     private long totalOpenFilesBlocks = 0L;
  538.     private long totalFiles = 0L;
  539.     private long totalOpenFiles = 0L;
  540.     private long totalDirs = 0L;
  541.     private long totalSize = 0L;
  542.     private long totalOpenFilesSize = 0L;
  543.     private long totalReplicas = 0L;
  544.     private int totalDatanodes = 0;
  545.     private int totalRacks = 0;
  546.     
  547.     /**
  548.      * DFS is considered healthy if there are no missing blocks.
  549.      */
  550.     public boolean isHealthy() {
  551.       return ((missingIds.size() == 0) && (corruptBlocks == 0));
  552.     }
  553.     
  554.     /** Add a missing block name, plus its size. */
  555.     public void addMissing(String id, long size) {
  556.       missingIds.add(id);
  557.       missingSize += size;
  558.     }
  559.     
  560.     /** Return a list of missing block names (as list of Strings). */
  561.     public ArrayList<String> getMissingIds() {
  562.       return missingIds;
  563.     }
  564.     
  565.     /** Return total size of missing data, in bytes. */
  566.     public long getMissingSize() {
  567.       return missingSize;
  568.     }
  569.     public void setMissingSize(long missingSize) {
  570.       this.missingSize = missingSize;
  571.     }
  572.     
  573.     /** Return the number of over-replicated blocks. */
  574.     public long getExcessiveReplicas() {
  575.       return excessiveReplicas;
  576.     }
  577.     
  578.     public void setExcessiveReplicas(long overReplicatedBlocks) {
  579.       this.excessiveReplicas = overReplicatedBlocks;
  580.     }
  581.     
  582.     /** Return the actual replication factor. */
  583.     public float getReplicationFactor() {
  584.       if (totalBlocks == 0)
  585.         return 0.0f;
  586.       return (float) (totalReplicas) / (float) totalBlocks;
  587.     }
  588.     
  589.     /** Return the number of under-replicated blocks. Note: missing blocks are not counted here.*/
  590.     public long getMissingReplicas() {
  591.       return missingReplicas;
  592.     }
  593.     
  594.     public void setMissingReplicas(long underReplicatedBlocks) {
  595.       this.missingReplicas = underReplicatedBlocks;
  596.     }
  597.     
  598.     /** Return total number of directories encountered during this scan. */
  599.     public long getTotalDirs() {
  600.       return totalDirs;
  601.     }
  602.     
  603.     public void setTotalDirs(long totalDirs) {
  604.       this.totalDirs = totalDirs;
  605.     }
  606.     
  607.     /** Return total number of files encountered during this scan. */
  608.     public long getTotalFiles() {
  609.       return totalFiles;
  610.     }
  611.     
  612.     public void setTotalFiles(long totalFiles) {
  613.       this.totalFiles = totalFiles;
  614.     }
  615.     
  616.     /** Return total number of files opened for write encountered during this scan. */
  617.     public long getTotalOpenFiles() {
  618.       return totalOpenFiles;
  619.     }
  620.     /** Set total number of open files encountered during this scan. */
  621.     public void setTotalOpenFiles(long totalOpenFiles) {
  622.       this.totalOpenFiles = totalOpenFiles;
  623.     }
  624.     
  625.     /** Return total size of scanned data, in bytes. */
  626.     public long getTotalSize() {
  627.       return totalSize;
  628.     }
  629.     
  630.     public void setTotalSize(long totalSize) {
  631.       this.totalSize = totalSize;
  632.     }
  633.     
  634.     /** Return total size of open files data, in bytes. */
  635.     public long getTotalOpenFilesSize() {
  636.       return totalOpenFilesSize;
  637.     }
  638.     
  639.     public void setTotalOpenFilesSize(long totalOpenFilesSize) {
  640.       this.totalOpenFilesSize = totalOpenFilesSize;
  641.     }
  642.     
  643.     /** Return the intended replication factor, against which the over/under-
  644.      * replicated blocks are counted. Note: this values comes from the current
  645.      * Configuration supplied for the tool, so it may be different from the
  646.      * value in DFS Configuration.
  647.      */
  648.     public int getReplication() {
  649.       return replication;
  650.     }
  651.     
  652.     public void setReplication(int replication) {
  653.       this.replication = replication;
  654.     }
  655.     
  656.     /** Return the total number of blocks in the scanned area. */
  657.     public long getTotalBlocks() {
  658.       return totalBlocks;
  659.     }
  660.     
  661.     public void setTotalBlocks(long totalBlocks) {
  662.       this.totalBlocks = totalBlocks;
  663.     }
  664.     
  665.     /** Return the total number of blocks held by open files. */
  666.     public long getTotalOpenFilesBlocks() {
  667.       return totalOpenFilesBlocks;
  668.     }
  669.     
  670.     public void setTotalOpenFilesBlocks(long totalOpenFilesBlocks) {
  671.       this.totalOpenFilesBlocks = totalOpenFilesBlocks;
  672.     }
  673.     
  674.     public String toString() {
  675.       StringBuffer res = new StringBuffer();
  676.       res.append("Status: " + (isHealthy() ? "HEALTHY" : "CORRUPT"));
  677.       res.append("n Total size:t" + totalSize + " B");
  678.       if (totalOpenFilesSize != 0) 
  679.         res.append(" (Total open files size: " + totalOpenFilesSize + " B)");
  680.       res.append("n Total dirs:t" + totalDirs);
  681.       res.append("n Total files:t" + totalFiles);
  682.       if (totalOpenFiles != 0)
  683.         res.append(" (Files currently being written: " + 
  684.                    totalOpenFiles + ")");
  685.       res.append("n Total blocks (validated):t" + totalBlocks);
  686.       if (totalBlocks > 0) res.append(" (avg. block size "
  687.                                       + (totalSize / totalBlocks) + " B)");
  688.       if (totalOpenFilesBlocks != 0)
  689.         res.append(" (Total open file blocks (not validated): " + 
  690.                    totalOpenFilesBlocks + ")");
  691.       if (corruptFiles > 0) { 
  692.         res.append("n  ********************************");
  693.         res.append("n  CORRUPT FILES:t" + corruptFiles);
  694.         if (missingSize > 0) {
  695.           res.append("n  MISSING BLOCKS:t" + missingIds.size());
  696.           res.append("n  MISSING SIZE:tt" + missingSize + " B");
  697.         }
  698.         if (corruptBlocks > 0) {
  699.           res.append("n  CORRUPT BLOCKS: t" + corruptBlocks);
  700.         }
  701.         res.append("n  ********************************");
  702.       }
  703.       res.append("n Minimally replicated blocks:t" + numMinReplicatedBlocks);
  704.       if (totalBlocks > 0)        res.append(" (" + ((float) (numMinReplicatedBlocks * 100) / (float) totalBlocks) + " %)");
  705.       res.append("n Over-replicated blocks:t" + numOverReplicatedBlocks);
  706.       if (totalBlocks > 0)        res.append(" (" + ((float) (numOverReplicatedBlocks * 100) / (float) totalBlocks) + " %)");
  707.       res.append("n Under-replicated blocks:t" + numUnderReplicatedBlocks);
  708.       if (totalBlocks > 0)        res.append(" (" + ((float) (numUnderReplicatedBlocks * 100) / (float) totalBlocks) + " %)");
  709.       res.append("n Mis-replicated blocks:tt" + numMisReplicatedBlocks);
  710.       if (totalBlocks > 0)        res.append(" (" + ((float) (numMisReplicatedBlocks * 100) / (float) totalBlocks) + " %)");
  711.       res.append("n Default replication factor:t" + replication);
  712.       res.append("n Average block replication:t" + getReplicationFactor());
  713.       res.append("n Corrupt blocks:tt" + corruptBlocks);
  714.       res.append("n Missing replicas:tt" + missingReplicas);
  715.       if (totalReplicas > 0)        res.append(" (" + ((float) (missingReplicas * 100) / (float) totalReplicas) + " %)");
  716.       res.append("n Number of data-nodes:tt" + totalDatanodes);
  717.       res.append("n Number of racks:tt" + totalRacks);
  718.       return res.toString();
  719.     }
  720.     
  721.     /** Return the number of currupted files. */
  722.     public long getCorruptFiles() {
  723.       return corruptFiles;
  724.     }
  725.     
  726.     public void setCorruptFiles(long corruptFiles) {
  727.       this.corruptFiles = corruptFiles;
  728.     }
  729.   }
  730. }