Package org.apache.hadoop.raid

Source Code of org.apache.hadoop.raid.TestRetryTaskEncoding$TestEncodingHandler

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

import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.BlockMissingException;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.TestRaidDfs;
import org.apache.hadoop.hdfs.util.InjectionEvent;
import org.apache.hadoop.mapred.Reporter;
import org.apache.hadoop.raid.DistRaid.DistRaidMapper;
import org.apache.hadoop.raid.DistRaid.EncodingCandidate;
import org.apache.hadoop.raid.protocol.PolicyInfo;
import org.apache.hadoop.util.InjectionEventI;
import org.apache.hadoop.util.InjectionHandler;

public class TestRetryTaskEncoding extends TestMultiTasksEncoding {
  final static Log LOG =
      LogFactory.getLog("org.apache.hadoop.raid.TestRetryTaskEncoding");
 
  class TestEncodingHandler extends InjectionHandler {
    Map<InjectionEventI, AtomicInteger> events =
        new HashMap<InjectionEventI, AtomicInteger>();
    Random rand = new Random();
    HashMap<InjectionEventI, Double> specialFailProbs;
    HashMap<OutputStream, Integer> blockMissingMap;
    double defaultFailProb;
    public Path lockFile;
    public Path parityFile;
    public Path finalTmpPath;
    public Long numStripes;
    public boolean throwBlockMissingException = false;
    private AtomicInteger blockMissingCount = new AtomicInteger(0);
   
    public TestEncodingHandler(double defaultProb,
        HashMap<InjectionEventI, Double> specialProbs,
        boolean newThrowBlockMissingException) {
      defaultFailProb = defaultProb;
      specialFailProbs = specialProbs;
      throwBlockMissingException = newThrowBlockMissingException;
      for (InjectionEventI event: new InjectionEventI[]{
          InjectionEvent.RAID_ENCODING_PARTIAL_STRIPE_ENCODED,
          InjectionEvent.RAID_ENCODING_FAILURE_PARTIAL_PARITY_SIZE_MISMATCH,
          InjectionEvent.RAID_ENCODING_FAILURE_BLOCK_MISSING,
          InjectionEvent.RAID_ENCODING_FAILURE_PUT_CHECKSUM,
          InjectionEvent.RAID_ENCODING_FAILURE_RENAME_FILE,
          InjectionEvent.RAID_ENCODING_FAILURE_CONCAT_FILE,
          InjectionEvent.RAID_ENCODING_FAILURE_GET_SRC_STRIPES,
          InjectionEvent.RAID_ENCODING_FAILURE_PUT_STRIPE,
      }) {
        events.put(event, new AtomicInteger(0));
      }
      blockMissingMap = new HashMap<OutputStream, Integer>();
    }

    @Override
    public void _processEventIO(InjectionEventI event, Object... args)
        throws IOException {
      if (!events.containsKey(event)) {
        return;
      }
      int count = events.get(event).incrementAndGet();
      if (event == InjectionEvent.RAID_ENCODING_FAILURE_PUT_STRIPE) {
        parityFile = (Path)args[0];
        finalTmpPath = (Path)args[1];
        assertTrue("parity file should exist", fileSys.exists(parityFile));
        assertFalse("finalTmpPath should not exist", fileSys.exists(finalTmpPath));
      }
      if (event ==
          InjectionEvent.RAID_ENCODING_FAILURE_PARTIAL_PARITY_SIZE_MISMATCH ||
          event == InjectionEvent.RAID_ENCODING_PARTIAL_STRIPE_ENCODED) {
        return;
      }
      Double failProb = null;
      // Only use the specialFailProb for the first time
      if (specialFailProbs != null && count == 1) {
        failProb = specialFailProbs.get(event);
      }
      if (failProb == null) {
        failProb = defaultFailProb;
      }
      if (rand.nextDouble() < failProb) {
        if (event == InjectionEvent.RAID_ENCODING_FAILURE_BLOCK_MISSING) {
          if (throwBlockMissingException && events.get(
              InjectionEvent.RAID_ENCODING_PARTIAL_STRIPE_ENCODED).get() == 0 &&
              args[0] instanceof FSDataOutputStream) {
            FSDataOutputStream stream = (FSDataOutputStream)args[0];
            // Skip the first stripe
            if (stream.getPos() == 0) {
              return;
            }
            if (this.blockMissingCount.incrementAndGet() > 2) {
              return;
            }
            Integer errorCount = 0;
            synchronized(blockMissingMap) {
              errorCount = blockMissingMap.get(stream);
              if (errorCount == null) {
                errorCount = 1;
              } else {
                errorCount++;
              }
              blockMissingMap.put(stream, errorCount);
            }
            if (errorCount <= 2) {
              throw new BlockMissingException(stream.toString(),
                  event.toString(), stream.getPos());
            }
          }
        } else {
          throw new IOException(event.toString());
        }
      }
    }
  }

