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

网格计算

开发平台:

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;
  19. import junit.framework.TestCase;
  20. import java.io.*;
  21. import java.net.*;
  22. import java.util.List;
  23. import org.apache.hadoop.conf.Configuration;
  24. import org.apache.hadoop.fs.FileSystem;
  25. import org.apache.hadoop.fs.Path;
  26. import org.apache.hadoop.fs.FSDataOutputStream;
  27. import org.apache.hadoop.fs.FSDataInputStream;
  28. import org.apache.hadoop.fs.FileUtil.HardLink;
  29. import org.apache.hadoop.fs.BlockLocation;
  30. import org.apache.hadoop.hdfs.protocol.Block;
  31. import org.apache.hadoop.hdfs.protocol.LocatedBlock;
  32. import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
  33. import org.apache.hadoop.hdfs.server.datanode.DataNode;
  34. import org.apache.hadoop.hdfs.server.datanode.FSDataset;
  35. import org.apache.hadoop.hdfs.server.datanode.SimulatedFSDataset;
  36. /**
  37.  * This class tests the building blocks that are needed to
  38.  * support HDFS appends.
  39.  */
  40. public class TestFileAppend extends TestCase {
  41.   static final int blockSize = 1024;
  42.   static final int numBlocks = 10;
  43.   static final int fileSize = numBlocks * blockSize + 1;
  44.   boolean simulatedStorage = false;
  45.   private long seed;
  46.   private byte[] fileContents = null;
  47.   //
  48.   // create a buffer that contains the entire test file data.
  49.   //
  50.   private void initBuffer(int size) {
  51.     seed = AppendTestUtil.nextLong();
  52.     fileContents = AppendTestUtil.randomBytes(seed, size);
  53.   }
  54.   /*
  55.    * creates a file but does not close it
  56.    */ 
  57.   private FSDataOutputStream createFile(FileSystem fileSys, Path name, int repl)
  58.     throws IOException {
  59.     FSDataOutputStream stm = fileSys.create(name, true,
  60.                                             fileSys.getConf().getInt("io.file.buffer.size", 4096),
  61.                                             (short)repl, (long)blockSize);
  62.     return stm;
  63.   }
  64.   //
  65.   // writes to file but does not close it
  66.   //
  67.   private void writeFile(FSDataOutputStream stm) throws IOException {
  68.     byte[] buffer = AppendTestUtil.randomBytes(seed, fileSize);
  69.     stm.write(buffer);
  70.   }
  71.   //
  72.   // verify that the data written to the full blocks are sane
  73.   // 
  74.   private void checkFile(FileSystem fileSys, Path name, int repl)
  75.     throws IOException {
  76.     boolean done = false;
  77.     // wait till all full blocks are confirmed by the datanodes.
  78.     while (!done) {
  79.       try {
  80.         Thread.sleep(1000);
  81.       } catch (InterruptedException e) {}
  82.       done = true;
  83.       BlockLocation[] locations = fileSys.getFileBlockLocations(
  84.           fileSys.getFileStatus(name), 0, fileSize);
  85.       if (locations.length < numBlocks) {
  86.         System.out.println("Number of blocks found " + locations.length);
  87.         done = false;
  88.         continue;
  89.       }
  90.       for (int idx = 0; idx < numBlocks; idx++) {
  91.         if (locations[idx].getHosts().length < repl) {
  92.           System.out.println("Block index " + idx + " not yet replciated.");
  93.           done = false;
  94.           break;
  95.         }
  96.       }
  97.     }
  98.     FSDataInputStream stm = fileSys.open(name);
  99.     byte[] expected = new byte[numBlocks * blockSize];
  100.     if (simulatedStorage) {
  101.       for (int i= 0; i < expected.length; i++) {  
  102.         expected[i] = SimulatedFSDataset.DEFAULT_DATABYTE;
  103.       }
  104.     } else {
  105.       for (int i= 0; i < expected.length; i++) {  
  106.         expected[i] = fileContents[i];
  107.       }
  108.     }
  109.     // do a sanity check. Read the file
  110.     byte[] actual = new byte[numBlocks * blockSize];
  111.     stm.readFully(0, actual);
  112.     checkData(actual, 0, expected, "Read 1");
  113.   }
  114.   private void checkFullFile(FileSystem fs, Path name) throws IOException {
  115.     FSDataInputStream stm = fs.open(name);
  116.     byte[] actual = new byte[fileSize];
  117.     stm.readFully(0, actual);
  118.     checkData(actual, 0, fileContents, "Read 2");
  119.     stm.close();
  120.   }
  121.   private void checkData(byte[] actual, int from, byte[] expected, String message) {
  122.     for (int idx = 0; idx < actual.length; idx++) {
  123.       assertEquals(message+" byte "+(from+idx)+" differs. expected "+
  124.                    expected[from+idx]+" actual "+actual[idx],
  125.                    expected[from+idx], actual[idx]);
  126.       actual[idx] = 0;
  127.     }
  128.   }
  129.   /**
  130.    * Test that copy on write for blocks works correctly
  131.    */
  132.   public void testCopyOnWrite() throws IOException {
  133.     Configuration conf = new Configuration();
  134.     if (simulatedStorage) {
  135.       conf.setBoolean(SimulatedFSDataset.CONFIG_PROPERTY_SIMULATED, true);
  136.     }
  137.     MiniDFSCluster cluster = new MiniDFSCluster(conf, 1, true, null);
  138.     FileSystem fs = cluster.getFileSystem();
  139.     InetSocketAddress addr = new InetSocketAddress("localhost",
  140.                                                    cluster.getNameNodePort());
  141.     DFSClient client = new DFSClient(addr, conf);
  142.     try {
  143.       // create a new file, write to it and close it.
  144.       //
  145.       Path file1 = new Path("/filestatus.dat");
  146.       FSDataOutputStream stm = createFile(fs, file1, 1);
  147.       writeFile(stm);
  148.       stm.close();
  149.       // Get a handle to the datanode
  150.       DataNode[] dn = cluster.listDataNodes();
  151.       assertTrue("There should be only one datanode but found " + dn.length,
  152.                   dn.length == 1);
  153.       LocatedBlocks locations = client.namenode.getBlockLocations(
  154.                                   file1.toString(), 0, Long.MAX_VALUE);
  155.       List<LocatedBlock> blocks = locations.getLocatedBlocks();
  156.       FSDataset dataset = (FSDataset) dn[0].data;
  157.       //
  158.       // Create hard links for a few of the blocks
  159.       //
  160.       for (int i = 0; i < blocks.size(); i = i + 2) {
  161.         Block b = (Block) blocks.get(i).getBlock();
  162.         FSDataset fsd = (FSDataset) dataset;
  163.         File f = fsd.getFile(b);
  164.         File link = new File(f.toString() + ".link");
  165.         System.out.println("Creating hardlink for File " + f + 
  166.                            " to " + link);
  167.         HardLink.createHardLink(f, link);
  168.       }
  169.       //
  170.       // Detach all blocks. This should remove hardlinks (if any)
  171.       //
  172.       for (int i = 0; i < blocks.size(); i++) {
  173.         Block b = (Block) blocks.get(i).getBlock();
  174.         System.out.println("testCopyOnWrite detaching block " + b);
  175.         assertTrue("Detaching block " + b + " should have returned true",
  176.                    dataset.detachBlock(b, 1) == true);
  177.       }
  178.       // Since the blocks were already detached earlier, these calls should
  179.       // return false
  180.       //
  181.       for (int i = 0; i < blocks.size(); i++) {
  182.         Block b = (Block) blocks.get(i).getBlock();
  183.         System.out.println("testCopyOnWrite detaching block " + b);
  184.         assertTrue("Detaching block " + b + " should have returned false",
  185.                    dataset.detachBlock(b, 1) == false);
  186.       }
  187.     } finally {
  188.       fs.close();
  189.       cluster.shutdown();
  190.     }
  191.   }
  192.   /**
  193.    * Test a simple flush on a simple HDFS file.
  194.    */
  195.   public void testSimpleFlush() throws IOException {
  196.     Configuration conf = new Configuration();
  197.     if (simulatedStorage) {
  198.       conf.setBoolean(SimulatedFSDataset.CONFIG_PROPERTY_SIMULATED, true);
  199.     }
  200.     initBuffer(fileSize);
  201.     MiniDFSCluster cluster = new MiniDFSCluster(conf, 1, true, null);
  202.     FileSystem fs = cluster.getFileSystem();
  203.     try {
  204.       // create a new file.
  205.       Path file1 = new Path("/simpleFlush.dat");
  206.       FSDataOutputStream stm = createFile(fs, file1, 1);
  207.       System.out.println("Created file simpleFlush.dat");
  208.       // write to file
  209.       int mid = fileSize/2;
  210.       stm.write(fileContents, 0, mid);
  211.       stm.sync();
  212.       System.out.println("Wrote and Flushed first part of file.");
  213.       // write the remainder of the file
  214.       stm.write(fileContents, mid, fileSize - mid);
  215.       System.out.println("Written second part of file");
  216.       stm.sync();
  217.       stm.sync();
  218.       System.out.println("Wrote and Flushed second part of file.");
  219.       // verify that full blocks are sane
  220.       checkFile(fs, file1, 1);
  221.       stm.close();
  222.       System.out.println("Closed file.");
  223.       // verify that entire file is good
  224.       checkFullFile(fs, file1);
  225.     } catch (IOException e) {
  226.       System.out.println("Exception :" + e);
  227.       throw e; 
  228.     } catch (Throwable e) {
  229.       System.out.println("Throwable :" + e);
  230.       e.printStackTrace();
  231.       throw new IOException("Throwable : " + e);
  232.     } finally {
  233.       fs.close();
  234.       cluster.shutdown();
  235.     }
  236.   }
  237.   /**
  238.    * Test that file data can be flushed.
  239.    */
  240.   public void testComplexFlush() throws IOException {
  241.     Configuration conf = new Configuration();
  242.     if (simulatedStorage) {
  243.       conf.setBoolean(SimulatedFSDataset.CONFIG_PROPERTY_SIMULATED, true);
  244.     }
  245.     initBuffer(fileSize);
  246.     MiniDFSCluster cluster = new MiniDFSCluster(conf, 1, true, null);
  247.     FileSystem fs = cluster.getFileSystem();
  248.     try {
  249.       // create a new file.
  250.       Path file1 = new Path("/complexFlush.dat");
  251.       FSDataOutputStream stm = createFile(fs, file1, 1);
  252.       System.out.println("Created file complexFlush.dat");
  253.       int start = 0;
  254.       for (start = 0; (start + 29) < fileSize; ) {
  255.         stm.write(fileContents, start, 29);
  256.         stm.sync();
  257.         start += 29;
  258.       }
  259.       stm.write(fileContents, start, fileSize-start);
  260.       // verify that full blocks are sane
  261.       checkFile(fs, file1, 1);
  262.       stm.close();
  263.       // verify that entire file is good
  264.       checkFullFile(fs, file1);
  265.     } catch (IOException e) {
  266.       System.out.println("Exception :" + e);
  267.       throw e; 
  268.     } catch (Throwable e) {
  269.       System.out.println("Throwable :" + e);
  270.       e.printStackTrace();
  271.       throw new IOException("Throwable : " + e);
  272.     } finally {
  273.       fs.close();
  274.       cluster.shutdown();
  275.     }
  276.   }
  277. }