@Override
    public void run() {
      boolean succeeded = false;
      final FsDatasetImpl dataset = (FsDatasetImpl) datanode.getFSDataset();
      try (FsVolumeReference ref = this.targetVolume) {
        int smallBufferSize = DFSUtil.getSmallBufferSize(EMPTY_HDFS_CONF);
        // No FsDatasetImpl lock for the file copy
        File targetFiles[] =
            FsDatasetImpl.copyBlockFiles(
                blockId, genStamp, metaFile, blockFile, lazyPersistDir, true, smallBufferSize);

        // Lock FsDataSetImpl during onCompleteLazyPersist callback
        dataset.onCompleteLazyPersist(
            bpId, blockId, creationTime, targetFiles, (FsVolumeImpl) targetVolume.getVolume());
        succeeded = true;
      } catch (Exception e) {
        FsDatasetImpl.LOG.warn(
            "LazyWriter failed to async persist RamDisk block pool id: "
                + bpId
                + "block Id: "
                + blockId,
            e);
      } finally {
        if (!succeeded) {
          dataset.onFailLazyPersist(bpId, blockId);
        }
      }
    }
 File addBlock(Block b, File f) throws IOException {
   File blockDir = DatanodeUtil.idToBlockDir(finalizedDir, b.getBlockId());
   if (!blockDir.exists()) {
     if (!blockDir.mkdirs()) {
       throw new IOException("Failed to mkdirs " + blockDir);
     }
   }
   File blockFile = FsDatasetImpl.moveBlockFiles(b, f, blockDir);
   File metaFile = FsDatasetUtil.getMetaFile(blockFile, b.getGenerationStamp());
   dfsUsage.incDfsUsed(b.getNumBytes() + metaFile.length());
   return blockFile;
 }
Exemplo n.º 3
0
 public FsDatasetCache(FsDatasetImpl dataset) {
   this.dataset = dataset;
   this.maxBytes = dataset.datanode.getDnConf().getMaxLockedMemory();
   ThreadFactory workerFactory =
       new ThreadFactoryBuilder()
           .setDaemon(true)
           .setNameFormat("FsDatasetCache-%d-" + dataset.toString())
           .build();
   this.usedBytesCount = new UsedBytesCount();
   this.uncachingExecutor =
       new ThreadPoolExecutor(
           0, 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), workerFactory);
   this.uncachingExecutor.allowCoreThreadTimeOut(true);
 }
