protected void die(ShellBoltException exception) {
   String processInfo =
       _process.getProcessInfoString() + _process.getProcessTerminationInfoString();
   _exception = new RuntimeException(processInfo, exception);
   LOG.error("Halting process: ShellBolt died.", _exception);
   _collector.reportError(_exception);
   if (_running
       || (exception.getCause()
           instanceof Error)) { // don't exit if not running, unless it is an Error
     Runtime.getRuntime().halt(11);
   }
 }
  private void handleLog(ShellMsg shellMsg) {
    String msg = shellMsg.getMsg();
    msg = "ShellLog " + _process.getProcessInfoString() + " " + msg;
    ShellMsg.ShellLogLevel logLevel = shellMsg.getLogLevel();

    switch (logLevel) {
      case TRACE:
        LOG.trace(msg);
        break;
      case DEBUG:
        LOG.debug(msg);
        break;
      case INFO:
        LOG.info(msg);
        break;
      case WARN:
        LOG.warn(msg);
        break;
      case ERROR:
        LOG.error(msg);
        _collector.reportError(new ReportedFailedException(msg));
        break;
      default:
        LOG.info(msg);
        break;
    }
  }
  protected void prepare(
      Map stormConf, final TopologyContext context, final IOutputCollector collector) {

    _rand = new Random();
    _collector = collector;

    _context = context;

    heartbeatTimeoutMills = getHeartbeatTimeoutMillis(stormConf);

    _process = new NuShellProcess(_command, this, this);

    // subprocesses must send their pid first thing
    Number subpid = _process.launch(stormConf, context);
    LOG.info("Launched subprocess with pid " + subpid);
    this.pid = subpid.longValue();

    /**
     * randomizing the initial delay would prevent all shell bolts from heartbeating at the same
     * time frame
     */
    int initialDelayMillis = random.nextInt(4000) + 1000;
    BoltHeartbeatTimerTask task = new BoltHeartbeatTimerTask(this);
    heartBeatExecutorService.scheduleAtFixedRate(
        task, initialDelayMillis, getHeartbeatPeriodMillis(stormConf), TimeUnit.MILLISECONDS);
  }
  public void execute(Tuple input) {
    if (_exception != null) {
      throw new RuntimeException(_exception);
    }

    // just need an id
    String genId = Long.toString(_rand.nextLong());
    _inputs.put(genId, input);
    _process.writeBoltMsg(createBoltMessage(input, genId));
  }
  private void handleEmit(ShellResponseMsg shellMsg) {
    List<Tuple> anchors = new ArrayList<Tuple>();
    List<String> recvAnchors = shellMsg.getAnchors();
    if (recvAnchors != null) {
      for (String anchor : recvAnchors) {
        Tuple t = _inputs.get(anchor);
        if (t == null) {
          throw new RuntimeException("Anchored onto " + anchor + " after ack/fail");
        }
        anchors.add(t);
      }
    }

    if (shellMsg.getTask() == 0) {
      List<Integer> outtasks = _collector.emit(shellMsg.getStream(), anchors, shellMsg.getTuple());
      if (shellMsg.areTaskIdsNeeded()) {
        Preconditions.checkNotNull(outtasks);
        _process.writeTaskIds(outtasks);
      }
    } else {
      _collector.emitDirect(
          (int) shellMsg.getTask(), shellMsg.getStream(), anchors, shellMsg.getTuple());
    }
  }
 public void cleanup() {
   _running = false;
   heartBeatExecutorService.shutdownNow();
   _process.destroy(/*force=*/ true);
   _inputs.clear();
 }