  public class EncodingThread extends Thread {
    public PolicyInfo policyInfo = null;
    public boolean succeed = false;
    public int retryNum = 0;
    public EncodingCandidate encodingCandidate = null;
    public IOException exp = null;
    public int threadNum = 0;
    public Configuration encodingConf = null;
   
    public EncodingThread(PolicyInfo pi, EncodingCandidate newEC,
        int newRetryNum, int newThreadNum, Configuration newConf) {
      policyInfo = pi;
      encodingCandidate = newEC;
      retryNum = newRetryNum;
      threadNum = newThreadNum;
      encodingConf = newConf;
    }
   
    public void run() {
      try {
        succeed = DistRaidMapper.doRaid(retryNum, encodingCandidate.toString(),
            encodingConf, policyInfo, new RaidNode.Statistics(), Reporter.NULL);
        LOG.info("Finished Thread " + threadNum + " " + succeed);
      } catch (IOException ioe) {
        exp = ioe;
      }
    }
  }
 
  // Run one round of encoding job
  // Each task could have multiple instances to simulate race conditions
  public boolean runEncodingTasks(Configuration conf, Codec codec,
      FileStatus stat, PolicyInfo info, int retryNum) throws Exception {
    String jobId = RaidNode.getJobID(conf);
    LOG.info("Set local raid job id: " + jobId);
    List<EncodingCandidate> lec =
        RaidNode.splitPaths(conf, codec, stat);
    EncodingThread[] threads = new EncodingThread[lec.size()];
    boolean succeed = false;
    for (int i = 0; i < lec.size(); i++) {
      threads[i] = new EncodingThread(info, lec.get(i), retryNum, i, conf);
    }
    for (EncodingThread et: threads) {
      et.start();
    }
    for (EncodingThread et: threads) {
      et.join();
      succeed |= et.succeed;
      if (et.exp != null) {
        LOG.warn("Exception from Thread " + et.threadNum +
            et.encodingCandidate + " :" + et.exp.getMessage());
      }
    }
    return succeed;
  }
 
