Package org.apache.hadoop.hdfs

Source Code of org.apache.hadoop.hdfs.TestFileHardLink

/**
* 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;

import static org.junit.Assert.*;

import java.io.IOException;
import java.util.List;

import junit.framework.Assert;

import org.apache.commons.logging.impl.Log4JLogger;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.ContentSummary;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.protocol.DSQuotaExceededException;
import org.apache.hadoop.hdfs.protocol.FSConstants;
import org.apache.hadoop.hdfs.protocol.LocatedBlock;
import org.apache.hadoop.hdfs.protocol.NSQuotaExceededException;
import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
import org.apache.hadoop.hdfs.server.namenode.LeaseManager;
import org.apache.hadoop.hdfs.server.namenode.NameNode;
import org.apache.log4j.Level;
import org.junit.Test;

public class TestFileHardLink {
    {
      ((Log4JLogger)NameNode.stateChangeLog).getLogger().setLevel(Level.ALL);
      ((Log4JLogger)LeaseManager.LOG).getLogger().setLevel(Level.ALL);
      ((Log4JLogger)FSNamesystem.LOG).getLogger().setLevel(Level.ALL);
    }
   
  @Test
  public void testHardLinkAfterRestart() throws Exception {
    final Configuration conf = new Configuration();
    final MiniDFSCluster cluster = new MiniDFSCluster(conf, 1, true, null);
    try {
      final FileSystem fs = cluster.getFileSystem();
      DFSTestUtil.createFile(fs, new Path("/f1"), 1, (short) 1, 0);
      DFSTestUtil.createFile(fs, new Path("/f2"), 1, (short) 1, 0);
      fs.hardLink(new Path("/f1"), new Path("/dst/f1"));
      cluster.getNameNode().saveNamespace(true, false);
      cluster.restartNameNode();
      fs.hardLink(new Path("/f2"), new Path("/dst/f2"));
      long hid1 = cluster.getNameNode().namesystem.dir.getHardLinkId("/f1");
      long hid2 = cluster.getNameNode().namesystem.dir.getHardLinkId("/f2");
      assertEquals(0, hid1);
      assertEquals(1, hid2);
    } finally {
      cluster.shutdown();
    }
  }

  @Test
  public void testHardLinkWithSameFilename() throws Exception
    final Configuration conf = new Configuration();
    final MiniDFSCluster cluster = new MiniDFSCluster(conf, 2, true, null);
    final FileSystem fs = cluster.getFileSystem()
    assertTrue("Not a HDFS: "+ fs.getUri(), fs instanceof DistributedFileSystem);
    final DistributedFileSystem dfs = (DistributedFileSystem)fs; 
    final Path p1 = new Path("/d1/f");
    final Path p2 = new Path("/d2/f");
    try {
      FSDataOutputStream stm1 = TestFileCreation.createFile(fs, p1, 1);
      stm1.sync();
      stm1.close();
     
      dfs.hardLink(p1, p2);
      dfs.delete(p2, true);
    } catch (Exception e) {
      Assert.fail("testHardLinkWithSameFilename is failed due to " + e.getMessage());
    } finally {
      cluster.shutdown();
    }
  }

  @Test
  public void testHardLinkFiles() throws IOException {
    Configuration conf = new Configuration();
    final int MAX_IDLE_TIME = 2000; // 2s
    conf.setInt("ipc.client.connection.maxidletime", MAX_IDLE_TIME);
    conf.setInt("heartbeat.recheck.interval", 1000);
    conf.setInt("dfs.heartbeat.interval", 1);
    conf.setInt("dfs.safemode.threshold.pct", 1);
    conf.setBoolean("dfs.support.append", true);
    conf.setLong("dfs.blockreport.intervalMsec", 0);

    // create cluster
    MiniDFSCluster cluster = new MiniDFSCluster(conf, 3, true, null);
    //final DFSClient dfsClient = new DFSClient(NameNode.getAddress(conf), conf);
    FileSystem fs = null;
    long dirOverHead = 0;
    boolean result;
    NameNode nameNode = cluster.getNameNode();
    try {
      cluster.waitActive();
      fs = cluster.getFileSystem();

      try {
        cluster.getNameNode().namesystem.dir.getHardLinkId("/nonexistentfile");
        fail("Did not throw exception for getHardLinkId() on nonexistent file");
      } catch (IOException ie) {
        System.out.println("Expected exception : " + ie);
      }

      // open /user/dir1/file1 and write
      Path dir1 = new Path("/user/dir1");
      fs.mkdirs(dir1);
      dirOverHead = fs.getContentSummary(dir1).getLength();
      System.out.println("The dir overhead is " + dirOverHead);
     
      // write file into file1
      Path file1 = new Path(dir1, "file1");
      FSDataOutputStream stm1 = TestFileCreation.createFile(fs, file1, 1);
      byte[] content = TestFileCreation.writeFile(stm1);
      stm1.sync();
      stm1.close();
     
      try {
        cluster.getNameNode().namesystem.dir.getHardLinkId(file1.toUri()
            .getPath());
        fail("Did not throw exception for getHardLinkId() on non hardlinked file file");
      } catch (IOException ie) {
        System.out.println("Expected exception : " + ie);
      }

      // Verify links.
      String[] links = fs.getHardLinkedFiles(file1);
      Assert.assertEquals(0, links.length);

      /* du /user/dir1 -> dirLength1
       * du /user/dir1/file1 -> fileLength1
       * dirLenght1 = fileLenght1 + dirOverhead
       */
      long dirLength1 = fs.getContentSummary(dir1).getLength();
      long fileLength1 = fs.getContentSummary(file1).getLength();
      Assert.assertEquals(dirOverHead, dirLength1 - fileLength1);
      FileStatus fStatus1 = fs.getFileStatus(file1);
      Assert.assertTrue(fStatus1.getBlockSize() > 0 );
      System.out.println("dir1 length: " + dirLength1 + " file1 length: " + fileLength1 +
          " block size " + fStatus1.getBlockSize());
     
      // create /user/dir2
      Path dir2 = new Path("/user/dir2");
      fs.mkdirs(dir2);
      Path file2 = new Path(dir2, "file2");
      // ln /user/dir1/ /user/dir2/ [error: cannot hard link a directory]
      result = fs.hardLink(dir1, dir2);
      Assert.assertFalse(result);
     
      // ln /user/dir1/file1 /user/dir2/file2
      result = fs.hardLink(file1, file2);

      // Verify links.
      links = fs.getHardLinkedFiles(file1);
      Assert.assertEquals(1, links.length);
      Assert.assertEquals(file2, new Path(links[0]));

      Assert.assertTrue(result);
      verifyLinkedFileIdenticial(fs, nameNode, fStatus1, fs.getFileStatus(file1), content);
      // Verify all the linked files shared the same file properties such as modification time
      long current = System.currentTimeMillis();
      String testUserName = "testUser";
      String testGroupName = "testGroupName";
      FsPermission pemission = new FsPermission(FsAction.READ_WRITE,
          FsAction.READ_WRITE, FsAction.READ_WRITE);
      short newReplication = (short) (fs.getFileStatus(file1).getReplication() + 1);
     
      fs.setTimes(file2, current, current);
      fs.setOwner(file2, testUserName, testGroupName);
      fs.setPermission(file1, pemission);
     
      // increase replication
      fs.setReplication(file2, newReplication);
     
      // make sure the file is replicated
      DFSTestUtil.waitReplication(fs, file2, (short) newReplication);
      DFSTestUtil.waitReplication(fs, file1, (short) newReplication);
     
      // decrease replication
      newReplication--;
      fs.setReplication(file2, newReplication);
     
      // make sure the file is replicated
      DFSTestUtil.waitReplication(fs, file2, (short) newReplication);
      DFSTestUtil.waitReplication(fs, file1, (short) newReplication);

      fStatus1 = fs.getFileStatus(file1);
      FileStatus fStatus2 = fs.getFileStatus(file2);
     
      assertEquals(current, fStatus1.getModificationTime());
      assertEquals(current, fStatus2.getModificationTime());
     
      assertEquals(testUserName, fStatus1.getOwner());
      assertEquals(testUserName, fStatus2.getOwner());
     
      assertEquals(testGroupName, fStatus1.getGroup());
      assertEquals(testGroupName, fStatus2.getGroup());
     
      assertEquals(pemission, fStatus1.getPermission());
      assertEquals(pemission, fStatus2.getPermission());
     
      assertEquals(newReplication, fStatus1.getReplication());
      assertEquals(newReplication, fStatus2.getReplication());
     
      /*
       * du /user/dir2 -> dirLength2
       * du /user/dir2/file2 -> fileLength2
       * dirLength2 == dirLenght1
       * fileLenght2 == fileLength1
       */
      Assert.assertTrue(fStatus2.getBlockSize() > 0 );
      long dirLength2 = fs.getContentSummary(dir2).getLength();
      long fileLength2 = fs.getContentSummary(file2).getLength();
      Assert.assertEquals(dirOverHead, dirLength2 - fileLength2);
      Assert.assertEquals(fileLength1, fileLength2);
      Assert.assertEquals(dirLength1, dirLength2);
      // verify file1 and file2 are identical
      verifyLinkedFileIdenticial(fs, nameNode, fStatus1, fStatus2, content);
      System.out.println("dir2 length: " + dirLength2 + " file2 length: " + fileLength2);
     
      // ln /user/dir1/file1 /user/dir2/file2
      // client can retry the hardlink operation without error
      result = fs.hardLink(file1, file2);
      Assert.assertTrue(result);
     
      Path dir3= new Path("/user/dir3/dir33/dir333");
      Path file3 = new Path(dir3, "file3");
     
      // ln /user/dir2/file2 /user/dir3/dir33/dir333/file3 [create the intermediate dirs on the fly]
      result = fs.hardLink(file2, file3);
      Assert.assertTrue(result);
      // ln /user/dir2/file2 /user/dir3/file3
      fs.mkdirs(dir3);
      result = fs.hardLink(file2, file3);

      // Verify links, now 3 links file1, file2, file3
      links = fs.getHardLinkedFiles(file1);
      Assert.assertEquals(2, links.length);
      for (String link : links) {
        if (!(file2.equals(new Path(link)) || file3.equals(new Path(link)))) {
          fail("Could not find " + file1 + " or " + file2
              + " in the list of links");
        }
      }

      Assert.assertTrue(result);
      FileStatus fStatus3 = fs.getFileStatus(file3);
     
      long dirLength3 = fs.getContentSummary(dir3).getLength();
      long fileLength3 = fs.getContentSummary(file3).getLength();
      Assert.assertEquals(dirOverHead, dirLength3 - fileLength3);
      Assert.assertEquals(fileLength2, fileLength3);
      Assert.assertEquals(dirLength2, dirLength3);
     
      // verify that file3 is identical to file 2 and file 1
      Assert.assertTrue(fStatus3.getBlockSize() > 0 );
      verifyLinkedFileIdenticial(fs, nameNode, fStatus1, fStatus3, content);
      verifyLinkedFileIdenticial(fs, nameNode, fStatus2, fStatus3, content);
      System.out.println("dir3 length: " + dirLength3 + " file3 length: " + fileLength3);
     
      /* 
       * du /user -> totalDU 
       * totalDU = du1 + du2 + du3 - file1 - file2 
       * totalDU = 3 * dirOverhead + file1 
       */
      long totalDU = fs.getContentSummary(new Path("/user")).getLength();
      System.out.println("Total DU for /user is " + totalDU);
      Assert.assertEquals(totalDU, dirLength3 + dirLength2 + dirLength1
          - fileLength1 - fileLength2 )
      Assert.assertEquals(totalDU, 3 * dirOverHead + fileLength1);
     
      /* start to test the delete operation
      * delete /user/dir1/file1
      * verify no file1 any more and verify there is no change for file2 and file3
      */
      fs.delete(file1, true);

      // Verify links, now 2 links file2, file3
      links = fs.getHardLinkedFiles(file2);
      Assert.assertEquals(1, links.length);
      Assert.assertEquals(file3, new Path(links[0]));

      Assert.assertFalse(fs.exists(file1)) ;
      Assert.assertEquals(dirOverHead, fs.getContentSummary(dir1).getLength());
      Assert.assertEquals(fileLength2, fs.getContentSummary(file2).getLength());
      Assert.assertEquals(fileLength3, fs.getContentSummary(file3).getLength());
      Assert.assertEquals(dirLength2, fs.getContentSummary(dir2).getLength());
      Assert.assertEquals(dirLength3, fs.getContentSummary(dir3).getLength());
      verifyLinkedFileIdenticial(fs, nameNode, fStatus2, fs.getFileStatus(file2), content);
      verifyLinkedFileIdenticial(fs, nameNode, fStatus3, fs.getFileStatus(file3), content);
     
      /*
      * delete /user/dir2/
      * verify no file2 or dir2 any more and verify there is no change for file3
      */
      fs.delete(dir2, true);
      // Verify links, now only 1 links file3
      links = fs.getHardLinkedFiles(file3);
      Assert.assertEquals(0, links.length);

      Assert.assertFalse(fs.exists(file2));
      Assert.assertFalse(fs.exists(dir2));
      Assert.assertEquals(fileLength3, fs.getContentSummary(file3).getLength());
      Assert.assertEquals(dirLength3, fs.getContentSummary(dir3).getLength());
      verifyLinkedFileIdenticial(fs, nameNode, fStatus3, fs.getFileStatus(file3), content);
     
      /*
       * delete /user/dir3/
       * verify no file3 or dir3 any more and verify the total DU
       */
       fs.delete(dir3, true);
       Assert.assertFalse(fs.exists(file3));
       Assert.assertFalse(fs.exists(dir3));
       totalDU = fs.getContentSummary(new Path("/user")).getLength()
       Assert.assertEquals(totalDU, dirOverHead);
    } finally {
      fs.close();
      cluster.shutdown();
    }
  }

  @Test
  public void testHardLinkWithDirDeletion() throws Exception
    final Configuration conf = new Configuration();
    final MiniDFSCluster cluster = new MiniDFSCluster(conf, 2, true, null);
    final FileSystem fs = cluster.getFileSystem()
    assertTrue("Not a HDFS: "+ fs.getUri(), fs instanceof DistributedFileSystem);
    final DistributedFileSystem dfs = (DistributedFileSystem)fs; 
    final int NUM_FILES = 1000;
    try {
      // 1: create directories: /root/dir1 and /root/dir2
      final Path root = new Path("/root/");
      assertTrue(dfs.mkdirs(root));
       
      final Path dir1 = new Path(root, "dir1");
      assertTrue(dfs.mkdirs(dir1));
      final Path dir2 = new Path(root, "dir2");
      assertTrue(dfs.mkdirs(dir2));
       
      ContentSummary rootSummary, c1, c2;
      rootSummary = dfs.getContentSummary(root)
      Assert.assertEquals(0, rootSummary.getFileCount());
      Assert.assertEquals(3, rootSummary.getDirectoryCount())
      // There are 4 directories left: root, dir1, dir2 and HDFS's root directory. 
      Assert.assertEquals(4, cluster.getNameNode().getNamesystem().getFilesAndDirectoriesTotal())
       
      // 2: create NUM_FILES files under dir1 and create their hardlink files in both dir1 and dir2. 
      // And check the files count as well.
      for (int i = 1; i <= NUM_FILES; i++) { 
        final Path target = new Path(dir1, "file-" + i)
        final Path hardLink1 = new Path(dir1, "hardlink-file-" + i)
        final Path hardLink2 = new Path(dir2, "hardlink-file-" + i)
         
        DFSTestUtil.createFile(dfs, target, 1L, (short)3, 0L)
        fs.hardLink(target, hardLink1);
        fs.hardLink(target, hardLink2);
         
        c1 = dfs.getContentSummary(dir1);
        Assert.assertEquals(2 * i, c1.getFileCount())
         
        c2 = dfs.getContentSummary(dir2);
        Assert.assertEquals(i, c2.getFileCount())
      }
       
      rootSummary = dfs.getContentSummary(root)
      Assert.assertEquals(3 * NUM_FILES, rootSummary.getFileCount());
      Assert.assertEquals(3, rootSummary.getDirectoryCount())
       
      // 3: delete dir1 directly (skipping trash) and check the files count again
      dfs.getClient().delete(dir1.toUri().getPath(), true);
       
      c2 = dfs.getContentSummary(dir2);
      Assert.assertEquals(NUM_FILES, c2.getFileCount())
       
      rootSummary = dfs.getContentSummary(root)
      Assert.assertEquals(NUM_FILES, rootSummary.getFileCount());
      Assert.assertEquals(2, rootSummary.getDirectoryCount())
       
      // There are 3 directories left: root, dir1 and HDFS's root directory. 
      Assert.assertEquals(NUM_FILES + 3
          cluster.getNameNode().getNamesystem().getFilesAndDirectoriesTotal());
    } finally {
      cluster.shutdown();
    }
  }
 
  @Test
  public void testHardLinkWithFileOverwite() throws Exception {
    final Configuration conf = new Configuration();
    final MiniDFSCluster cluster = new MiniDFSCluster(conf, 2, true, null);
    final FileSystem fs = cluster.getFileSystem();
    assertTrue("Not a HDFS: "+ fs.getUri(), fs instanceof DistributedFileSystem);
    final DistributedFileSystem dfs = (DistributedFileSystem)fs;
    try {
      // 1: create the root dir
      ContentSummary c;
      final Path root = new Path("/root/");
      assertTrue(dfs.mkdirs(root));
     
      // 2: create file1 and its hardlink file: file1-hardlink-orig
      final Path file1 =  new Path(root, "file1");
      DFSTestUtil.createFile(dfs, file1, 1L, (short)3, 0L);
     
      final Path file1HardLinkOrig =  new Path(root, "file1-hardlink-orig");
      fs.hardLink(file1, file1HardLinkOrig);
      Assert.assertEquals(1, fs.getHardLinkedFiles(file1).length);
     
      c = dfs.getContentSummary(root);
      Assert.assertEquals(2, c.getFileCount());
      Assert.assertEquals(4, cluster.getNameNode().getNamesystem().getFilesAndDirectoriesTotal());
     
      // 3: overwrite the file1
      DFSTestUtil.createFile(dfs, file1, 2L, (short)3, 0L);
      Assert.assertEquals(0, fs.getHardLinkedFiles(file1).length);
      Assert.assertEquals(0, fs.getHardLinkedFiles(file1HardLinkOrig).length);
     
      c = dfs.getContentSummary(root);
      Assert.assertEquals(2, c.getFileCount());
      Assert.assertEquals(4, cluster.getNameNode().getNamesystem().getFilesAndDirectoriesTotal());
     
      // 4: create a new hardlink file for the file1: file1-hardlink-new
      final Path file1HardLinkNew =  new Path(root, "file1-hardlink-new");
      fs.hardLink(file1, file1HardLinkNew);
      Assert.assertEquals(1, fs.getHardLinkedFiles(file1).length);
      Assert.assertEquals(1, fs.getHardLinkedFiles(file1HardLinkNew).length);
      Assert.assertEquals(0, fs.getHardLinkedFiles(file1HardLinkOrig).length);
     
      c = dfs.getContentSummary(root);
      Assert.assertEquals(3, c.getFileCount());
      Assert.assertEquals(5, cluster.getNameNode().getNamesystem().getFilesAndDirectoriesTotal());
    } finally {
      cluster.shutdown();
    }
  }
 
  @Test
  public void testHardLinkWithNNRestart() throws Exception {
    final Configuration conf = new Configuration();
    MiniDFSCluster cluster = new MiniDFSCluster(conf, 2, true, null);
    FileSystem fs = cluster.getFileSystem();
    NameNode nameNode = cluster.getNameNode();
    assertTrue("Not a HDFS: "+ fs.getUri(), fs instanceof DistributedFileSystem);
    try {
      // Create a new file
      Path root = new Path("/user/");
      Path file10 = new Path(root, "file1");
      FSDataOutputStream stm1 = TestFileCreation.createFile(fs, file10, 1);
      byte[] content = TestFileCreation.writeFile(stm1);
      stm1.close();
     
      Path file11 =  new Path(root, "file-11");
      Path file12 =  new Path(root, "file-12");
      fs.hardLink(file10, file11);
      fs.hardLink(file11, file12);
     
      verifyLinkedFileIdenticial(fs, nameNode, fs.getFileStatus(file10), fs.getFileStatus(file11),
          content);
      verifyLinkedFileIdenticial(fs, nameNode, fs.getFileStatus(file10), fs.getFileStatus(file12),
          content);
     
      // Restart the cluster
      cluster.restartNameNode();
      nameNode = cluster.getNameNode();
     
      // Verify all the linked files are the same
      verifyLinkedFileIdenticial(fs, nameNode, fs.getFileStatus(file10), fs.getFileStatus(file11),
          content);
      verifyLinkedFileIdenticial(fs, nameNode, fs.getFileStatus(file10), fs.getFileStatus(file12),
          content);
     
      // Delete file10
      fs.delete(file10, true);
      assertFalse(fs.exists(file10));
      assertTrue(fs.exists(file11));
      assertTrue(fs.exists(file12));
     
      // Restart the cluster
      cluster.restartNameNode();
      nameNode = cluster.getNameNode();
     
      // Verify the deleted files
      assertFalse(fs.exists(file10));
      assertTrue(fs.exists(file11));
      assertTrue(fs.exists(file12));
      verifyLinkedFileIdenticial(fs, nameNode, fs.getFileStatus(file11), fs.getFileStatus(file12),
          content);
     
      // Delete file11
      fs.delete(file11, true);
      assertFalse(fs.exists(file11));
      assertTrue(fs.exists(file12));
     
      // Restart the cluster
      cluster.restartNameNode();
      assertFalse(fs.exists(file11));
      assertTrue(fs.exists(file12));
    } finally {
      cluster.shutdown();
    }
  }
 
  @Test
  public void testHardLinkWithNSQuota() throws Exception {
    final Configuration conf = new Configuration();
    final MiniDFSCluster cluster = new MiniDFSCluster(conf, 2, true, null);
    final FileSystem fs = cluster.getFileSystem();
    assertTrue("Not a HDFS: "+ fs.getUri(), fs instanceof DistributedFileSystem);
    final DistributedFileSystem dfs = (DistributedFileSystem)fs;
    try {
      // 1: create directories
      final Path root = new Path("/user/");
      final Path dir1 = new Path("/user/dir1/");
      final Path dir2 = new Path("/user/dir1/dir2/");
      assertTrue(dfs.mkdirs(dir2));
     
      // 2: set the ns quota
      dfs.setQuota(root, 6, FSConstants.QUOTA_DONT_SET);
      dfs.setQuota(dir1, 4, FSConstants.QUOTA_DONT_SET);
      dfs.setQuota(dir2, 2, FSConstants.QUOTA_DONT_SET);
     
      verifyNSQuotaSetting(dfs, root, 6, 3);
      verifyNSQuotaSetting(dfs, dir1, 4, 2);
      verifyNSQuotaSetting(dfs, dir2, 2, 1);
     
      // 3: create a regular file: /user/dir1/dir2/file-10 and check the ns quota
      final Path file10 =  new Path(dir2, "file-10");
      DFSTestUtil.createFile(dfs, file10, 1L, (short)3, 0L);
      verifyNSQuotaSetting(dfs, root, 6 ,4);
      verifyNSQuotaSetting(dfs, dir1, 4 ,3);
      verifyNSQuotaSetting(dfs, dir2, 2, 2);
     
      // 4: create a regular file: /user/dir1/dir2/file-11 and catch the NSQuotaExceededException
      final Path file11 =  new Path(dir2, "file-11");
      try {
        DFSTestUtil.createFile(dfs, file11, 1L, (short)3, 0L);
        Assert.fail("Expect an NSQuotaExceededException thrown out");
      } catch (NSQuotaExceededException e) {}

      verifyNSQuotaSetting(dfs, root, 6 ,4);
      verifyNSQuotaSetting(dfs, dir1, 4 ,3);
      verifyNSQuotaSetting(dfs, dir2, 2, 2);
     
      // 5: ln /user/dir1/dir2/file-10 /user/dir1/dir2/file-11 and catch the NSQuotaExceededException
      try {
        fs.hardLink(file10, file11);
        Assert.fail("Expect an NSQuotaExceededException thrown out");
      } catch (NSQuotaExceededException e) {}
      verifyNSQuotaSetting(dfs, root, 6 ,4);
      verifyNSQuotaSetting(dfs, dir1, 4 ,3);
      verifyNSQuotaSetting(dfs, dir2, 2, 2);
     
      // 6: ln /user/dir1/dir2/file-10 /user/dir1/file-12 and verify the quota
      final Path file12 =  new Path(dir1, "file-12");
      assertTrue(fs.hardLink(file10, file12));
      verifyNSQuotaSetting(dfs, root, 6 ,5);
      verifyNSQuotaSetting(dfs, dir1, 4 ,4);
      verifyNSQuotaSetting(dfs, dir2, 2, 2);
     
      // 7: ln /user/dir1/dir2/file-10 /user/dir1/file-13 and catch the NSQuotaExceededException
      final Path file13 = new Path(dir1, "file-13");
      try {
        fs.hardLink(file10, file13);
        Assert.fail("Expect an NSQuotaExceededException thrown out");
      } catch (NSQuotaExceededException e) {}
      verifyNSQuotaSetting(dfs, root, 6 ,5);
      verifyNSQuotaSetting(dfs, dir1, 4 ,4);
      verifyNSQuotaSetting(dfs, dir2, 2, 2);
     
      // 8: ln /user/dir1/dir2/file-10 /user/file-14 and verify the quota
      final Path file14 =  new Path(root, "file-14");
      assertTrue(fs.hardLink(file10, file14));
      verifyNSQuotaSetting(dfs, root, 6 ,6);
      verifyNSQuotaSetting(dfs, dir1, 4 ,4);
      verifyNSQuotaSetting(dfs, dir2, 2, 2);
     
      // 9: ln /user/dir1/dir2/file-10 /user/file-15 and catch the NSQuotaExceededException
      final Path file15 = new Path(root, "file-15");
      try {
        fs.hardLink(file10, file15);
        Assert.fail("Expect an NSQuotaExceededException thrown out");
      } catch (NSQuotaExceededException e) {}
     
      verifyNSQuotaSetting(dfs, root, 6 ,6);
      verifyNSQuotaSetting(dfs, dir1, 4 ,4);
      verifyNSQuotaSetting(dfs, dir2, 2, 2);
    } finally {
      cluster.shutdown();
    }
  }
 
  @Test
  public void testHardLinkWithDSQuota() throws Exception {
    final Configuration conf = new Configuration();
    final MiniDFSCluster cluster = new MiniDFSCluster(conf, 2, true, null);
    final FileSystem fs = cluster.getFileSystem();
    assertTrue("Not a HDFS: "+ fs.getUri(), fs instanceof DistributedFileSystem);
    final DistributedFileSystem dfs = (DistributedFileSystem)fs;
    int fileSize = 256;
    long diskSize = 0;
    try {
      // 1: create directories
      final Path root = new Path("/user/");
      final Path dir1 = new Path("/user/dir1/");
      final Path dir2 = new Path("/user/dir1/dir2/");
      assertTrue(dfs.mkdirs(dir2));
     
      // 2 create the files and get the diskSize
      final Path file10 =  new Path(dir2, "file-10");
      DFSTestUtil.createFile(dfs, file10, (long)fileSize, (short)1, 0L);
      final Path file11 =  new Path(root, "file-11");
      DFSTestUtil.createFile(dfs, file11, (long)fileSize, (short)1, 0L);

      ContentSummary c1 = dfs.getContentSummary(file10);
      diskSize = c1.getSpaceConsumed();
      assertEquals(fileSize, diskSize);
      ContentSummary c2 = dfs.getContentSummary(file11);
      diskSize = c2.getSpaceConsumed();
      assertEquals(fileSize, diskSize);
     
      // 3: set the ds quota
      dfs.setQuota(root, FSConstants.QUOTA_DONT_SET, 3 * diskSize);
      dfs.setQuota(dir1, FSConstants.QUOTA_DONT_SET, 2 * diskSize);
      dfs.setQuota(dir2, FSConstants.QUOTA_DONT_SET, 1 * diskSize);
     
      verifyDSQuotaSetting(dfs, root, 3 * diskSize, 2 * diskSize);
      verifyDSQuotaSetting(dfs, dir1, 2 * diskSize, 1 * diskSize);
      verifyDSQuotaSetting(dfs, dir2, 1 * diskSize, 1 * diskSize);

      // 4: ln /user/dir1/dir2/file-10 /user/dir1/dir2/file-12
      final Path file12 =  new Path(dir2, "file-12");
      assertTrue(fs.hardLink(file10, file12));
      verifyDSQuotaSetting(dfs, root, 3 * diskSize, 2 * diskSize);
      verifyDSQuotaSetting(dfs, dir1, 2 * diskSize, 1 * diskSize);
      verifyDSQuotaSetting(dfs, dir2, 1 * diskSize, 1 * diskSize);

      // 6: ln /user/dir1/dir2/file-10 /user/dir1/file-13
      final Path file13 =  new Path(dir1, "file-13");
      assertTrue(fs.hardLink(file10, file13));
      verifyDSQuotaSetting(dfs, root, 3 * diskSize, 2 * diskSize);
      verifyDSQuotaSetting(dfs, dir1, 2 * diskSize, 1 * diskSize);
      verifyDSQuotaSetting(dfs, dir2, 1 * diskSize, 1 * diskSize);
     
      // 7: ln /user/file-11 /user/dir1/file-14
      final Path file14 =  new Path(dir1, "file-14");
      assertTrue(fs.hardLink(file11, file14));
      verifyDSQuotaSetting(dfs, root, 3 * diskSize, 2 * diskSize);
      verifyDSQuotaSetting(dfs, dir1, 2 * diskSize, 2 * diskSize);
      verifyDSQuotaSetting(dfs, dir2, 1 * diskSize, 1 * diskSize);
     
      // 8: ln /user/file-11 /user/dir1/dir2/file-15
      final Path file15 =  new Path(dir2, "file-15");
      try {
        fs.hardLink(file11, file15);
        Assert.fail("Expect a DSQuotaExceededException thrown out");
      } catch (DSQuotaExceededException e) {}
      verifyDSQuotaSetting(dfs, root, 3 * diskSize, 2 * diskSize);
      verifyDSQuotaSetting(dfs, dir1, 2 * diskSize, 2 * diskSize);
      verifyDSQuotaSetting(dfs, dir2, 1 * diskSize, 1 * diskSize);
    } finally {
      cluster.shutdown();
    }
  }

  public static void verifyLinkedFileIdenticial(FileSystem fs, NameNode nameNode, FileStatus f1,
      FileStatus f2, byte[] content) throws IOException {
    Assert.assertEquals(f1.getBlockSize(), f2.getBlockSize());
    Assert.assertEquals(f1.getAccessTime(), f2.getAccessTime());
    Assert.assertEquals(f1.getChildrenCount(), f2.getChildrenCount());
    Assert.assertEquals(f1.getLen(), f2.getLen());
    Assert.assertEquals(f1.getModificationTime(), f2.getModificationTime());
    Assert.assertEquals(f1.getReplication(), f2.getReplication());
    Assert.assertEquals(f1.getPermission(), f2.getPermission());

    checkBlocks(
        nameNode.getBlockLocations(f1.getPath().toUri().getPath(), 0, f1.getLen()).getLocatedBlocks(),
        nameNode.getBlockLocations(f2.getPath().toUri().getPath(), 0, f2.getLen()).getLocatedBlocks());
   
    checkFile(fs, f1.getPath(), (int) f1.getLen(), content);
    checkFile(fs, f2.getPath(), (int) f2.getLen(), content);
  }

  private static void checkBlocks(List<LocatedBlock> blocks1, List<LocatedBlock> blocks2) {
    Assert.assertEquals(blocks1.size(), blocks2.size());
    for (int i = 0; i < blocks1.size(); i++) {
      Assert.assertEquals(blocks1.get(i).getBlock().getBlockId(),
                          blocks2.get(i).getBlock().getBlockId());
    }
  }
 
  private static void checkFile(FileSystem fs, Path name, int len, byte[] content)
      throws IOException {
    FSDataInputStream stm = fs.open(name);
    byte[] actual = new byte[len];
    stm.readFully(0, actual);
    checkData(actual, 0, content, "check the content of the hard linked file "
        + name + " :");
    stm.close();
  }

  private static void checkData(byte[] actual, int from, byte[] expected,
      String message) {
    for (int idx = 0; idx < actual.length; idx++) {
      assertEquals(message + " byte " + (from + idx) + " differs. expected "
          + expected[from + idx] + " actual " + actual[idx], expected[from
          + idx], actual[idx]);
      actual[idx] = 0;
    }
  }
 
  private static void verifyNSQuotaSetting(DistributedFileSystem dfs, Path path, int nsQuota,
      int nsComsumed) throws IOException {
    ContentSummary c = dfs.getContentSummary(path);
    assertEquals(nsQuota, c.getQuota());
    assertEquals(nsComsumed, c.getFileCount() + c.getDirectoryCount());
  }
 
  private static void verifyDSQuotaSetting(DistributedFileSystem dfs, Path path, long dsCount,
      long diskComsumed) throws IOException {
    ContentSummary c = dfs.getContentSummary(path);
    assertEquals(dsCount, c.getSpaceQuota());
    assertEquals(diskComsumed, c.getSpaceConsumed());
  }
}
TOP

Related Classes of org.apache.hadoop.hdfs.TestFileHardLink

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.