Exemplo n.º 4
0
  private void testClose(FsDatasetImpl dataSet, ExtendedBlock[] blocks) throws IOException {
    long newGS = blocks[FINALIZED].getGenerationStamp() + 1;
    dataSet.recoverClose(blocks[FINALIZED], newGS, blocks[FINALIZED].getNumBytes()); // successful
    blocks[FINALIZED].setGenerationStamp(newGS);

    try {
      dataSet.recoverClose(
          blocks[TEMPORARY],
          blocks[TEMPORARY].getGenerationStamp() + 1,
          blocks[TEMPORARY].getNumBytes());
      Assert.fail("Should not have recovered close a temporary replica " + blocks[TEMPORARY]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertTrue(
          e.getMessage().startsWith(ReplicaNotFoundException.UNFINALIZED_AND_NONRBW_REPLICA));
    }

    newGS = blocks[RBW].getGenerationStamp() + 1;
    dataSet.recoverClose(blocks[RBW], newGS, blocks[RBW].getNumBytes());
    blocks[RBW].setGenerationStamp(newGS);

    try {
      dataSet.recoverClose(
          blocks[RWR], blocks[RWR].getGenerationStamp() + 1, blocks[RBW].getNumBytes());
      Assert.fail("Should not have recovered close an RWR replica" + blocks[RWR]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertTrue(
          e.getMessage().startsWith(ReplicaNotFoundException.UNFINALIZED_AND_NONRBW_REPLICA));
    }

    try {
      dataSet.recoverClose(
          blocks[RUR], blocks[RUR].getGenerationStamp() + 1, blocks[RUR].getNumBytes());
      Assert.fail("Should not have recovered close an RUR replica" + blocks[RUR]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertTrue(
          e.getMessage().startsWith(ReplicaNotFoundException.UNFINALIZED_AND_NONRBW_REPLICA));
    }

    try {
      dataSet.recoverClose(
          blocks[NON_EXISTENT],
          blocks[NON_EXISTENT].getGenerationStamp(),
          blocks[NON_EXISTENT].getNumBytes());
      Assert.fail("Should not have recovered close a non-existent replica " + blocks[NON_EXISTENT]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertTrue(e.getMessage().startsWith(ReplicaNotFoundException.NON_EXISTENT_REPLICA));
    }
  }
Exemplo n.º 5
0
  private void testWriteToTemporary(FsDatasetImpl dataSet, ExtendedBlock[] blocks)
      throws IOException {
    try {
      dataSet.createTemporary(StorageType.DEFAULT, blocks[FINALIZED]);
      Assert.fail(
          "Should not have created a temporary replica that was "
              + "finalized "
              + blocks[FINALIZED]);
    } catch (ReplicaAlreadyExistsException e) {
    }

    try {
      dataSet.createTemporary(StorageType.DEFAULT, blocks[TEMPORARY]);
      Assert.fail(
          "Should not have created a replica that had created as"
              + "temporary "
              + blocks[TEMPORARY]);
    } catch (ReplicaAlreadyExistsException e) {
    }

    try {
      dataSet.createTemporary(StorageType.DEFAULT, blocks[RBW]);
      Assert.fail("Should not have created a replica that had created as RBW " + blocks[RBW]);
    } catch (ReplicaAlreadyExistsException e) {
    }

    try {
      dataSet.createTemporary(StorageType.DEFAULT, blocks[RWR]);
      Assert.fail(
          "Should not have created a replica that was waiting to be " + "recovered " + blocks[RWR]);
    } catch (ReplicaAlreadyExistsException e) {
    }

    try {
      dataSet.createTemporary(StorageType.DEFAULT, blocks[RUR]);
      Assert.fail("Should not have created a replica that was under recovery " + blocks[RUR]);
    } catch (ReplicaAlreadyExistsException e) {
    }

    dataSet.createTemporary(StorageType.DEFAULT, blocks[NON_EXISTENT]);

    try {
      dataSet.createTemporary(StorageType.DEFAULT, blocks[NON_EXISTENT]);
      Assert.fail(
          "Should not have created a replica that had already been "
              + "created "
              + blocks[NON_EXISTENT]);
    } catch (Exception e) {
      Assert.assertTrue(e.getMessage().contains(blocks[NON_EXISTENT].getBlockName()));
      Assert.assertTrue(e instanceof ReplicaAlreadyExistsException);
    }

    long newGenStamp = blocks[NON_EXISTENT].getGenerationStamp() * 10;
    blocks[NON_EXISTENT].setGenerationStamp(newGenStamp);
    try {
      ReplicaInPipelineInterface replicaInfo =
          dataSet.createTemporary(StorageType.DEFAULT, blocks[NON_EXISTENT]).getReplica();
      Assert.assertTrue(replicaInfo.getGenerationStamp() == newGenStamp);
      Assert.assertTrue(replicaInfo.getBlockId() == blocks[NON_EXISTENT].getBlockId());
    } catch (ReplicaAlreadyExistsException e) {
      Assert.fail(
          "createRbw() Should have removed the block with the older "
              + "genstamp and replaced it with the newer one: "
              + blocks[NON_EXISTENT]);
    }
  }
Exemplo n.º 6
0
  private void testWriteToRbw(FsDatasetImpl dataSet, ExtendedBlock[] blocks) throws IOException {
    try {
      dataSet.recoverRbw(
          blocks[FINALIZED],
          blocks[FINALIZED].getGenerationStamp() + 1,
          0L,
          blocks[FINALIZED].getNumBytes());
      Assert.fail("Should not have recovered a finalized replica " + blocks[FINALIZED]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertTrue(e.getMessage().startsWith(ReplicaNotFoundException.NON_RBW_REPLICA));
    }

    try {
      dataSet.createRbw(StorageType.DEFAULT, blocks[FINALIZED], false);
      Assert.fail(
          "Should not have created a replica that's already " + "finalized " + blocks[FINALIZED]);
    } catch (ReplicaAlreadyExistsException e) {
    }

    try {
      dataSet.recoverRbw(
          blocks[TEMPORARY],
          blocks[TEMPORARY].getGenerationStamp() + 1,
          0L,
          blocks[TEMPORARY].getNumBytes());
      Assert.fail("Should not have recovered a temporary replica " + blocks[TEMPORARY]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertTrue(e.getMessage().startsWith(ReplicaNotFoundException.NON_RBW_REPLICA));
    }

    try {
      dataSet.createRbw(StorageType.DEFAULT, blocks[TEMPORARY], false);
      Assert.fail(
          "Should not have created a replica that had created as "
              + "temporary "
              + blocks[TEMPORARY]);
    } catch (ReplicaAlreadyExistsException e) {
    }

    dataSet.recoverRbw(
        blocks[RBW],
        blocks[RBW].getGenerationStamp() + 1,
        0L,
        blocks[RBW].getNumBytes()); // expect to be successful

    try {
      dataSet.createRbw(StorageType.DEFAULT, blocks[RBW], false);
      Assert.fail("Should not have created a replica that had created as RBW " + blocks[RBW]);
    } catch (ReplicaAlreadyExistsException e) {
    }

    try {
      dataSet.recoverRbw(
          blocks[RWR], blocks[RWR].getGenerationStamp() + 1, 0L, blocks[RWR].getNumBytes());
      Assert.fail("Should not have recovered a RWR replica " + blocks[RWR]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertTrue(e.getMessage().startsWith(ReplicaNotFoundException.NON_RBW_REPLICA));
    }

    try {
      dataSet.createRbw(StorageType.DEFAULT, blocks[RWR], false);
      Assert.fail(
          "Should not have created a replica that was waiting to be " + "recovered " + blocks[RWR]);
    } catch (ReplicaAlreadyExistsException e) {
    }

    try {
      dataSet.recoverRbw(
          blocks[RUR], blocks[RUR].getGenerationStamp() + 1, 0L, blocks[RUR].getNumBytes());
      Assert.fail("Should not have recovered a RUR replica " + blocks[RUR]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertTrue(e.getMessage().startsWith(ReplicaNotFoundException.NON_RBW_REPLICA));
    }

    try {
      dataSet.createRbw(StorageType.DEFAULT, blocks[RUR], false);
      Assert.fail("Should not have created a replica that was under recovery " + blocks[RUR]);
    } catch (ReplicaAlreadyExistsException e) {
    }

    try {
      dataSet.recoverRbw(
          blocks[NON_EXISTENT],
          blocks[NON_EXISTENT].getGenerationStamp() + 1,
          0L,
          blocks[NON_EXISTENT].getNumBytes());
      Assert.fail("Cannot recover a non-existent replica " + blocks[NON_EXISTENT]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertTrue(e.getMessage().contains(ReplicaNotFoundException.NON_EXISTENT_REPLICA));
    }

    dataSet.createRbw(StorageType.DEFAULT, blocks[NON_EXISTENT], false);
  }
Exemplo n.º 7
0
  private void testAppend(String bpid, FsDatasetImpl dataSet, ExtendedBlock[] blocks)
      throws IOException {
    long newGS = blocks[FINALIZED].getGenerationStamp() + 1;
    final FsVolumeImpl v =
        (FsVolumeImpl) dataSet.volumeMap.get(bpid, blocks[FINALIZED].getLocalBlock()).getVolume();
    long available = v.getCapacity() - v.getDfsUsed();
    long expectedLen = blocks[FINALIZED].getNumBytes();
    try {
      v.decDfsUsed(bpid, -available);
      blocks[FINALIZED].setNumBytes(expectedLen + 100);
      dataSet.append(blocks[FINALIZED], newGS, expectedLen);
      Assert.fail("Should not have space to append to an RWR replica" + blocks[RWR]);
    } catch (DiskOutOfSpaceException e) {
      Assert.assertTrue(e.getMessage().startsWith("Insufficient space for appending to "));
    }
    v.decDfsUsed(bpid, available);
    blocks[FINALIZED].setNumBytes(expectedLen);

    newGS = blocks[RBW].getGenerationStamp() + 1;
    dataSet.append(blocks[FINALIZED], newGS, blocks[FINALIZED].getNumBytes()); // successful
    blocks[FINALIZED].setGenerationStamp(newGS);

    try {
      dataSet.append(
          blocks[TEMPORARY],
          blocks[TEMPORARY].getGenerationStamp() + 1,
          blocks[TEMPORARY].getNumBytes());
      Assert.fail("Should not have appended to a temporary replica " + blocks[TEMPORARY]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertEquals(
          ReplicaNotFoundException.UNFINALIZED_REPLICA + blocks[TEMPORARY], e.getMessage());
    }

    try {
      dataSet.append(blocks[RBW], blocks[RBW].getGenerationStamp() + 1, blocks[RBW].getNumBytes());
      Assert.fail("Should not have appended to an RBW replica" + blocks[RBW]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertEquals(
          ReplicaNotFoundException.UNFINALIZED_REPLICA + blocks[RBW], e.getMessage());
    }

    try {
      dataSet.append(blocks[RWR], blocks[RWR].getGenerationStamp() + 1, blocks[RBW].getNumBytes());
      Assert.fail("Should not have appended to an RWR replica" + blocks[RWR]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertEquals(
          ReplicaNotFoundException.UNFINALIZED_REPLICA + blocks[RWR], e.getMessage());
    }

    try {
      dataSet.append(blocks[RUR], blocks[RUR].getGenerationStamp() + 1, blocks[RUR].getNumBytes());
      Assert.fail("Should not have appended to an RUR replica" + blocks[RUR]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertEquals(
          ReplicaNotFoundException.UNFINALIZED_REPLICA + blocks[RUR], e.getMessage());
    }

    try {
      dataSet.append(
          blocks[NON_EXISTENT],
          blocks[NON_EXISTENT].getGenerationStamp(),
          blocks[NON_EXISTENT].getNumBytes());
      Assert.fail("Should not have appended to a non-existent replica " + blocks[NON_EXISTENT]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertEquals(
          ReplicaNotFoundException.NON_EXISTENT_REPLICA + blocks[NON_EXISTENT], e.getMessage());
    }

    newGS = blocks[FINALIZED].getGenerationStamp() + 1;
    dataSet.recoverAppend(blocks[FINALIZED], newGS, blocks[FINALIZED].getNumBytes()); // successful
    blocks[FINALIZED].setGenerationStamp(newGS);

    try {
      dataSet.recoverAppend(
          blocks[TEMPORARY],
          blocks[TEMPORARY].getGenerationStamp() + 1,
          blocks[TEMPORARY].getNumBytes());
      Assert.fail("Should not have appended to a temporary replica " + blocks[TEMPORARY]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertTrue(
          e.getMessage().startsWith(ReplicaNotFoundException.UNFINALIZED_AND_NONRBW_REPLICA));
    }

    newGS = blocks[RBW].getGenerationStamp() + 1;
    dataSet.recoverAppend(blocks[RBW], newGS, blocks[RBW].getNumBytes());
    blocks[RBW].setGenerationStamp(newGS);

    try {
      dataSet.recoverAppend(
          blocks[RWR], blocks[RWR].getGenerationStamp() + 1, blocks[RBW].getNumBytes());
      Assert.fail("Should not have appended to an RWR replica" + blocks[RWR]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertTrue(
          e.getMessage().startsWith(ReplicaNotFoundException.UNFINALIZED_AND_NONRBW_REPLICA));
    }

    try {
      dataSet.recoverAppend(
          blocks[RUR], blocks[RUR].getGenerationStamp() + 1, blocks[RUR].getNumBytes());
      Assert.fail("Should not have appended to an RUR replica" + blocks[RUR]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertTrue(
          e.getMessage().startsWith(ReplicaNotFoundException.UNFINALIZED_AND_NONRBW_REPLICA));
    }

    try {
      dataSet.recoverAppend(
          blocks[NON_EXISTENT],
          blocks[NON_EXISTENT].getGenerationStamp(),
          blocks[NON_EXISTENT].getNumBytes());
      Assert.fail("Should not have appended to a non-existent replica " + blocks[NON_EXISTENT]);
    } catch (ReplicaNotFoundException e) {
      Assert.assertTrue(e.getMessage().startsWith(ReplicaNotFoundException.NON_EXISTENT_REPLICA));
    }
  }
  /** Test for {@link FsDatasetImpl#updateReplicaUnderRecovery(ExtendedBlock, long, long)} */
  @Test
  public void testUpdateReplicaUnderRecovery() throws IOException {
    MiniDFSCluster cluster = null;

    try {
      cluster = new MiniDFSCluster.Builder(conf).numDataNodes(3).build();
      cluster.waitActive();
      String bpid = cluster.getNamesystem().getBlockPoolId();

      // create a file
      DistributedFileSystem dfs = (DistributedFileSystem) cluster.getFileSystem();
      String filestr = "/foo";
      Path filepath = new Path(filestr);
      DFSTestUtil.createFile(dfs, filepath, 1024L, (short) 3, 0L);

      // get block info
      final LocatedBlock locatedblock =
          getLastLocatedBlock(DFSClientAdapter.getDFSClient(dfs).getNamenode(), filestr);
      final DatanodeInfo[] datanodeinfo = locatedblock.getLocations();
      Assert.assertTrue(datanodeinfo.length > 0);

      // get DataNode and FSDataset objects
      final DataNode datanode = cluster.getDataNode(datanodeinfo[0].getIpcPort());
      Assert.assertTrue(datanode != null);

      // initReplicaRecovery
      final ExtendedBlock b = locatedblock.getBlock();
      final long recoveryid = b.getGenerationStamp() + 1;
      final long newlength = b.getNumBytes() - 1;
      final FsDatasetSpi<?> fsdataset = DataNodeTestUtils.getFSDataset(datanode);
      final ReplicaRecoveryInfo rri =
          fsdataset.initReplicaRecovery(new RecoveringBlock(b, null, recoveryid));

      // check replica
      final ReplicaInfo replica =
          FsDatasetTestUtil.fetchReplicaInfo(fsdataset, bpid, b.getBlockId());
      Assert.assertEquals(ReplicaState.RUR, replica.getState());

      // check meta data before update
      FsDatasetImpl.checkReplicaFiles(replica);

      // case "THIS IS NOT SUPPOSED TO HAPPEN"
      // with (block length) != (stored replica's on disk length).
      {
        // create a block with same id and gs but different length.
        final ExtendedBlock tmp =
            new ExtendedBlock(
                b.getBlockPoolId(),
                rri.getBlockId(),
                rri.getNumBytes() - 1,
                rri.getGenerationStamp());
        try {
          // update should fail
          fsdataset.updateReplicaUnderRecovery(tmp, recoveryid, newlength);
          Assert.fail();
        } catch (IOException ioe) {
          System.out.println("GOOD: getting " + ioe);
        }
      }

      // update
      final String storageID =
          fsdataset.updateReplicaUnderRecovery(
              new ExtendedBlock(b.getBlockPoolId(), rri), recoveryid, newlength);
      assertTrue(storageID != null);

    } finally {
      if (cluster != null) cluster.shutdown();
    }
  }
  /** Test {@link FsDatasetImpl#initReplicaRecovery(String, ReplicaMap, Block, long)} */
  @Test
  public void testInitReplicaRecovery() throws IOException {
    final long firstblockid = 10000L;
    final long gs = 7777L;
    final long length = 22L;
    final ReplicaMap map = new ReplicaMap(this);
    String bpid = "BP-TEST";
    final Block[] blocks = new Block[5];
    for (int i = 0; i < blocks.length; i++) {
      blocks[i] = new Block(firstblockid + i, length, gs);
      map.add(bpid, createReplicaInfo(blocks[i]));
    }

    {
      // normal case
      final Block b = blocks[0];
      final ReplicaInfo originalInfo = map.get(bpid, b);

      final long recoveryid = gs + 1;
      final ReplicaRecoveryInfo recoveryInfo =
          FsDatasetImpl.initReplicaRecovery(bpid, map, blocks[0], recoveryid);
      assertEquals(originalInfo, recoveryInfo);

      final ReplicaUnderRecovery updatedInfo = (ReplicaUnderRecovery) map.get(bpid, b);
      Assert.assertEquals(originalInfo.getBlockId(), updatedInfo.getBlockId());
      Assert.assertEquals(recoveryid, updatedInfo.getRecoveryID());

      // recover one more time
      final long recoveryid2 = gs + 2;
      final ReplicaRecoveryInfo recoveryInfo2 =
          FsDatasetImpl.initReplicaRecovery(bpid, map, blocks[0], recoveryid2);
      assertEquals(originalInfo, recoveryInfo2);

      final ReplicaUnderRecovery updatedInfo2 = (ReplicaUnderRecovery) map.get(bpid, b);
      Assert.assertEquals(originalInfo.getBlockId(), updatedInfo2.getBlockId());
      Assert.assertEquals(recoveryid2, updatedInfo2.getRecoveryID());

      // case RecoveryInProgressException
      try {
        FsDatasetImpl.initReplicaRecovery(bpid, map, b, recoveryid);
        Assert.fail();
      } catch (RecoveryInProgressException ripe) {
        System.out.println("GOOD: getting " + ripe);
      }
    }

    { // BlockRecoveryFI_01: replica not found
      final long recoveryid = gs + 1;
      final Block b = new Block(firstblockid - 1, length, gs);
      ReplicaRecoveryInfo r = FsDatasetImpl.initReplicaRecovery(bpid, map, b, recoveryid);
      Assert.assertNull("Data-node should not have this replica.", r);
    }

    { // BlockRecoveryFI_02: "THIS IS NOT SUPPOSED TO HAPPEN" with recovery id < gs
      final long recoveryid = gs - 1;
      final Block b = new Block(firstblockid + 1, length, gs);
      try {
        FsDatasetImpl.initReplicaRecovery(bpid, map, b, recoveryid);
        Assert.fail();
      } catch (IOException ioe) {
        System.out.println("GOOD: getting " + ioe);
      }
    }

    // BlockRecoveryFI_03: Replica's gs is less than the block's gs
    {
      final long recoveryid = gs + 1;
      final Block b = new Block(firstblockid, length, gs + 1);
      try {
        FsDatasetImpl.initReplicaRecovery(bpid, map, b, recoveryid);
        fail(
            "InitReplicaRecovery should fail because replica's "
                + "gs is less than the block's gs");
      } catch (IOException e) {
        e.getMessage()
            .startsWith("replica.getGenerationStamp() < block.getGenerationStamp(), block=");
      }
    }
  }