  public void testBlockMissingExceptionDuringEncoding() throws Exception {
    LOG.info("Test testBlockMissingExceptionDuringEncoding started.");
    createClusters(false);
    Configuration newConf = new Configuration(conf);
    // Make sure only one thread is running
    newConf.setLong(RaidNode.RAID_ENCODING_STRIPES_KEY, 1000);
    newConf.setLong("raid.encoder.bufsize", 4096);
    RaidNode.createChecksumStore(newConf, true);
    Path raidDir = new Path("/raidtest/1");
    HashMap<Codec, Long[]> fileCRCs = new HashMap<Codec, Long[]>();
    HashMap<Codec, Path> filePaths = new HashMap<Codec, Path>();
    PolicyInfo info = new PolicyInfo();
    info.setProperty("targetReplication", Integer.toString(targetReplication));
    info.setProperty("metaReplication", Integer.toString(metaReplication));
    try {
      createTestFiles(raidDir, filePaths, fileCRCs, null);
      LOG.info("Test testBlockMissingExceptionDuringEncoding created test files");
      // create the InjectionHandler
      for (Codec codec: Codec.getCodecs()) {
        Path filePath = filePaths.get(codec);
        FileStatus stat = fileSys.getFileStatus(filePath);
        info.setCodecId(codec.id);
        boolean succeed = false;
        TestEncodingHandler h = new TestEncodingHandler(0.5,
            null, true);
        InjectionHandler.set(h);
        succeed = runEncodingTasks(newConf, codec, stat, info, 100);
        assertTrue("Block missing exceptions should be more than 0",
            h.events.get(
                InjectionEvent.RAID_ENCODING_FAILURE_BLOCK_MISSING).get() > 0);
        assertEquals("No Encoding failure of partial parity size mismatch", 0,
            h.events.get(
                InjectionEvent.RAID_ENCODING_FAILURE_PARTIAL_PARITY_SIZE_MISMATCH
                ).get());
        assertTrue("We should succeed", succeed);
        if (!codec.isDirRaid) {
          TestRaidDfs.waitForFileRaided(LOG, fileSys, filePath,
              new Path(codec.parityDirectory,
                  RaidNode.makeRelative(filePath.getParent())),
              targetReplication);
        } else {
          TestRaidDfs.waitForDirRaided(LOG, fileSys, filePath,
              new Path(codec.parityDirectory,
                  RaidNode.makeRelative(raidDir)),
                  targetReplication);
        }
        TestRaidDfs.waitForReplicasReduction(fileSys, filePath,
            targetReplication);
      }
      verifyCorrectness(raidDir, fileCRCs, null);
      LOG.info("Test testBlockMissingExceptionDuringEncoding successful.");
    } catch (Exception e) {
      LOG.info("testBlockMissingExceptionDuringEncoding Exception ", e);
      throw e;
    } finally {
      stopClusters();
    }
    LOG.info("Test testBlockMissingExceptionDuringEncoding completed.");
  }
 
  public void testRetryTask() throws Exception {
    LOG.info("Test testRetryTask started.");
    createClusters(false);
    Configuration newConf = new Configuration(conf);
    RaidNode.createChecksumStore(newConf, true);
    Path raidDir = new Path("/raidtest/1");
    HashMap<Codec, Long[]> fileCRCs = new HashMap<Codec, Long[]>();
    HashMap<Codec, Path> filePaths = new HashMap<Codec, Path>();
    HashMap<InjectionEventI, Double> specialFailProbs =
        new HashMap<InjectionEventI, Double>();
    PolicyInfo info = new PolicyInfo();
    info.setProperty("targetReplication", Integer.toString(targetReplication));
    info.setProperty("metaReplication", Integer.toString(metaReplication));
    try {
      createTestFiles(raidDir, filePaths, fileCRCs, null);
      LOG.info("Test testRetryTask created test files");
      for (Codec codec: Codec.getCodecs()) {
        Path filePath = filePaths.get(codec);
        FileStatus stat = fileSys.getFileStatus(filePath);
        info.setCodecId(codec.id);
       
        LOG.info("Codec: " + codec + ", Path: " + filePath +
                 " Sync every task to the finalize stage, " +
                 "all partial parity files are generated");
        specialFailProbs.clear();
        specialFailProbs.put(
            InjectionEvent.RAID_ENCODING_FAILURE_CONCAT_FILE, 1.0);
        specialFailProbs.put(
            InjectionEvent.RAID_ENCODING_FAILURE_GET_SRC_STRIPES, 1.0);
        specialFailProbs.put(
            InjectionEvent.RAID_ENCODING_FAILURE_PUT_STRIPE, 1.0);
        TestEncodingHandler h = new TestEncodingHandler(0.0,
            specialFailProbs, false);
        InjectionHandler.set(h);
        assertEquals("Should succeed", true,
            runEncodingTasks(newConf, codec, stat, info, 1000));
        assertEquals("Only did two concats, one failed, one succeeded ", 2,
            h.events.get(
                InjectionEvent.RAID_ENCODING_FAILURE_CONCAT_FILE).get());
        if (codec.isDirRaid) {
          assertEquals("Only did two getSrcStripes, one failed, two succeeded",
              2, h.events.get(
                  InjectionEvent.RAID_ENCODING_FAILURE_GET_SRC_STRIPES).get());
          assertEquals("Only did two putStripes, one failed, one succeeded", 2,
              h.events.get(InjectionEvent.RAID_ENCODING_FAILURE_PUT_STRIPE).get());
        }
        if (!codec.isDirRaid) {
          TestRaidDfs.waitForFileRaided(LOG, fileSys, filePath,
              new Path(codec.parityDirectory,
                  RaidNode.makeRelative(filePath.getParent())),
              targetReplication);
        } else {
          TestRaidDfs.waitForDirRaided(LOG, fileSys, filePath,
              new Path(codec.parityDirectory,
                  RaidNode.makeRelative(raidDir)),
                  targetReplication);
        }
        TestRaidDfs.waitForReplicasReduction(fileSys, filePath,
            targetReplication);
      }
      verifyCorrectness(raidDir, fileCRCs, null);
      LOG.info("Test testRetryTask successful.");
    } catch (Exception e) {
      LOG.info("testRetryTask Exception ", e);
      throw e;
    } finally {
      stopClusters();
     
    }
    LOG.info("Test testRetryTask completed.");
  }
 
