/**
   * 쓰레드 덤프를 요청하는 전문을 보낸다<br>
   * <br>
   *
   * @param threadDumpData
   * @param agentId
   * @param channel
   * @author Kim Ji Hye
   * @since 2015. 11. 26.
   */
  public ThreadDumpData sendThreadDumpRequest(ThreadDumpData td) {

    // Assembler를 사용하여 socket에 write한다.
    byte[] sendData = Assembler.getSendData(td, true);
    Channel channel = AgentClientSocketHandler.getClient(td.getAgentId());
    if (channel != null) {
      ByteBufAllocator alloc = channel.alloc();
      ByteBuf buf = alloc.buffer(sendData.length);
      buf.writeBytes(sendData);
      channel.writeAndFlush(buf);
    }
    return td;
  }
  /**
   * TODO 쓰레드 정보 조회.<br>
   * <br>
   *
   * @param request
   * @param response
   * @param inParams
   * @return
   * @author Park Woon Kyung
   * @since 2015. 10.18
   */
  @RequestMapping(value = "/threadSearch")
  public Parameters threadSearch(
      HttpServletRequest request, HttpServletResponse response, Parameters inParams) {

    Parameters outParam = ParametersFactory.createParameters(inParams);

    // 수집 쓰레드덤프 데이터
    ThreadDumpData threadDumpData = null;
    // 호출시간 날짜형태로 표현
    SimpleDateFormat time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    List<ThreadState> threadStateList = null;

    // FDGS 조회 시작 시간
    String startTime = null;
    // FDGS 조회 순간 시간
    String now = null;

    // 쓰레드 정보 저장 DataSet 컬럼 구성
    FrameOneDataset dsThreadDump = new FrameOneHtmlDataset();
    dsThreadDump.addStringColumn("AGENT_ID");
    dsThreadDump.addStringColumn("CLIENT_IP");
    dsThreadDump.addStringColumn("REQ_TIME");
    dsThreadDump.addIntegerColumn("RES_TIME");
    dsThreadDump.addIntegerColumn("THREAD_ID");
    dsThreadDump.addStringColumn("THREAD_STATE");
    dsThreadDump.addStringColumn("APPLICATION");
    dsThreadDump.addStringColumn("THREAD_STACKTRC");
    dsThreadDump.addStringColumn("SQL");

    // 선택된 Agent 처리(반드시 1개의 Agent만 선택가능)
    String agentId = inParams.getVariableAsString("AGENTLIST");
    if (null != agentId && !"".equals(agentId)) {

      // 쓰레드 덤프를 요청하는 모델 클래스
      ThreadDumpData td = new ThreadDumpData();
      td.setAgentId(agentId);
      td.setTypeCd(APMConstants.THREADDUMP_DATA);
      td.setWeightValue(APMConstants.THREADDUMP_WEIGHT_VALUE);
      td.setThreadDumpReqDtm(DateUtil.getDateTime("yyyyMMddHHmmssSSS"));

      // 선택한 에이전트의 쓰레드 덤프 요청
      sendThreadDumpRequest(td);

      // FDGS 조회 시작 시간
      startTime = DateUtil.getDateTime("yyyyMMddHHmmss");

      // FDGS 캐시에 요청한 키에 해당하는 쓰레드 덤프 데이터가 있는지 확인
      while (threadDumpData == null) {
        // FDGS 조회 시간이 10초이상이면 break
        now = DateUtil.getDateTime("yyyyMMddHHmmss");
        if (DateUtil.getDiffSecCount(startTime, now) >= 10) {
          break;
        }

        threadDumpData =
            FDGSUtil.getObject(
                APMConstants.THREAD_DUMP_DATA,
                td.getThreadDumpReqDtm() + "|" + td.getAgentId(),
                ThreadDumpData.class);

        // 에이전트에서 받은 데이터가 있을 때
        if (threadDumpData != null) {
          threadStateList = threadDumpData.getThreadStateList();
          break;
        }

        try {
          // 0.5초 쉼
          Thread.sleep(500);
        } catch (InterruptedException e) {
          LOG.error("InterruptedException", e);
        }
      }

      if (threadStateList != null) {
        for (ThreadState ts : threadStateList) {
          int row = dsThreadDump.appendRow();
          dsThreadDump.setColumn(row, "AGENT_ID", agentId);
          dsThreadDump.setColumn(row, "CLIENT_IP", ts.getClientIp());
          dsThreadDump.setColumn(
              row,
              "REQ_TIME",
              time.format(
                  DateUtil.parseDate(String.valueOf(ts.getReqStartDtm()).substring(0, 14))));
          dsThreadDump.setColumn(row, "RES_TIME", ts.getElapsedTime());
          dsThreadDump.setColumn(row, "THREAD_ID", ts.getThreadId());
          dsThreadDump.setColumn(row, "THREAD_STATE", ts.getThreadState());
          dsThreadDump.setColumn(row, "APPLICATION", ts.getCallUri());
          dsThreadDump.setColumn(row, "THREAD_STACKTRC", ts.getStackTrc());
          dsThreadDump.setColumn(row, "SQL", ts.getSqlString());
        }
      }
    }

    if (LOG.isDebugEnabled()) {
      LOG.debug("[dsThreadDump]");
      LOG.debug(dsThreadDump);
    }

    outParam.setFrameOneDataset("ds_threadDump", dsThreadDump);
    return outParam;
  }