Package com.dp.nebula.wormhole.engine.core

Source Code of com.dp.nebula.wormhole.engine.core.WriterManager$WritePrepareCallable

package com.dp.nebula.wormhole.engine.core;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.dp.nebula.wormhole.common.AbstractPlugin;
import com.dp.nebula.wormhole.common.JobStatus;
import com.dp.nebula.wormhole.common.LineExchangerFactory;
import com.dp.nebula.wormhole.common.config.JobPluginConf;
import com.dp.nebula.wormhole.common.interfaces.IParam;
import com.dp.nebula.wormhole.common.interfaces.IPluginMonitor;
import com.dp.nebula.wormhole.common.interfaces.ISplitter;
import com.dp.nebula.wormhole.common.interfaces.IWriterPeriphery;
import com.dp.nebula.wormhole.engine.config.PluginConfParamKey;
import com.dp.nebula.wormhole.engine.monitor.MonitorManager;
import com.dp.nebula.wormhole.engine.storage.StorageManager;
import com.dp.nebula.wormhole.engine.utils.JarLoader;
import com.dp.nebula.wormhole.engine.utils.ReflectionUtil;

final class WriterManager extends AbstractPluginManager {

  private static final Log s_logger = LogFactory.getLog(WriterManager.class);
  private static final String JOB_PARAM_FAILED_LINES_THRESHOLD = "failedLinesThreshold";
  private static final int TIME_OUT = 10 * 60 * 60;// 60 * ten minutes

  private Map<String, ExecutorService> writerPoolMap;
  private StorageManager storageManager;
  private MonitorManager monitorManager;
  private Map<String, IWriterPeriphery> writerPeripheryMap;
  private Map<String, IParam> writerToJobParamsMap;
  private Map<String, List<Future<Integer>>> writerToResultsMap;

  private static WriterManager wmInstance;

  private WriterManager(StorageManager storageManager,
      MonitorManager monitorManager, int writerNum) {
    super();
    writerPoolMap = new HashMap<String, ExecutorService>(writerNum);
    writerPeripheryMap = new HashMap<String, IWriterPeriphery>(writerNum);
    writerToJobParamsMap = new HashMap<String, IParam>(writerNum);
    writerToResultsMap = new HashMap<String, List<Future<Integer>>>(
        writerNum);
    this.storageManager = storageManager;
    this.monitorManager = monitorManager;
  }

  public static WriterManager getInstance(StorageManager storageManager,
      MonitorManager monitorManager, int writerNum) {
    if (wmInstance == null) {
      wmInstance = new WriterManager(storageManager, monitorManager,
          writerNum);
    }

    return wmInstance;
  }

  public int getFailedLinesThreshold(String writerID) {
    IParam jobParam = writerToJobParamsMap.get(writerID);
    if (jobParam == null) {
      return 0;
    }
    return jobParam.getIntValue(JOB_PARAM_FAILED_LINES_THRESHOLD, 0);
  }

  public void run(List<JobPluginConf> jobPluginList,
      Map<String, IParam> pluginParamsMap) throws TimeoutException,
      ExecutionException, InterruptedException {
    for (JobPluginConf jobPluginConf : jobPluginList) {

      String writerID = jobPluginConf.getId();
      IParam jobParams = jobPluginConf.getPluginParam();
      writerToJobParamsMap.put(writerID, jobParams);
      IParam pluginParams = pluginParamsMap.get(jobPluginConf
          .getPluginName());
      jobParams.putValue(AbstractPlugin.PLUGINID, writerID);
      String writerPath = pluginParams.getValue(PluginConfParamKey.PATH);
      String writerPeripheryClassName = pluginParams
          .getValue(PluginConfParamKey.PERIPHERY_CLASS_NAME);
      IWriterPeriphery writerPeriphery = null;
      if (StringUtils.isEmpty(writerPeripheryClassName)) {
        writerPeriphery = new DefaultWriterPeriphery();
      } else {
        writerPeriphery = ReflectionUtil
            .createInstanceByDefaultConstructor(
                writerPeripheryClassName,
                IWriterPeriphery.class,
                JarLoader.getInstance(writerPath));
      }
      writerPeripheryMap.put(writerID, writerPeriphery);

      String splitterClassName = pluginParams
          .getValue(PluginConfParamKey.SPLITTER_CLASS_NAME);
      ISplitter splitter = null;
      if (StringUtils.isEmpty(splitterClassName)) {
        splitter = new DefaultSplitter();
      } else {
        splitter = ReflectionUtil.createInstanceByDefaultConstructor(
            splitterClassName, ISplitter.class,
            JarLoader.getInstance(writerPath));
      }

      WritePrepareCallable<List<IParam>> writerCallable = new WritePrepareCallable<List<IParam>>();
      writerCallable.writerPeriphery = writerPeriphery;
      writerCallable.jobParams = jobParams;
      runWithTimeout(new FutureTask<List<IParam>>(writerCallable));
      splitter.init(jobParams);

      WriteSplitCallable<List<IParam>> splitCallable = new WriteSplitCallable<List<IParam>>();
      splitCallable.splitter = splitter;
      List<IParam> splittedParam = (List<IParam>) runWithTimeout(new FutureTask<List<IParam>>(
          splitCallable));

      int concurrency = getConcurrency(jobParams, pluginParams);
      String writeClassName = pluginParams
          .getValue(PluginConfParamKey.PLUGIN_CLASS_NAME);
      ExecutorService writerPool = createThreadPool(concurrency);
      writerPoolMap.put(writerID, writerPool);

      List<Future<Integer>> resultList = new ArrayList<Future<Integer>>();
      for (IParam p : splittedParam) {
        IPluginMonitor pm = monitorManager.newWriterMonitor(writerID);
        WriterThread rt = WriterThread.getInstance(LineExchangerFactory
            .createNewLineReceiver(
                storageManager.getStorageForWriter(writerID),
                null), p, writeClassName, writerPath, pm);

        Future<Integer> r = writerPool.submit(rt);
        resultList.add(r);
      }
      writerToResultsMap.put(writerID, resultList);
      s_logger.info("Writer: " + writerID + " start to write data");
      // Do not accept any new threads
      writerPool.shutdown();
    }
  }