  public void testLargeFailureRateEncoding() throws Exception {
    LOG.info("Test testLargeFailureRateEncoding started.");
    createClusters(false);
    Configuration newConf = new Configuration(conf);
    RaidNode.createChecksumStore(newConf, true);
    Path raidDir = new Path("/raidtest/1");
    HashMap<Codec, Long[]> fileCRCs = new HashMap<Codec, Long[]>();
    HashMap<Codec, Path> filePaths = new HashMap<Codec, Path>();
    PolicyInfo info = new PolicyInfo();
    info.setProperty("targetReplication", Integer.toString(targetReplication));
    info.setProperty("metaReplication", Integer.toString(metaReplication));
    try {
      createTestFiles(raidDir, filePaths, fileCRCs, null);
      LOG.info("Test testLargeFailureRateEncoding created test files");
      // create the InjectionHandler
      for (Codec codec: Codec.getCodecs()) {
        Path filePath = filePaths.get(codec);
        FileStatus stat = fileSys.getFileStatus(filePath);
        info.setCodecId(codec.id);
        boolean succeed = false;
        TestEncodingHandler h = new TestEncodingHandler(0.5, null, false);
        InjectionHandler.set(h);
        succeed = runEncodingTasks(newConf, codec, stat, info, 100);
        assertTrue("We should succeed", succeed);
        if (!codec.isDirRaid) {
          TestRaidDfs.waitForFileRaided(LOG, fileSys, filePath,
              new Path(codec.parityDirectory,
                  RaidNode.makeRelative(filePath.getParent())),
              targetReplication);
        } else {
          TestRaidDfs.waitForDirRaided(LOG, fileSys, filePath,
              new Path(codec.parityDirectory,
                  RaidNode.makeRelative(raidDir)),
                  targetReplication);
        }
        TestRaidDfs.waitForReplicasReduction(fileSys, filePath,
            targetReplication);
      }
      verifyCorrectness(raidDir, fileCRCs, null);
      LOG.info("Test testLargeFailureRateEncoding successful.");
    } catch (Exception e) {
      LOG.info("testLargeFailureRateEncoding Exception ", e);
      throw e;
    } finally {
      stopClusters();
     
    }
    LOG.info("Test testLargeFailureRateEncoding completed.");
  }
 
  @Override
  public void testFileListPolicy() throws Exception {
  }
}
TOP

Related Classes of org.apache.hadoop.raid.TestRetryTaskEncoding$TestEncodingHandler

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.