  public void killAll() {
    for (String writerID : writerPoolMap.keySet()) {
      ExecutorService es = writerPoolMap.get(writerID);
      es.shutdownNow();
    }
  }

  class WritePrepareCallable<V> implements Callable<V> {
    IWriterPeriphery writerPeriphery;
    IParam jobParams;

    @Override
    public V call() throws Exception {
      writerPeriphery.prepare(jobParams, monitorManager);
      return null;
    }
  }

  class WriteSplitCallable<V> implements Callable<V> {
    ISplitter splitter;

    @SuppressWarnings("unchecked")
    @Override
    public V call() throws Exception {
      List<IParam> splittedParam = splitter.split();
      return (V) splittedParam;

    }
  }

  public static List<IParam> runWithTimeout(FutureTask<List<IParam>> task)
      throws TimeoutException, ExecutionException, InterruptedException {
    task.run();
    return task.get(TIME_OUT, TimeUnit.SECONDS);
  }

  public boolean terminate(boolean writerConsistency) {
    boolean result = true;
    Set<String> failedIDs = getFailedWriterID();
    if (writerConsistency && failedIDs.size() > 0) {
      for (String writerID : writerPoolMap.keySet()) {
        ExecutorService es = writerPoolMap.get(writerID);
        es.shutdownNow();
        terminate(writerID);
      }
      writerPoolMap.clear();
      return true;
    }
    Collection<String> needToRemoveWriterIDList = new ArrayList<String>(
        writerPoolMap.size());
    for (String writerID : writerPoolMap.keySet()) {
      ExecutorService es = writerPoolMap.get(writerID);
      if (es.isTerminated()) {
        terminate(writerID);
        needToRemoveWriterIDList.add(writerID);
      } else {
        result = false;
      }
    }

    // remove terminated writers from writerPoolMap
    for (String writerID : needToRemoveWriterIDList) {
      writerPoolMap.remove(writerID);
    }

    return result;
  }

  public Set<String> getFailedWriterID() {
    Set<String> failedIDs = new HashSet<String>();
    for (String writerID : writerToResultsMap.keySet()) {
      if (!isSuccess(writerToResultsMap.get(writerID),
          writerPoolMap.get(writerID))) {
        failedIDs.add(writerID);
      }
    }
    return failedIDs;
  }

  public int getErrorCode() {
    int result = Integer.MAX_VALUE;
    for (String writerID : writerToResultsMap.keySet()) {
      int status = getStatus(writerToResultsMap.get(writerID),
          writerPoolMap.get(writerID));
      if (status != JobStatus.SUCCESS.getStatus() && status < result) {
        result = status;
      }
    }
    return result;
  }

  private void terminate(String writerID) {
    IWriterPeriphery writerPeriphery = writerPeripheryMap.get(writerID);
    if (writerPeriphery == null) {
      s_logger.error("can not find any writer periphery for " + writerID);
      return;
    }
    IParam jobParams = writerToJobParamsMap.get(writerID);
    if (jobParams == null) {
      s_logger.error("can not find any job parameters for " + writerID);
      return;
    }

    writerPeriphery.doPost(jobParams, monitorManager);
  }

  public void rollbackAll() {
    for (String writerID : writerPeripheryMap.keySet()) {
      rollback(writerID);
    }
  }

  public void rollback(Collection<String> writerIDs) {
    for (String writerID : writerIDs) {
      rollback(writerID);
    }
  }

  public void rollback(String writerID) {
    IWriterPeriphery writerPeriphery = writerPeripheryMap.get(writerID);
    if (writerPeriphery == null) {
      s_logger.error("can not find any writer periphery for " + writerID);
      return;
    }
    IParam jobParams = writerToJobParamsMap.get(writerID);
    if (jobParams == null) {
      s_logger.error("can not find any job parameters for " + writerID);
      return;
    }

    writerPeriphery.rollback(jobParams);
  }
}
TOP

Related Classes of com.dp.nebula.wormhole.engine.core.WriterManager$WritePrepareCallable

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.