2048 lines
88 KiB
Java
2048 lines
88 KiB
Java
package com.eactive.eai.adapter.wca;
|
|
|
|
import java.io.BufferedOutputStream;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.net.InetSocketAddress;
|
|
import java.net.Socket;
|
|
import java.net.SocketAddress;
|
|
import java.net.SocketException;
|
|
import java.net.SocketTimeoutException;
|
|
import java.time.ZonedDateTime;
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.util.ArrayList;
|
|
import java.util.Date;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
|
|
import com.eactive.eai.adapter.AdapterManager;
|
|
import com.eactive.eai.adapter.AdapterPropManager;
|
|
import com.eactive.eai.adapter.AdapterVO;
|
|
import com.eactive.eai.adapter.wca.cfg.SNAAdapter;
|
|
import com.eactive.eai.adapter.wca.cfg.SNAAdapterManager;
|
|
import com.eactive.eai.adapter.wca.cfg.SessionGroupDataEx;
|
|
import com.eactive.eai.adapter.wca.data.AppCodeCmd;
|
|
import com.eactive.eai.adapter.wca.data.ManualBackupCmd;
|
|
import com.eactive.eai.adapter.wca.data.WCAAdapterInfoCmd;
|
|
import com.eactive.eai.adapter.wca.data.WCAHeader;
|
|
import com.eactive.eai.adapter.wca.data.WCAQueue;
|
|
import com.eactive.eai.adapter.wca.data.WCAQueueData;
|
|
import com.eactive.eai.adapter.wca.exception.WCAException;
|
|
import com.eactive.eai.adapter.wca.global.WCADefine;
|
|
import com.eactive.eai.adapter.wca.util.CodeCvrt;
|
|
import com.eactive.eai.adapter.wca.util.MyLog;
|
|
import com.eactive.eai.adapter.wca.util.MyUtil;
|
|
import com.eactive.eai.common.errorcode.ErrorCodeHandler;
|
|
import com.eactive.eai.common.property.PropManager;
|
|
import com.eactive.eai.common.util.LogKeys;
|
|
import com.eactive.eai.common.util.Logger;
|
|
import com.eactive.eai.common.util.SMSLogUtil;
|
|
|
|
/**
|
|
* 1. 기능 : Softlink TCP 세션 연결 및 수신 데이타를 처리한다.
|
|
* 2. 처리 개요 :
|
|
* -
|
|
* 3. 주의사항
|
|
*
|
|
* @author :
|
|
* @version : v 1.0.0
|
|
* @see :
|
|
* @since : 2005. 6. 17. 오후 10:01:13
|
|
*/
|
|
public class WCASessionThread implements Runnable {
|
|
/**
|
|
* SNAAdapter critical한 정보 로깅을 위한 logger
|
|
*/
|
|
Logger adapter_logger = Logger.getLogger(WCADefine.ADAPTER_LOGGER_NAME);
|
|
|
|
// 20090810 Start
|
|
private String sNodeName = ""; // Softlink Node Name
|
|
// 20090810 End
|
|
|
|
private Socket sockSoftLink = null; // SoftLink와 연결할 Socket
|
|
//private BufferedInputStream isSoftLink = null; // Socket에 대한 InputStream
|
|
private InputStream isSoftLink = null; // Socket에 대한 InputStream
|
|
private BufferedOutputStream osSoftLink = null; // Socket에 대한 OutputStream
|
|
private HashMap hmapRcvData = null; // 세션에서 수신된 데이터를 저장할 Queue에 대한 HashMap
|
|
private MyLog myLog = null; // 메시지 로그 처리 오브젝트
|
|
private MyLog myTrc = null; // 트레이스 처리 오브젝트
|
|
private String sIpAddr = null; // SoftLink IP 주소
|
|
private int nPortNo = 0; // SoftLink Port 번호
|
|
private String sAdapterGroupName = null; // SoftLink 세션에 대한 Adapter Group Name
|
|
private String sAdapterName = null; // SoftLink 세션에 대한 Adapter Name
|
|
private String sGroupCode = null; // SoftLink 세션에 대한 Group Code
|
|
private int nSessId = 0; // SoftLiInk 세션 ID
|
|
private WCAEventInterface wcaEventHandler = null; // SoftLiInk 세션에 대한 수신 데이터 처리 이벤트 핸들러
|
|
|
|
private int nRcvTimeout = 0; // 데이터 수신 Timeout
|
|
private int nConnTimeout = 0; // 세션 연결 Timeout
|
|
private int nSessStat = 0; // TCP 세션 상태 0 : 연결안됨, 1 : TCP 세션 연결, 2 : TCP 세션 사용중 (사용안함)
|
|
|
|
private int nDisconnectCnt = 0; // 세션 해제 횟수
|
|
private int nContinuousDisconnectCnt = 0; // 연속적으로 세션 연결 실패 횟수
|
|
private int nSndCnt = 0; // 데이터 송신 횟수
|
|
private int nRcvCnt = 0; // 데이터 수신 횟수
|
|
|
|
private boolean bRunning = false; // Thread 동작 여부
|
|
private boolean bBackupSessionPool = false; // Backup 세션 여부
|
|
|
|
// Softlink IP 주소가 여러개인 경우, 백업 모드 기능 자체를 사용할 수 없음
|
|
private boolean bBackupEnableFlag = true; // Backup 세션 전환 사용 가능 여부
|
|
|
|
private boolean bBeforeConn = false; // 이전 TCP 세션 연결 여부
|
|
|
|
private int tran_timeout = WCADefine.DEFAULT_TRANSACTION_TIMEOUT ; // 트랜잭션 타임아웃
|
|
private String tran_mode; // 송신(S),수신(R) 모드
|
|
|
|
long lReadStartTime = 0L, lReadEndTime = 0L, lNotifyEndTime = 0L;
|
|
|
|
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd=HH:mm:ss.SSS");
|
|
|
|
private SNAAdapter snaAdapter = null;
|
|
|
|
// 20090810
|
|
public boolean getBackupEnableFlag() {
|
|
return bBackupEnableFlag;
|
|
}
|
|
|
|
public void setBackupEnableFlag(boolean bBackupEnableFlag) {
|
|
this.bBackupEnableFlag = bBackupEnableFlag;
|
|
return;
|
|
}
|
|
// 20090810 End
|
|
|
|
|
|
/**
|
|
* 1. 기능 : 노드 이름 설정
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @param sNodName 노드이름
|
|
**/
|
|
public void setNodeName(String s_node_name) {
|
|
if (s_node_name == null) { s_node_name = ""; }
|
|
this.sNodeName = s_node_name.trim();
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 노드 이름 반환
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @return 노드이름
|
|
**/
|
|
public String getNodeName() {
|
|
return this.sNodeName;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 세션 정보 반환
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @return 세션 정보
|
|
**/
|
|
public String toString() {
|
|
StringBuffer sb_name = new StringBuffer();
|
|
|
|
sb_name.append(" " + sGroupCode + "-" + nSessId);
|
|
|
|
if (bBackupSessionPool) {
|
|
sb_name.append(":BACKUP ");
|
|
}
|
|
else {
|
|
sb_name.append(" ");
|
|
}
|
|
|
|
return sb_name.toString();
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : INBOUND 핸들러 등록
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
**/
|
|
public void registerEventHandler(Object objHandler) {
|
|
wcaEventHandler = (WCAEventInterface)objHandler;
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 트랜잭션 타임아웃 설정
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @param timeout 트랜잭션 타임아웃
|
|
**/
|
|
public void setTranTimeout(int timeout) {
|
|
this.tran_timeout = timeout;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 트랜잭션 타임아웃 반환
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @return 트랜잭션 타임아웃
|
|
**/
|
|
public int getTranTimeout() {
|
|
return this.tran_timeout;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 트랜잭션 송수신 모드 설정
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @param sTranMode 트랜잭션 송수신 모드
|
|
**/
|
|
public void setTranMode(String sTranMode) {
|
|
if (sTranMode == null ) { sTranMode = ""; }
|
|
this.tran_mode = sTranMode;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 트랜잭션 송수신 모드 반환
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @return 트랜잭션 송수신 모드
|
|
**/
|
|
public String getTranMode() {
|
|
return this.tran_mode;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : Sotlink 세션 정보 설정
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @param sIpAddr Softlink Ip 주소
|
|
* @param nPortNo SoftLink Port 번호
|
|
* @param nSessNum WCA 세션 수
|
|
**/
|
|
public void setSessionInfo(String sIpAddr, int nPortNo) {
|
|
this.sIpAddr = sIpAddr;
|
|
this.nPortNo = nPortNo;
|
|
}
|
|
|
|
public void updateSessionInfoEx(SessionGroupDataEx sessgroup) {
|
|
// 로컬 세션인 경우
|
|
if (!isBackupSessionPool()) {
|
|
setSessionInfo(sessgroup.getSoftLinkSevrName(), sessgroup.getPort());
|
|
}
|
|
// 백업 세션인 경우
|
|
else {
|
|
setSessionInfo(sessgroup.getBackupNodeName(), sessgroup.getBackupPort());
|
|
}
|
|
|
|
setLogInfo(sessgroup.isLogWritable(), sessgroup.getLogLevel(), sessgroup.getLogSize());
|
|
setTranTimeout(sessgroup.getTranTimeout());
|
|
setBackupEnableFlag(sessgroup.getBackupEnableFlag());
|
|
|
|
// APP_CODE 프라퍼티가 변경되었을 경우, Softlink에게 데이터 전송
|
|
try {
|
|
sendWcaSessionAppCode(true);
|
|
}
|
|
catch (Exception e) {
|
|
adapter_logger.warn("WCASessionThread:updateSessionInfoEx> Exception Msg = " + e.getMessage());
|
|
}
|
|
|
|
myLog.logMsg(MyLog.INFO, toString() + " 세션 정보 갱신 " + sessgroup.toString());
|
|
}
|
|
|
|
// 2020.05.27 updateSessionInfoEx 함수를 참조하여 개발함
|
|
public void updateWcaAppCodeEx() {
|
|
// APP_CODE 프라퍼티가 변경되었을 경우, Softlink에게 데이터 전송
|
|
try {
|
|
adapter_logger.warn("WCASessionThread:updateWcaAppCodeEx> Try to Send Wca AppCode");
|
|
sendWcaSessionAppCode(false);
|
|
}
|
|
catch (Exception e) {
|
|
adapter_logger.warn("WCASessionThread:updateWcaAppCodeEx> Exception Msg = " + e.getMessage());
|
|
}
|
|
|
|
myLog.logMsg(MyLog.INFO, toString() + " WCA APP CODE 정보 갱신");
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 로그 설정
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @param bLogYN 로깅 여부
|
|
* @param nLogLevel 로깅 레벨
|
|
* @param nLogSize 로깅 파일 사이즈
|
|
**/
|
|
public void setLogInfo(boolean bLogYN, int nLogLevel, int nLogSize) {
|
|
if (myLog != null) {
|
|
myLog.setLogLevel(nLogLevel);
|
|
myLog.setTraceOnOff(bLogYN);
|
|
myLog.setMaxLogFileSize(nLogSize);
|
|
}
|
|
|
|
if (myTrc != null) {
|
|
myTrc.setLogLevel(nLogLevel);
|
|
myTrc.setTraceOnOff(bLogYN);
|
|
myTrc.setMaxLogFileSize(nLogSize);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : SoftLink와의 세션을 관리할 쓰레드 클래스 생성 함수
|
|
* 2. 처리 개용 :
|
|
* - 파라미터로 넘어온 정보를 내부 변수에 설정한다.
|
|
* - 로그와 트레이스를 저장하기 위한 로그 처리 클래스의 오브젝트를 생성한다.
|
|
* 3. 주의사항
|
|
* - 트레이스 처리의 동기화를 위해서 myTrc 클래스에 대한 동기화를 수행한다.
|
|
* - 송신 데이터 버퍼 형식 : 길이(4) + Data(n)
|
|
*
|
|
* @param sIpAddr Softlink Ip 주소
|
|
* @param nPortNo SoftLink Port 번호
|
|
* @param sAdapterGroupName 어댑터 그룹 이름
|
|
* @param sAdapterName 어댑터 이름
|
|
* @param sGroupCode LU 그룹 이름
|
|
* @param nSessId Pool에 설정된 세션 수
|
|
* @param bBackupSessionPool Backup Pool 여부 (true: 백업 세션)
|
|
* @param bLogYN 로깅 여부
|
|
* @param nLogLevel 로그 레벨
|
|
* @param nLogSize 로그 파일 사이즈
|
|
*/
|
|
public WCASessionThread(String sNodeName, String sIpAddr, int nPortNo,
|
|
String sAdapterGroupName, String sAdapterName, String sGroupCode, int nSessId,
|
|
boolean bBackupSessionPool,
|
|
boolean bLogYN, int nLogLevel, int nLogSize) {
|
|
try {
|
|
this.sNodeName = sNodeName;
|
|
this.sIpAddr = sIpAddr;
|
|
this.nPortNo = nPortNo;
|
|
this.sAdapterGroupName = sAdapterGroupName;
|
|
this.sAdapterName = sAdapterName;
|
|
this.sGroupCode = sGroupCode;
|
|
|
|
this.nSessId = nSessId;
|
|
this.bBackupSessionPool = bBackupSessionPool;
|
|
|
|
nSessStat = WCADefine.SESS_STAT_NOTCONN;
|
|
|
|
hmapRcvData = new HashMap();
|
|
nRcvTimeout = WCADefine.DEFAULT_RECEIVE_TIMEOUT;
|
|
nConnTimeout = WCADefine.DEFAULT_CONNECT_TIMEOUT;
|
|
|
|
snaAdapter = SNAAdapterManager.getInstance().selectSnaAdapter(sAdapterGroupName);
|
|
|
|
String sLogDirectory = PropManager.getInstance().getProperty(LogKeys.LOGGER_INFO, LogKeys.LOG_DIRECOTRY_PREFIX);
|
|
if (sLogDirectory==null || sLogDirectory.equals("")) {
|
|
sLogDirectory = WCADefine.SERVER_NAME + File.separatorChar + "wca";
|
|
}
|
|
else {
|
|
sLogDirectory = sLogDirectory + File.separatorChar + WCADefine.SERVER_NAME + File.separatorChar + "wca";
|
|
}
|
|
|
|
//if (trc_logger.isDebug()) trc_logger.debug(">> sLogDirectory = " + sLogDirectory);
|
|
// 로그와 트레이스 처리를 위한 오브젝트 생성
|
|
String sMyTrcPath = "";
|
|
String sMyLogPath = "";
|
|
|
|
if (bBackupSessionPool) {
|
|
// 20090810 Start
|
|
/*
|
|
myTrc = new MyLog(bLogYN, nLogLevel, nLogSize, sLogDirectory + File.separatorChar + sGroupCode + "-" + nSessId + "_BACKUP.trc");
|
|
myLog = new MyLog(bLogYN, nLogLevel, nLogSize, sLogDirectory + File.separatorChar + sGroupCode + "-" + nSessId + "_BACKUP.log");
|
|
|
|
sMyTrcPath = sLogDirectory + File.separatorChar + sGroupCode + "-" + nSessId + "_BACKUP.trc";
|
|
sMyLogPath = sLogDirectory + File.separatorChar + sGroupCode + "-" + nSessId + "_BACKUP.log";
|
|
*/
|
|
myTrc = new MyLog(bLogYN, nLogLevel, nLogSize, sLogDirectory + File.separatorChar + sNodeName + "_" + sGroupCode + "-" + nSessId + "_BACKUP.trc");
|
|
myLog = new MyLog(bLogYN, nLogLevel, nLogSize, sLogDirectory + File.separatorChar + sNodeName + "_" + sGroupCode + "-" + nSessId + "_BACKUP.log");
|
|
|
|
sMyTrcPath = sLogDirectory + File.separatorChar + sNodeName + "_" + sGroupCode + "-" + nSessId + "_BACKUP.trc";
|
|
sMyLogPath = sLogDirectory + File.separatorChar + sNodeName + "_" + sGroupCode + "-" + nSessId + "_BACKUP.log";
|
|
// 200908010 End
|
|
}
|
|
else {
|
|
// 20090810 Start
|
|
/*
|
|
myTrc = new MyLog(bLogYN, nLogLevel, nLogSize, sLogDirectory + File.separatorChar + sGroupCode + "-" + nSessId + ".trc");
|
|
myLog = new MyLog(bLogYN, nLogLevel, nLogSize, sLogDirectory + File.separatorChar + sGroupCode + "-" + nSessId + ".log");
|
|
|
|
sMyTrcPath = sLogDirectory + File.separatorChar + sGroupCode + "-" + nSessId + ".trc";
|
|
sMyLogPath = sLogDirectory + File.separatorChar + sGroupCode + "-" + nSessId + ".log";
|
|
*/
|
|
myTrc = new MyLog(bLogYN, nLogLevel, nLogSize, sLogDirectory + File.separatorChar + sNodeName + "_" + sGroupCode + "-" + nSessId + ".trc");
|
|
myLog = new MyLog(bLogYN, nLogLevel, nLogSize, sLogDirectory + File.separatorChar + sNodeName + "_" + sGroupCode + "-" + nSessId + ".log");
|
|
|
|
sMyTrcPath = sLogDirectory + File.separatorChar + sNodeName + "_" + sGroupCode + "-" + nSessId + ".trc";
|
|
sMyLogPath = sLogDirectory + File.separatorChar + sNodeName + "_" + sGroupCode + "-" + nSessId + ".log";
|
|
// 20090810 End
|
|
}
|
|
|
|
/* 20080523 Start */
|
|
try {
|
|
if (adapter_logger.isWarn()) {
|
|
adapter_logger.warn("adapter_logger trc_logger Path : " + Logger.LOGGER_ADAPTER);
|
|
adapter_logger.warn("adapter_logger adapter_logger Path : " + WCADefine.ADAPTER_LOGGER_NAME);
|
|
adapter_logger.warn("adapter_logger myTrc Path : " + sMyTrcPath);
|
|
adapter_logger.warn("adapter_logger myLog Path : " + sMyLogPath);
|
|
}
|
|
|
|
myLog.logMsg(MyLog.WARN, "trc_logger Path : " + Logger.LOGGER_ADAPTER);
|
|
myLog.logMsg(MyLog.WARN, "adapter_logger Path : " + WCADefine.ADAPTER_LOGGER_NAME);
|
|
myLog.logMsg(MyLog.WARN, "myTrc Path : " + sMyTrcPath);
|
|
myLog.logMsg(MyLog.WARN, "myLog Path : " + sMyLogPath);
|
|
}
|
|
catch(Exception ignore) {
|
|
// System.out.println("WCASessionThread> Exception Msg = " + ignore.toString());
|
|
}
|
|
/* 20080523 End */
|
|
}
|
|
catch(Exception e) {
|
|
adapter_logger.error("WCASessionThread] - [" + WCAException.E_ETC + "] " + toString() + e.toString());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 백업 세션 여부 설정 (true: 백업 세션)
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @param flag 백업 세션 여부
|
|
**/
|
|
public void setBackupSessionPool(boolean flag) {
|
|
bBackupSessionPool = flag;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 백업 세션 여부 반환 (true: 백업 세션)
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @return 백업 세션 여부
|
|
**/
|
|
public boolean isBackupSessionPool() {
|
|
return bBackupSessionPool;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 데이터 송신별 수신 데이터를 대기할 Queue를 등록
|
|
* 2. 처리 개요 :
|
|
* - 송신 데이터의 트랜잭션 Key 필드를 기준으로 HashMap에 등록한다.
|
|
* 3. 주의사항
|
|
* - WLI의 송신 쓰레드는 데이터 송신 후, 등록한 Queue를 대기한다.
|
|
*
|
|
* @param objKey HashMap에 저장될 unique한 key (UUID)
|
|
* @param objData HashMap에 저장될 값 (송신에 대한 Queue 데이타)
|
|
* @return 0
|
|
**/
|
|
public int registerRcvQueue(Object objKey, Object objData) {
|
|
synchronized (hmapRcvData) {
|
|
hmapRcvData.put(objKey, objData);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : Queue에 등록된 송신에 대한 Queue 데이타 삭제
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @param objKey HashMap에 저장될 unique한 key (UUID)
|
|
**/
|
|
public int unregisterRcvQueue(Object objKey) {
|
|
synchronized (hmapRcvData) {
|
|
hmapRcvData.remove(objKey);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : SoftLink 세션을 연결한다.
|
|
* 2. 처리 개요 :
|
|
* - SoftLink와 TCP 세션을 연결한다.
|
|
* - 세션이 연결되면 소켓에 대한 In/Out 스트림을 생성한다.
|
|
* 3. 주의사항
|
|
*
|
|
* @param nTimeout 연결 Timeout
|
|
* @return 세션 연결 결과
|
|
* @exception IOException
|
|
*/
|
|
public boolean connectSoftLink(int nTimeout) throws IOException {
|
|
SocketAddress sockAddr = null;
|
|
|
|
try {
|
|
sockSoftLink = new Socket();
|
|
myLog.logMsg(MyLog.DEBUG, "connectSoftLink] New Socket is Created...");
|
|
sockAddr = new InetSocketAddress(sIpAddr, nPortNo);
|
|
myLog.logMsg(MyLog.INFO, "connectSoftLink] New Socket Address, Addr = " + sockAddr);
|
|
|
|
myLog.logMsg(MyLog.DEBUG, "connectSoftLink] Try Connect to SoftLink..., nTimeout = " + nTimeout + "ms");
|
|
sockSoftLink.connect(sockAddr, nTimeout);
|
|
|
|
myLog.logMsg(MyLog.INFO, "RECVEIVE Buffer Size = " + sockSoftLink.getReceiveBufferSize());
|
|
//sockSoftLink.setReceiveBufferSize(2048);
|
|
myLog.logMsg(MyLog.INFO, "connectSoftLink] Session is Connected...(Local Port = " + sockSoftLink.getLocalPort() + ")");
|
|
|
|
//isSoftLink = new BufferedInputStream(sockSoftLink.getInputStream());
|
|
isSoftLink = sockSoftLink.getInputStream();
|
|
osSoftLink = new BufferedOutputStream(sockSoftLink.getOutputStream());
|
|
|
|
myLog.logMsg(MyLog.INFO, "connectSoftLink] Socket In/Out Stream is Opened...");
|
|
|
|
// if true, pakcets are sent as quickly as possible regardless of their size
|
|
sockSoftLink.setTcpNoDelay(true);
|
|
|
|
nSessStat = WCADefine.SESS_STAT_READY;
|
|
nContinuousDisconnectCnt = 0;
|
|
return true;
|
|
}
|
|
catch (Exception e) {
|
|
myLog.logMsg(MyLog.ERROR, "connectSoftLink] " + e.toString());
|
|
|
|
// softlink가 내려가고 EAI가 내려갔을 경우,,, 세션이 백션으로 가야함...(2분)
|
|
if (nContinuousDisconnectCnt % WCADefine.DEFAULT_BACKUP_CONVERSION_CHECK == 0) {
|
|
checkBackupConversion();
|
|
}
|
|
|
|
nContinuousDisconnectCnt++;
|
|
nDisconnectCnt++;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : Thread 종료
|
|
* 2. 처리 개요 :
|
|
* - running 상태 Flag를 false로 설정한다.
|
|
* 3. 주의사항
|
|
**/
|
|
public void stopAdapter() {
|
|
myLog.logMsg(MyLog.INFO, "stopAdapter] Thread is Stopping. " + toString() );
|
|
bRunning = false;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 어댑터 상태 설정
|
|
* 2. 처리 개요 : 어댑터 그룹 이용가능한 세션이 없을 경우 어댑터 상태를 false로 한다.
|
|
* 3. 주의사항
|
|
**/
|
|
private void setAdapterStatus(boolean flag) {
|
|
int nAdapterConnected;
|
|
|
|
/* 20080523 수정 시작 */
|
|
/*
|
|
어댑터 상태를 사용안함으로 설정할때, EAI Framework쪽에서 어댑터 정보를 메모리에서
|
|
삭제하기 때문에 getAdapterVO 함수 호출시 NULL 값이 리턴되어 synchronized(av) 라인 처리시
|
|
java.lang.NullPointerException 발생함
|
|
--> 전체 로직을 try, catch로 묶음
|
|
*/
|
|
try {
|
|
AdapterManager amanager = AdapterManager.getInstance();
|
|
AdapterVO av = amanager.getAdapterVO(this.sAdapterGroupName,this.sAdapterName);
|
|
|
|
synchronized (av) {
|
|
// if (av.isStatus() == flag)
|
|
//{
|
|
try {
|
|
nAdapterConnected = snaAdapter.getConnectedSessNum();
|
|
if (av != null) {
|
|
if (nAdapterConnected <= 0 ) {
|
|
av.setStatus(false);
|
|
}
|
|
else {
|
|
av.setStatus(true);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
adapter_logger.error("setAdapterStatus error", e);
|
|
}
|
|
//}
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
myLog.logMsg(MyLog.INFO, "setAdapterStatus] Exception Msg = " + e.toString());
|
|
}
|
|
/* 20080523 수정 끝 */
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 처리되지 않은 트랜잭션 출력 및 notify
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
**/
|
|
private void traceRemainTransaction() {
|
|
int iRemainWorkCnt = 0;
|
|
String sKey = null;
|
|
WCAQueue queueWSA = null;
|
|
WCAHeader header = null;
|
|
String sMessage = "";
|
|
String sCode = "";
|
|
char cMode ;
|
|
boolean bRecvSendOK = false;
|
|
|
|
Iterator iter = null;
|
|
|
|
HashMap copy = (HashMap)hmapRcvData.clone();
|
|
iter = copy.keySet().iterator();
|
|
|
|
myLog.logMsg(MyLog.ERROR, ">>>>>>>>> " + toString() +" Remain Work is started. (Number = "+copy.size() + ") <<<<<<<<<<");
|
|
while (iter.hasNext()) {
|
|
try {
|
|
iRemainWorkCnt++;
|
|
|
|
sKey = (String)iter.next();
|
|
if (sKey == null) {
|
|
if (adapter_logger.isError()) { adapter_logger.error("traceRemainTransaction] " + toString() + "sKey is null"); }
|
|
myLog.logMsg(MyLog.ERROR, "traceRemainTransaction] sKey is null");
|
|
continue;
|
|
}
|
|
|
|
myLog.logMsg(MyLog.ERROR, "Remain Work " + String.valueOf(iRemainWorkCnt) + "] TRANSACTION KEY = " + sKey);
|
|
|
|
// notify
|
|
synchronized (hmapRcvData) {
|
|
queueWSA = (WCAQueue)hmapRcvData.remove(sKey);
|
|
}
|
|
|
|
synchronized (queueWSA) {
|
|
bRecvSendOK = queueWSA.getRecvSendOKFlag();
|
|
cMode = queueWSA.getMode();
|
|
}
|
|
|
|
if (bRecvSendOK) {
|
|
sCode = WCAException.E_SOFTLINK_RECV_SESSION_CLOSE;
|
|
}
|
|
else {
|
|
sCode = WCAException.E_SOFTLINK_SEND_SESSION_CLOSE;
|
|
}
|
|
|
|
if (adapter_logger.isError()) { adapter_logger.error(WCAException.displayError(sCode) + toString() + " TRANSACTION KEY = " + sKey); }
|
|
sMessage = sCode + ErrorCodeHandler.getMessage(sCode);
|
|
|
|
// 데이타 조립
|
|
header = new WCAHeader();
|
|
byte[] pBuff = new byte[WCAHeader.WCA_HEADER_LEN + sMessage.getBytes().length];
|
|
System.arraycopy(header.getHeader(), 0, pBuff, 0, WCAHeader.WCA_HEADER_LEN);
|
|
System.arraycopy(sMessage.getBytes(), 0, pBuff, WCAHeader.WCA_HEADER_LEN, sMessage.getBytes().length);
|
|
|
|
// NonResponse 모드이고 sendok를 받았으면 INBOUND로 보낸다. 그외는 notify
|
|
if (cMode == (WCAHeader.TRAN_MODE_NONRESPONSE).charAt(0) && bRecvSendOK){
|
|
myLog.logMsg(MyLog.DEBUG, "traceRemainTransaction] NonResponse, send OK is received ... inbound");
|
|
byte[] pRecvBuff = queueWSA.getDataFromQueue();
|
|
System.arraycopy(pRecvBuff, 0, pBuff, 0, WCAHeader.WCA_HEADER_LEN);
|
|
|
|
if (wcaEventHandler != null) {
|
|
myLog.logMsg(MyLog.DEBUG, "traceRemainTransaction] Call Event Handler : handleTimeoutData()");
|
|
wcaEventHandler.handleNonRspData(sAdapterGroupName, sAdapterName, sGroupCode, pBuff.length, pBuff);
|
|
}
|
|
else {
|
|
myLog.logMsg(MyLog.ERROR, "traceRemainTransaction] Event Handler is Not Registered, So Discard Data...");
|
|
}
|
|
}
|
|
else {
|
|
synchronized (queueWSA) {
|
|
WCAQueueData qdataWSA = new WCAQueueData(pBuff.length, pBuff);
|
|
queueWSA.addDataToQueue(qdataWSA);
|
|
myLog.logMsg(MyLog.DEBUG, "traceRemainTransaction] (START) Notify WLI Thread...");
|
|
queueWSA.notifyAll();
|
|
myLog.logMsg(MyLog.DEBUG, "traceRemainTransaction] (END) Notify WLI Thread...");
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
if (adapter_logger.isError()) { adapter_logger.error(WCAException.displayError(WCAException.E_INFORM_ERROR, sKey)); }
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 데이타 수신 대기 및 수신 데이타 처리
|
|
* 2. 처리 개요 :
|
|
* - 세션이 연결될때까지 계속 socket 연결 시도한다.
|
|
* - bRunning가 true 일 동안 계속 Socket InputStream을 read한다.
|
|
* - 수신 데이타를 DATA TYPE에 따라 처리한다.
|
|
* 3. 주의사항
|
|
**/
|
|
public void run() {
|
|
int nRcvLen;
|
|
byte[] pLenBuff = null;
|
|
int nDataLen = 0;
|
|
int nCheckOldWCAQueueCnt = 0;
|
|
|
|
int nConnectedSessNum = 0;
|
|
int nConfiguredSessNum = 0;
|
|
|
|
myLog.logMsg(MyLog.INFO, "Transaction Timeout = " + tran_timeout + ", Transaction Mode = " + tran_mode);
|
|
myLog.logMsg(MyLog.INFO, "run] " + toString() + " Thread is Started. (Thread Group Name = " + Thread.currentThread().getThreadGroup().getName() + ")");
|
|
//adapter_logger.debug(toString() + " Thread is Started. (Thread Group Name = " + Thread.currentThread().getThreadGroup().getName() + ")");
|
|
|
|
bRunning = true;
|
|
|
|
while(true) {
|
|
try {
|
|
// Thread stop 시켰을 경우 종료한다.
|
|
if (!bRunning) {
|
|
myLog.logMsg(MyLog.DEBUG, "run] " + toString() + " bRunning = false so stop");
|
|
break;
|
|
}
|
|
|
|
// 1. Socket 연결 시도
|
|
if (nSessStat == WCADefine.SESS_STAT_NOTCONN) {
|
|
if (bBackupSessionPool) {
|
|
nConfiguredSessNum = snaAdapter.getConfiguredBackupSessNum(sNodeName, sGroupCode);
|
|
nConnectedSessNum = snaAdapter.getConnectedBackupSessNum(sNodeName, sGroupCode);
|
|
}
|
|
else {
|
|
nConfiguredSessNum = snaAdapter.getConfiguredNormalSessNum(sNodeName, sGroupCode);
|
|
nConnectedSessNum = snaAdapter.getConnectedNormalSessNum(sNodeName, sGroupCode);
|
|
}
|
|
|
|
if (nConfiguredSessNum < nConnectedSessNum) {
|
|
if (adapter_logger.isWarn()) { adapter_logger.warn("설정된 세션수보다 많은 세션수가 존재합니다. Thread 종료합니다.[" + nConnectedSessNum + "/" + nConfiguredSessNum + "]"); }
|
|
myLog.logMsg(MyLog.WARN, "설정된 세션수보다 많은 세션수가 존재합니다. Thread 종료합니다.[" + nConnectedSessNum + "/" + nConfiguredSessNum + "]");
|
|
closeSoftLink();
|
|
break;
|
|
}
|
|
|
|
myLog.logMsg(MyLog.DEBUG, "run] Status = SESS_STAT_NOTCONN, So Retry to Connect To SoftLink....");
|
|
if (connectSoftLink(nConnTimeout) == false) {
|
|
myLog.logMsg(MyLog.ERROR, "run] Can't Connect To SoftLink, Sleep " + WCADefine.DEFAULT_SESS_RECOVERY_GAP);
|
|
|
|
if (bBeforeConn) {
|
|
adapter_logger.error(WCAException.displayError(WCAException.E_SOFTLINK_NOTCONN,toString()));
|
|
myLog.logMsg(MyLog.WARN, "run] Session is Closed ");
|
|
|
|
bBeforeConn = false;
|
|
|
|
/* 20080523 SMS 로그 추가 시작 */
|
|
try {
|
|
int nSessCnt = snaAdapter.getConnectedNormalSessNum(sNodeName, sGroupCode);
|
|
|
|
if (adapter_logger.isWarn()) { adapter_logger.warn("getConnectedNormalSessNum> " + sAdapterGroupName + ", " + sGroupCode + " = "+ nSessCnt); }
|
|
myLog.logMsg(MyLog.WARN, "getConnectedNormalSessNum> " + sAdapterGroupName + ", " + sGroupCode + " = "+ nSessCnt);
|
|
|
|
if (!bBackupSessionPool) {
|
|
if (nSessCnt == 0) {
|
|
// String strSmsMsg = sAdapterGroupName + " Session is Closed";
|
|
// String strSmsMsg = sGroupCode + " Session is Closed";
|
|
String strSmsMsg = "Session is Closed";
|
|
try {
|
|
if (adapter_logger.isWarn()) { adapter_logger.warn("WCASessionThread:run> Log SMS Msg, Msg = " + sGroupCode + " " + strSmsMsg); }
|
|
myLog.logMsg(MyLog.WARN, "WCASessionThread:run> Log SMS Msg, Msg = " + sGroupCode + " " + strSmsMsg);
|
|
SMSLogUtil.loggingSMS(sGroupCode, strSmsMsg);
|
|
}
|
|
catch (Exception ignore) {
|
|
myLog.logMsg(MyLog.DEBUG, "run] Exception, While Write SMS Log, Msg = " + ignore.toString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ignore) {
|
|
// System.out.println("WCASessionThread:run> Exception Msg = " + ignore.toString());
|
|
}
|
|
/* 20080523 SMS 로그 추가 끝 */
|
|
}
|
|
|
|
Thread.sleep(WCADefine.DEFAULT_SESS_RECOVERY_GAP * 1000);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// 세션이 복귀되면 adapter 상태를 변경한다.
|
|
if (!bBeforeConn) {
|
|
setAdapterStatus(false);
|
|
sendAdapterStatusData();
|
|
|
|
// 20090810 Start
|
|
sendWcaSessionAppCode(true);
|
|
// 20090810 End
|
|
}
|
|
|
|
bBeforeConn = true;
|
|
|
|
// Socket 수신 타임 아웃 설정
|
|
//sockSoftLink.setSoTimeout(WCADefine.DEFAULT_SOCK_RCV_TIMEOUT * 1000);
|
|
|
|
// 2. Socket 수신 데이타 대기 -- 길이 필드 수신 (4 바이트)
|
|
String dateString = formatter.format(ZonedDateTime.now());
|
|
lReadStartTime = System.currentTimeMillis();
|
|
|
|
pLenBuff = recvLenthField(WCADefine.LEGTH_FIELD_SIZE);
|
|
if (pLenBuff == null) { // Connection is Close...
|
|
closeSoftLink();
|
|
continue;
|
|
}
|
|
|
|
// 3. 길이 필드 변환
|
|
// 20090302 Start
|
|
/*
|
|
nDataLen = Integer.parseInt(new String(pLenBuff));
|
|
*/
|
|
nDataLen = getInt(pLenBuff, 0);
|
|
// 20090302 End
|
|
myLog.logMsg(MyLog.INFO, "run] Data Length Field = " + nDataLen);
|
|
if (nDataLen < 0) {
|
|
myLog.logMsg(MyLog.ERROR, "run] Invalid Data Length Field... So Close Session");
|
|
closeSoftLink();
|
|
continue;
|
|
}
|
|
|
|
// 4. 데이타 수신
|
|
byte[] pDataBuff = recvDataField(nRcvTimeout, nDataLen);
|
|
if (pDataBuff == null) { // Connection is Close...
|
|
closeSoftLink();
|
|
continue;
|
|
}
|
|
|
|
lReadEndTime = System.currentTimeMillis();
|
|
if (adapter_logger.isDebug()) { adapter_logger.debug(dateString + " : WCA_RECEIVING_TIME = " + (lReadEndTime - lReadStartTime)); }
|
|
myLog.logMsg(MyLog.DEBUG, "WCA_RECEIVING_TIME = " + (lReadEndTime - lReadStartTime));
|
|
|
|
nRcvLen = pDataBuff.length;
|
|
myLog.logMsg(MyLog.INFO, "run] Receive Data Field Length = " + nRcvLen);
|
|
|
|
// 5. 수신 데이타 처리
|
|
handleRcvData(nRcvLen, pDataBuff);
|
|
}
|
|
catch (java.lang.NumberFormatException n) { // 길이 데이타를 파싱못할경우...
|
|
myLog.logMsg(MyLog.ERROR, "run] " + WCAException.displayError(WCAException.E_RECVERR_DATALEN, toString(), MyUtil.toHex(pLenBuff)));
|
|
if (adapter_logger.isError()) { adapter_logger.error(WCAException.displayError(WCAException.E_RECVERR_DATALEN, toString(), MyUtil.toHex(pLenBuff))); }
|
|
this.closeSoftLink();
|
|
}
|
|
catch (SocketTimeoutException ste) {
|
|
myLog.logMsg(MyLog.DEBUG, "run] SocketTimeoutException ocurrs");
|
|
nCheckOldWCAQueueCnt++;
|
|
if (WCADefine.DEFAULT_SOCK_RCV_TIMEOUT * nCheckOldWCAQueueCnt > WCADefine.DEFAULT_TRANSACTION_DELETE_TIMEOUT) {
|
|
myLog.logMsg(MyLog.DEBUG, "run] There is No Data to Read, Running...");
|
|
nCheckOldWCAQueueCnt = 0;
|
|
myLog.logMsg(MyLog.DEBUG, "run] Check Old WCAQueue...");
|
|
/*
|
|
long lCurrTime = System.currentTimeMillis();
|
|
// HashMap에 WCAQueue가 무한적 추가되는 것을 막기 위해서, 시간이 경과한 WCAQueue를 삭제함.
|
|
synchronized(hmapRcvData) {
|
|
Iterator iter = hmapRcvData.keySet().iterator();
|
|
while(iter.hasNext()) {
|
|
String sKey = (String)iter.next();
|
|
if (sKey == null) { if (trc_logger.isDebug()) trc_logger.debug("run] sKey is null");}
|
|
|
|
WCAQueue wcaQueue = (WCAQueue)hmapRcvData.get(sKey);
|
|
if (wcaQueue == null) { if (trc_logger.isDebug()) trc_logger.debug("run] wcaQueue is null");}
|
|
|
|
if (wcaQueue != null) {
|
|
long lTimeGap = lCurrTime - wcaQueue.lCreateTime;
|
|
|
|
if (lTimeGap > (WCADefine.DEFAULT_TRANSACTION_DELETE_TIMEOUT * 1000)) {
|
|
myLog.logMsg(MyLog.ERROR, "run] Delete TRANSACTION Queue, Key = " + sKey);
|
|
if (adapter_logger.isError()) adapter_logger.error(toString() + " Delete TRANSACTION Queue, Key = " + sKey);
|
|
hmapRcvData.remove(sKey);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
catch (java.net.SocketException socket) {
|
|
myLog.logMsg(MyLog.ERROR, "run] Error = " + socket.toString());
|
|
this.closeSoftLink();
|
|
}
|
|
catch (Exception e) {
|
|
myLog.logMsg(MyLog.ERROR, "run] Error = " + e.toString());
|
|
if (adapter_logger.isError()) { adapter_logger.error("[" + WCAException.E_ETC + "] " + toString() + " 프로그램 에러입니다. ", e); }
|
|
this.closeSoftLink();
|
|
}
|
|
}
|
|
|
|
// 어댑터 상태 체크
|
|
setAdapterStatus(true);
|
|
|
|
// 미처리 트랜잭션 출력
|
|
traceRemainTransaction();
|
|
|
|
// Thread 종료시 LOG 파일 close
|
|
myLog.logMsg(MyLog.INFO, "run] " + toString() + " Thread is Stopped");
|
|
|
|
//adapter_logger.debug(toString() + " Thread is Stopped");
|
|
closeLogStream();
|
|
}
|
|
|
|
|
|
/**
|
|
* 1. 기능 : 수신 데이타 처리
|
|
* 2. 처리 개요 :
|
|
* - 수신 데이타 트레이스 파일에 로깅
|
|
* - DATA TYPE에 따라 각 처리 함수로 분기한다.
|
|
* 3. 주의사항
|
|
**/
|
|
public void handleRcvData(int nLen, byte[] pBuff) {
|
|
String sDataType = null;
|
|
|
|
boolean isLogFirstData = false;
|
|
String strFirstData = "";
|
|
|
|
String luName = "";
|
|
String threadName = "";
|
|
long startTime = 0;
|
|
|
|
WCAHeader wcaHeader = new WCAHeader(WCAHeader.WCA_HEADER_LEN, pBuff);
|
|
|
|
nRcvCnt++;
|
|
// 트레이스 로깅
|
|
/*
|
|
synchronized(myTrc) {
|
|
myTrc.logMsg("SoftLink -> WCA (LEN = " + nLen + ")");
|
|
myTrc.logMsg("WCA Header : " + wcaHeader.toString());
|
|
myTrc.logData(WCADefine.EBCDIC_CODE, nLen, pBuff);
|
|
}
|
|
*/
|
|
sDataType = wcaHeader.getDataType();
|
|
|
|
myLog.logMsg(MyLog.INFO, "handleRcvData] Receive DATA_TYPE VALUE = " + sDataType );
|
|
|
|
// 송신 완료
|
|
if (sDataType.equals(WCAHeader.DATA_TYPE_SEND_OK)) {
|
|
myLog.logMsg(MyLog.DEBUG, "handleRcvData] Status Mode : Send OK ");
|
|
handleSendOK(nLen, pBuff);
|
|
}
|
|
else if (sDataType.equals(WCAHeader.DATA_TYPE_TIMEOUT_ONLY) || sDataType.equals(WCAHeader.DATA_TYPE_TIMEOUT_LAST)) {
|
|
myLog.logMsg(MyLog.DEBUG, "handleRcvData] Status Mode : Timeout ");
|
|
handleTimeout(nLen, pBuff);
|
|
}
|
|
else if (sDataType.equals(WCAHeader.DATA_TYPE_NORMAL_FIRST) || sDataType.equals(WCAHeader.DATA_TYPE_NORMAL_MIDDLE) ||
|
|
sDataType.equals(WCAHeader.DATA_TYPE_DFS_FIRST) || sDataType.equals(WCAHeader.DATA_TYPE_DFS_MIDDLE) ||
|
|
sDataType.equals(WCAHeader.DATA_TYPE_TIMEOUT_FIRST) || sDataType.equals(WCAHeader.DATA_TYPE_TIMEOUT_MIDDLE)) {
|
|
myLog.logMsg(MyLog.DEBUG, "handleRcvData] Status Mode : Normal First, Normal Middle, Delay First, Delat Middel ");
|
|
handleData(nLen, pBuff);
|
|
}
|
|
else if (sDataType.equals(WCAHeader.DATA_TYPE_NORMAL_ONLY) || sDataType.equals(WCAHeader.DATA_TYPE_NORMAL_LAST) ||
|
|
sDataType.equals(WCAHeader.DATA_TYPE_DFS_ONLY) || sDataType.equals(WCAHeader.DATA_TYPE_DFS_LAST)) {
|
|
/// DEBUG_LOG : 20200406
|
|
isLogFirstData = false;
|
|
|
|
// 운영 환경이 기본 로그 레벨이 warn임, 20200406 가용성 테스트 이후에 isInfo으로 변경 해야 함. (KB 김양규 차장님 요청 사항)
|
|
if (adapter_logger.isInfo()) {
|
|
// if (adapter_logger.isError()) {
|
|
if (nLen > WCAHeader.WCA_HEADER_LEN + 60) {
|
|
isLogFirstData = true;
|
|
|
|
byte[] bFirstData = new byte[60];
|
|
System.arraycopy(pBuff, WCAHeader.WCA_HEADER_LEN, bFirstData, 0, 60);
|
|
|
|
strFirstData = new String(CodeCvrt.cvrtEbc2Ksc(bFirstData));
|
|
luName = wcaHeader.getLUName();
|
|
threadName = Thread.currentThread().getName();
|
|
|
|
adapter_logger.error("handleRcvData> ST " + threadName + ", " + luName + ", " + strFirstData);
|
|
|
|
startTime = System.currentTimeMillis();
|
|
}
|
|
}
|
|
|
|
myLog.logMsg(MyLog.DEBUG, "handleRcvData] Status Mode : NORML_ONLY, NORML_LAST, DFS");
|
|
handleNormalDFS(nLen, pBuff);
|
|
|
|
if (isLogFirstData == true) {
|
|
long endTime = System.currentTimeMillis();
|
|
long elapseTime = endTime - startTime;
|
|
|
|
adapter_logger.error("handleRcvData> EN " + threadName + ", " + luName + ", " + strFirstData + ", " + elapseTime);
|
|
|
|
if (elapseTime > 5000) {
|
|
adapter_logger.error("handleRcvData> OVEROVERTIME " + elapseTime + ", " + threadName + ", " + luName + ", " + strFirstData);
|
|
}
|
|
else if (elapseTime > 1000) {
|
|
adapter_logger.error("handleRcvData> OVERTIME " + elapseTime + ", " + threadName + ", " + luName + ", " + strFirstData);
|
|
}
|
|
}
|
|
}
|
|
else if (sDataType.equals(WCAHeader.DATA_TYPE_ERROR)) {
|
|
myLog.logMsg(MyLog.DEBUG, "handleRcvData] Status Mode : Error");
|
|
handleError(nLen, pBuff);
|
|
}
|
|
else if (sDataType.equals(WCAHeader.DATA_TYPE_ADAPTER_ERROR) || sDataType.equals(WCAHeader.DATA_TYPE_ADAPTER_OK)) {
|
|
myLog.logMsg(MyLog.DEBUG, "handleRcvData] Status Mode : DATA_TYPE_ADAPTER_ERROR, DATA_TYPE_ADAPTER_OK");
|
|
handleAutoBackup(nLen, pBuff);
|
|
}
|
|
else if (sDataType.equals(WCAHeader.DATA_TYPE_GET_ADAPTER_STATUS)) {
|
|
myLog.logMsg(MyLog.DEBUG, "handleRcvData] Status Mode : DATA_TYPE_GET_ADAPTER_STATUS");
|
|
handleAutoBackup(nLen, pBuff);
|
|
}
|
|
else {
|
|
myLog.logMsg(MyLog.ERROR, "handleRcvData] " + WCAException.displayError(WCAException.E_SOFTLINK_UNKNOWN_COMMAND, toString(), sDataType));
|
|
if (adapter_logger.isError()) { adapter_logger.error(WCAException.displayError(WCAException.E_SOFTLINK_UNKNOWN_COMMAND, toString(), sDataType)); }
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 송신 완료 (Send OK) 데이타 처리
|
|
* 2. 처리 개요 :
|
|
* - NONRESPONSE 모드 :
|
|
* 1. 송신 Queue에 있을 경우 : 데이타 수신했음을 알려준다.
|
|
* 2. 송신 Queue에 없을 경우 : 타임아웃 데이타로 INBOUND handleTimeoutData 핸들러로 보낸다.
|
|
* - RESPONSE 모드 : 수신 데이타 대기한다.
|
|
* 3. 주의사항
|
|
**/
|
|
public void handleSendOK(int nLen, byte[] pBuff) {
|
|
myLog.logMsg(MyLog.DEBUG, "handleRcvData] Receive STATUS_SENDOK...");
|
|
|
|
String sKey = null;
|
|
|
|
WCAHeader wcaHeader = new WCAHeader(WCAHeader.WCA_HEADER_LEN, pBuff);
|
|
|
|
char cMode = wcaHeader.getMode();
|
|
myLog.logMsg(MyLog.DEBUG, "handleSendOK] Tran Mode = " + cMode);
|
|
|
|
sKey = getKey(wcaHeader);
|
|
myLog.logMsg(MyLog.DEBUG, "handleSendOK] Key = " + sKey);
|
|
|
|
/* NONRESPONSE 모드 */
|
|
if (cMode == (WCAHeader.TRAN_MODE_NONRESPONSE).charAt(0)) {
|
|
myLog.logMsg(MyLog.DEBUG, "handleSendOK] Response Mode = MODE_NONRESPONSE");
|
|
|
|
WCAQueue queueWSA = null;
|
|
synchronized (hmapRcvData) {
|
|
queueWSA = (WCAQueue)hmapRcvData.remove(sKey);
|
|
}
|
|
|
|
if (queueWSA != null) {
|
|
synchronized (queueWSA) {
|
|
queueWSA.setRecvSendOKFlag(true);
|
|
WCAQueueData qdataWSA = new WCAQueueData(nLen, pBuff);
|
|
myLog.logMsg(MyLog.DEBUG, "handleSendOK] Add Queue Data, Length = " + nLen);
|
|
queueWSA.addDataToQueue(qdataWSA);
|
|
myLog.logMsg(MyLog.DEBUG, "handleSendOK] Notify WLI Thread...");
|
|
queueWSA.notifyAll();
|
|
lNotifyEndTime = System.currentTimeMillis();
|
|
String dateString = formatter.format(ZonedDateTime.now());
|
|
if (adapter_logger.isDebug()) { adapter_logger.debug(dateString + " : WCA_PROCESSIING_TIME = " + (lNotifyEndTime - lReadEndTime)); }
|
|
}
|
|
}
|
|
else {
|
|
if (wcaEventHandler != null) {
|
|
myLog.logMsg(MyLog.DEBUG, "handleSendOK] Call Event Handler : handleTimeoutData()");
|
|
wcaEventHandler.handleTimeoutData(sAdapterGroupName, sAdapterName, sGroupCode, nLen, pBuff);
|
|
}
|
|
else {
|
|
myLog.logMsg(MyLog.ERROR, "handleSendOK] Event Handler is Not Registered, So Discard Data...");
|
|
}
|
|
}
|
|
}
|
|
else if (cMode == (WCAHeader.TRAN_MODE_RESPONSE).charAt(0) || cMode == (WCAHeader.TRAN_MODE_TERMINAL).charAt(0)) {
|
|
myLog.logMsg(MyLog.DEBUG, "handleSendOK] Response Mode = MODE_RESPONSE");
|
|
myLog.logMsg(MyLog.DEBUG, "handleSendOK] Wait Host Data...");
|
|
WCAQueue queueWSA = null;
|
|
synchronized (hmapRcvData){
|
|
queueWSA = (WCAQueue)hmapRcvData.get(sKey);
|
|
if (queueWSA != null)
|
|
queueWSA.setRecvSendOKFlag(true);
|
|
}
|
|
}
|
|
else {
|
|
myLog.logMsg(MyLog.ERROR, "handleSendOK] Receive Unknown Mode, Mode = " + cMode);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : Timeout 데이타 처리
|
|
* 2. 처리 개요 :
|
|
* - TIMOUT 첫번째 데이타일 경우 (DATA_TYPE_TIMEOUT_ONLY) :
|
|
* 수신데이타를 INBOUND 핸들러로 보낸다.
|
|
* - TIMOUT 데이타가 하나이상의 패킷일 경우 :
|
|
* Queue에 저장된 키값을 구한다. (key값이 없을 경우 에러로그만 남긴다.)
|
|
* 1. 송신 Queue에 있을 경우 : 수신된 모든 데이타를 INBOUND 핸들러로 보낸다.
|
|
* 2. 송신 Queue에 없을 경우 : 현재 받은 데이타만 INBOUND 핸들러로 보낸다.
|
|
* 3. 주의사항
|
|
**/
|
|
public void handleTimeout(int nLen, byte[] pBuff) {
|
|
String sKey = null;
|
|
String sDataType = null;
|
|
byte[] pRecvBuff = null;
|
|
char cMode;
|
|
|
|
WCAHeader wcaHeader = new WCAHeader(WCAHeader.WCA_HEADER_LEN, pBuff);
|
|
|
|
sDataType = wcaHeader.getDataType();
|
|
myLog.logMsg(MyLog.DEBUG, "handleTimeout] Data Type = " + sDataType);
|
|
cMode = wcaHeader.getMode();
|
|
myLog.logMsg(MyLog.DEBUG, "handleTimeout] Tran Mode = " + cMode);
|
|
|
|
if (sDataType.equals(WCAHeader.DATA_TYPE_TIMEOUT_ONLY)){
|
|
pRecvBuff = pBuff;
|
|
}
|
|
else {
|
|
sKey = getKey(wcaHeader);
|
|
if (sKey == null) {
|
|
myLog.logMsg(MyLog.ERROR, "handleTimeout] Key is NULL" );
|
|
if (adapter_logger.isError()) { adapter_logger.error("handleTimeout] - " + WCAException.displayError(WCAException.E_RECVDATA_ERROR, toString(), "Key is NULL")); }
|
|
return;
|
|
}
|
|
|
|
WCAQueue queueWSA = null;
|
|
synchronized (hmapRcvData) {
|
|
queueWSA = (WCAQueue)hmapRcvData.remove(sKey);
|
|
}
|
|
|
|
if (queueWSA != null) {
|
|
synchronized (queueWSA) {
|
|
WCAQueueData qdataWSA = new WCAQueueData(nLen, pBuff);
|
|
myLog.logMsg(MyLog.DEBUG,"handleTimeout] Add Queue Data, Length = " + nLen);
|
|
queueWSA.addDataToQueue(qdataWSA);
|
|
}
|
|
pRecvBuff = queueWSA.getDataFromQueue();
|
|
}
|
|
else {
|
|
myLog.logMsg(MyLog.ERROR, "handleTimeout] - [" + WCAException.E_SOFTLINK_RECV_DATA_NOTFOUND + "] Queue Data doesn't existed....");
|
|
if (adapter_logger.isError()) { adapter_logger.error("handleTimeout] - [" + WCAException.E_SOFTLINK_RECV_DATA_NOTFOUND + "] " + toString() + " Queue Data doesn't existed...."); }
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (wcaEventHandler != null) {
|
|
myLog.logMsg(MyLog.DEBUG, "handleTimeout] Call Event Handler : handleTimeoutData()");
|
|
wcaEventHandler.handleTimeoutData(sAdapterGroupName, sAdapterName, sGroupCode, pRecvBuff.length, pRecvBuff);
|
|
}
|
|
else {
|
|
myLog.logMsg(MyLog.ERROR, "handleTimeout] Event Handler is Not Registered, So Discard Data...");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 수신 데이타를 Queue에 저장한다.
|
|
* 2. 처리 개요 :
|
|
* - DATA TYPE이 FIRST, MIDDEL인 경우 Queue에 저장될 key 값을 구하여 Queue 값을 구한다.
|
|
* - Queue에 수신데이타 저장 값이 있을 경우 Queue 데이타를 추가하며,
|
|
* 없을 경우 Queue를 생성하여 Queue 데이타를 추가한다.
|
|
* - Respnse 모드이고 timeout 데이타인 경우 setResTimeoutFlag(true)을 설정해준다.
|
|
* (차후 INBOUND 핸들러로 보내기 위함)
|
|
* 3. 주의사항
|
|
*
|
|
**/
|
|
public void handleData(int nLen, byte[] pBuff) {
|
|
String sKey = null;
|
|
|
|
WCAHeader wcaHeader = new WCAHeader(WCAHeader.WCA_HEADER_LEN, pBuff);
|
|
|
|
sKey = getKey(wcaHeader);
|
|
if (sKey == null) {
|
|
myLog.logMsg(MyLog.ERROR, "handleData] - "+ WCAException.displayError(WCAException.E_RECVDATA_ERROR, toString(), "Key is NULL"));
|
|
if (adapter_logger.isError()) { adapter_logger.error("handleData] - "+ WCAException.displayError(WCAException.E_RECVDATA_ERROR, toString(), "Key is NULL")); }
|
|
return;
|
|
}
|
|
|
|
WCAQueue queueWSA = null;
|
|
synchronized (hmapRcvData) {
|
|
queueWSA = (WCAQueue)hmapRcvData.get(sKey);
|
|
}
|
|
|
|
// Status가 DATA_TYPE_TIMEOUT_FIRST인 경우 LUNAME으로 Hashmap에 저장한다.
|
|
String sDataType = wcaHeader.getDataType();
|
|
char cMode = wcaHeader.getMode();
|
|
myLog.logMsg(MyLog.DEBUG, "handleData] Data Type = " + sDataType + ", Mode = " + cMode);
|
|
|
|
if (queueWSA == null) {
|
|
queueWSA = new WCAQueue();
|
|
registerRcvQueue(sKey, queueWSA);
|
|
|
|
// DFS가 아니고 response 모드인 경우 -> 타임아웃데이타
|
|
if ((String.valueOf(cMode).equals(WCAHeader.TRAN_MODE_RESPONSE) || String.valueOf(cMode).equals(WCAHeader.TRAN_MODE_TERMINAL)) &&
|
|
!sDataType.substring(0,1).equals(WCAHeader.DATA_TYPE_DFS_PREFIX)) {
|
|
queueWSA.setResTimeoutFlag(true);
|
|
}
|
|
}
|
|
|
|
if (queueWSA != null) {
|
|
synchronized (queueWSA) {
|
|
WCAQueueData qdataWSA = new WCAQueueData(nLen, pBuff);
|
|
myLog.logMsg(MyLog.DEBUG,"handleData] Add Queue Data, Length = " + nLen);
|
|
queueWSA.addDataToQueue(qdataWSA);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : Normal Data 및 DFS 데이타를 처리한다.
|
|
* 2. 처리 개요 :
|
|
* - NONRESPONSE 모드 :
|
|
* 1. Queue에 있을 경우 : 수신된 모든 데이타를 INBOUND 핸들러로 보낸다.
|
|
* 2. Queue에 없을 경우 : 수신된 현재 데이타를 INBOUND 핸들러로 보낸다.
|
|
* - RESPONSE 모드 :
|
|
* 1. Queue에 있을 경우 : RESPONSE 모드이고 TIMEOUT 데이타이면 INBOUND 핸들러로 보낸다.
|
|
* 그외의 경우 데이타 수신했음을 알려준다. (notify)
|
|
* 2. Queue에 없을 경우 : timeout 데이타로 INBOUND 핸들러로 보낸다.
|
|
* 3. 주의사항
|
|
*
|
|
**/
|
|
public void handleNormalDFS(int nLen, byte[] pBuff) {
|
|
String sKey = null;
|
|
char cMode;
|
|
byte[] pRecvBuff = null;
|
|
|
|
WCAHeader wcaHeader = new WCAHeader(WCAHeader.WCA_HEADER_LEN, pBuff);
|
|
|
|
sKey = getKey(wcaHeader);
|
|
if (sKey == null) {
|
|
myLog.logMsg(MyLog.ERROR, "handleNormalDFS] - " + WCAException.displayError(WCAException.E_RECVDATA_ERROR, toString(), "Key is NULL"));
|
|
if (adapter_logger.isError()) { adapter_logger.error("handleNormalDFS] - " + WCAException.displayError(WCAException.E_RECVDATA_ERROR, toString(), "Key is NULL")); }
|
|
return;
|
|
}
|
|
|
|
cMode = wcaHeader.getMode();
|
|
myLog.logMsg(MyLog.DEBUG, "handleNormalDFS] Tran Mode = " + cMode);
|
|
|
|
if (cMode == (WCAHeader.TRAN_MODE_NONRESPONSE).charAt(0)) {
|
|
WCAQueue queueWSA = null;
|
|
synchronized(hmapRcvData) {
|
|
queueWSA = (WCAQueue)hmapRcvData.remove(sKey);
|
|
}
|
|
|
|
if (queueWSA != null) {
|
|
synchronized (queueWSA) {
|
|
WCAQueueData qdataWSA = new WCAQueueData(nLen, pBuff);
|
|
myLog.logMsg(MyLog.DEBUG,"handleNormalDFS] Add Queue Data, Length = " + nLen);
|
|
queueWSA.addDataToQueue(qdataWSA);
|
|
}
|
|
pRecvBuff = queueWSA.getDataFromQueue();
|
|
}
|
|
else {
|
|
pRecvBuff = pBuff;
|
|
myLog.logMsg(MyLog.DEBUG, "handleNormalDFS] - [" + WCAException.E_SOFTLINK_RECV_DATA_NOTFOUND +"] Queue Data doesn't existed....");
|
|
}
|
|
|
|
if (wcaEventHandler != null) {
|
|
myLog.logMsg(MyLog.DEBUG, "handleNormalDFS] Call Event Handler : handleNonRspData()");
|
|
wcaEventHandler.handleNonRspData(sAdapterGroupName, sAdapterName, sGroupCode, pRecvBuff.length, pRecvBuff);
|
|
}
|
|
else {
|
|
myLog.logMsg(MyLog.ERROR, "handleNormalDFS] Event Handler is Not Registered, So Discard Data...");
|
|
}
|
|
}
|
|
else if (cMode == (WCAHeader.TRAN_MODE_RESPONSE).charAt(0) || cMode == (WCAHeader.TRAN_MODE_TERMINAL).charAt(0)) {
|
|
WCAQueue queueWSA = null;
|
|
synchronized (hmapRcvData) {
|
|
queueWSA = (WCAQueue)hmapRcvData.remove(sKey);
|
|
}
|
|
|
|
if (queueWSA != null) {
|
|
synchronized (queueWSA) {
|
|
WCAQueueData qdataWSA = new WCAQueueData(nLen, pBuff);
|
|
myLog.logMsg(MyLog.DEBUG,"handleNormalDFS] Add Queue Data, Length = " + nLen);
|
|
queueWSA.addDataToQueue(qdataWSA);
|
|
|
|
// timeout데이타일 경우
|
|
if (queueWSA.getResTimeoutFlag()) {
|
|
pRecvBuff = queueWSA.getDataFromQueue();
|
|
if (wcaEventHandler != null) {
|
|
myLog.logMsg(MyLog.DEBUG, "handleNormalDFS] Call Event Handler : handleTimeoutData()");
|
|
wcaEventHandler.handleTimeoutData(sAdapterGroupName, sAdapterName, sGroupCode, pRecvBuff.length, pRecvBuff);
|
|
}
|
|
else {
|
|
myLog.logMsg(MyLog.ERROR, "handleNormalDFS] Event Handler is Not Registered, So Discard Data...");
|
|
}
|
|
}
|
|
else {
|
|
myLog.logMsg(MyLog.DEBUG, "handleNormalDFS] Notify WLI Thread...");
|
|
|
|
// 20200724 Start
|
|
if (adapter_logger.isInfo()) { adapter_logger.debug("Before Notify WLI Thread, " + sAdapterGroupName + ", " + sAdapterName + ", " + sGroupCode); }
|
|
// 20200724 End
|
|
|
|
queueWSA.notifyAll();
|
|
|
|
// 20200724 Start
|
|
if (adapter_logger.isInfo()) { adapter_logger.debug("After Notify WLI Thread, " + sAdapterGroupName + ", " + sAdapterName + ", " + sGroupCode); }
|
|
// 20200724 End
|
|
|
|
lNotifyEndTime = System.currentTimeMillis();
|
|
String dateString = formatter.format(ZonedDateTime.now());
|
|
|
|
// 20200724 Start
|
|
// 로그 레벨 변경
|
|
// if (adapter_logger.isDebug()) { adapter_logger.debug(dateString + " : WCA_PROCESSIING_TIME = " + (lNotifyEndTime - lReadEndTime)); }
|
|
if (adapter_logger.isInfo()) { adapter_logger.info(dateString + " : WCA_PROCESSIING_TIME = " + (lNotifyEndTime - lReadEndTime)); }
|
|
// 20200724 End
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (wcaEventHandler != null) {
|
|
myLog.logMsg(MyLog.DEBUG, "handleNormalDFS] Call Event Handler : handleTimeoutData()");
|
|
wcaEventHandler.handleTimeoutData(sAdapterGroupName, sAdapterName, sGroupCode, nLen, pBuff);
|
|
}
|
|
else {
|
|
myLog.logMsg(MyLog.ERROR, "handleNormalDFS] Event Handler is Not Registered, So Discard Data...");
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
myLog.logMsg(MyLog.ERROR, "handleNormalDFS] Receive Unknown Mode, Mode = " + cMode);
|
|
adapter_logger.error("handleNormalDFS] - " + WCAException.displayError(WCAException.E_SOFTLINK_UNKNOWN_COMMAND, toString(), "Unknown Mode = " + cMode) );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : ERROR Data 및 DFS 데이타를 처리한다.
|
|
* 2. 처리 개요 :
|
|
* - Queue에 있을 경우 :
|
|
* 1. "LU사용중"이라는 에러코드인 경우 setResendFlag(true)로 설정한다.
|
|
* (차후 다른 LU 그룹으로 Resend 하기 위함)
|
|
* 2. 그외의 경우 : 그외의 경우 데이타 수신했음을 알려준다. (notify)
|
|
* - Queue에 없을 경우 : 수신된 데이타를 INBOUND 핸들러로 보낸다.
|
|
* 3. 주의사항
|
|
*
|
|
**/
|
|
public void handleError(int nLen, byte[] pBuff) {
|
|
String sKey = null;
|
|
byte[] bErrCode = new byte[WCAException.SOFTLINK_ERROR_SIZE];
|
|
byte[] bErrMsg = null;
|
|
|
|
WCAHeader wcaHeader = new WCAHeader(WCAHeader.WCA_HEADER_LEN, pBuff);
|
|
|
|
if (nLen >= (WCAHeader.WCA_HEADER_LEN + WCAException.SOFTLINK_ERROR_SIZE)) {
|
|
System.arraycopy(pBuff, WCAHeader.WCA_HEADER_LEN, bErrCode, 0, WCAException.SOFTLINK_ERROR_SIZE);
|
|
String sErrCode = new String(bErrCode);
|
|
myLog.logMsg(MyLog.DEBUG, "handleError] ErrCode = " + sErrCode);
|
|
}
|
|
|
|
if (nLen > (WCAHeader.WCA_HEADER_LEN + WCAException.SOFTLINK_ERROR_SIZE)) {
|
|
bErrMsg = new byte[nLen - WCAHeader.WCA_HEADER_LEN - WCAException.SOFTLINK_ERROR_SIZE];
|
|
System.arraycopy(pBuff, WCAHeader.WCA_HEADER_LEN + WCAException.SOFTLINK_ERROR_SIZE, bErrMsg, 0, nLen - WCAHeader.WCA_HEADER_LEN - WCAException.SOFTLINK_ERROR_SIZE);
|
|
String sErrMsg = new String(bErrMsg);
|
|
myLog.logMsg(MyLog.DEBUG, "handleError] ErrMsg = " + sErrMsg);
|
|
}
|
|
|
|
sKey = getKey(wcaHeader);
|
|
myLog.logMsg(MyLog.DEBUG, "handleError] Key = " + sKey);
|
|
|
|
if (bErrCode != null && bErrMsg != null) {
|
|
String sRecvErrCode = new String(bErrCode);
|
|
if (adapter_logger.isError()) { adapter_logger.error("[" + sRecvErrCode+"] " + toString() + " " + sKey + " : " + new String(bErrMsg)); }
|
|
}
|
|
|
|
WCAQueue queueWSA = null;
|
|
synchronized (hmapRcvData) {
|
|
queueWSA = (WCAQueue)hmapRcvData.remove(sKey);
|
|
}
|
|
|
|
if (queueWSA != null) {
|
|
// 해당 LU 세션이 사용중, 다운일 경우 다른 LU 세션으로 보낸다.
|
|
if (new String(bErrCode).equals(WCAException.E_HOST_LU_DOWN) || new String(bErrCode).equals(WCAException.E_HOST_LU_IN_USED)
|
|
|| new String(bErrCode).equals(WCAException.E_HOST_LU_NON_EXIST)) {
|
|
queueWSA.setResendFlag(true);
|
|
}
|
|
|
|
synchronized (queueWSA) {
|
|
WCAQueueData qdataWSA = new WCAQueueData(nLen, pBuff);
|
|
myLog.logMsg(MyLog.DEBUG,"handleError] Add Queue Data, Length = " + nLen);
|
|
queueWSA.addDataToQueue(qdataWSA);
|
|
myLog.logMsg(MyLog.DEBUG, "handleError] Notify WLI Thread...");
|
|
queueWSA.notifyAll();
|
|
lNotifyEndTime = System.currentTimeMillis();
|
|
String dateString = formatter.format(ZonedDateTime.now());
|
|
if (adapter_logger.isDebug()) adapter_logger.debug(dateString + " : WCA_PROCESSIING_TIME = " + (lNotifyEndTime - lReadEndTime));
|
|
}
|
|
}
|
|
else {
|
|
/*
|
|
if (wcaEventHandler != null) {
|
|
myLog.logMsg(MyLog.DEBUG, "handleError] Call Event Handler : handleTimeoutData()");
|
|
wcaEventHandler.handleTimeoutData(sAdapterGroupName, sAdapterName, nLen, pBuff);
|
|
}
|
|
else {
|
|
myLog.logMsg(MyLog.ERROR, "handleError] Event Handler is Not Registered, So Discard Data...");
|
|
}
|
|
*/
|
|
myLog.logMsg(MyLog.DEBUG, "handleError] Doesnt' Exist Data in Queue!!");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 수동 백업 및 복구 명령을 처리한다.
|
|
* 2. 처리 개요 :
|
|
* - DATA_TYPE_ADAPTER_ERROR 인 경우 : 해당 어댑터 그룹, LU 그룹을 백업모드로 전환한다.
|
|
* - DATA_TYPE_ADAPTER_OK 인 경우 : 해당 어댑터 그룹, LU 그룹을 백업모드에서 복귀한다.
|
|
* 3. 주의사항
|
|
*
|
|
**/
|
|
public void handleAutoBackup(int nLen, byte[] pBuff) {
|
|
ManualBackupCmd cmd = new ManualBackupCmd(ManualBackupCmd.BACKUP_CMD_LEN, pBuff);
|
|
|
|
String sBackupAdapterGrpName = null;
|
|
String sBackupLUGrpName = null;
|
|
|
|
try {
|
|
String sDataType = cmd.getDataType();
|
|
sBackupAdapterGrpName = cmd.getAdapterGrpName();
|
|
sBackupLUGrpName = cmd.getLUGrpName();
|
|
|
|
// 20090810 Start
|
|
if (bBackupEnableFlag == false) {
|
|
myLog.logMsg(MyLog.NOTICE, "handleAutoBackup] Backup Enable Flag is False, So Ignore 자동 백업 명령 (" +
|
|
sBackupAdapterGrpName + "/" + sNodeName + "/" + sBackupLUGrpName + ")");
|
|
return;
|
|
}
|
|
// 20090810 End
|
|
|
|
// 수동 백업 전환
|
|
if (sDataType.equals(ManualBackupCmd.DATA_TYPE_ADAPTER_ERROR)) {
|
|
myLog.logMsg(MyLog.NOTICE, "handleAutoBackup] 자동 백업 명령 수신 (" + sBackupAdapterGrpName + "/" + sNodeName + "/" + sBackupLUGrpName + ")");
|
|
adapter_logger.warn("handleAutoBackup] - " + toString() + " 자동 백업 명령 수신 " + sBackupAdapterGrpName + "/" + sBackupLUGrpName);
|
|
|
|
if (bBackupEnableFlag == true) {
|
|
if (isBackupSessionPool()) { return; }
|
|
snaAdapter.setAutoBackupMode(sNodeName, sBackupLUGrpName, true);
|
|
}
|
|
else {
|
|
myLog.logMsg(MyLog.NOTICE, "handleAutoBackup] bBackupEnableFlag is False, So Ignore Data");
|
|
adapter_logger.warn("handleAutoBackup] bBackupEnableFlag is False, So Ignore Data");
|
|
}
|
|
// 20090810 End
|
|
}
|
|
else { // 수동 복구 전환
|
|
myLog.logMsg(MyLog.NOTICE, "handleAutoBackup] 자동 복구 명령 수신 (" + sBackupAdapterGrpName + "/" + sBackupLUGrpName + ")");
|
|
adapter_logger.warn("handleAutoBackup] - " + toString() + " 자동 복구 명령 수신 " + sBackupAdapterGrpName + "/" + sBackupLUGrpName);
|
|
|
|
if (bBackupEnableFlag == true) {
|
|
if (isBackupSessionPool()) { return; }
|
|
snaAdapter.setAutoBackupMode(sNodeName, sBackupLUGrpName, false);
|
|
}
|
|
else {
|
|
myLog.logMsg(MyLog.NOTICE, "handleAutoBackup] bBackupEnableFlag is False, So Ignore Data");
|
|
adapter_logger.warn("handleAutoBackup] bBackupEnableFlag is False, So Ignore Data");
|
|
}
|
|
// 20090810 End
|
|
}
|
|
}
|
|
catch (WCAException e) {
|
|
// 해당 세션을 찾지 못하였을 경우
|
|
if (e.getErrorReturnCode().equals(WCAException.E_SOFTLINK_NOT_FOUND_SESSION)) {
|
|
adapter_logger.error(WCAException.displayError(WCAException.E_SOFTLINK_NOT_FOUND_SESSION, "백업 전환/복구 세션 시 발생[" + sBackupAdapterGrpName + "/" + sBackupLUGrpName + "]"));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* 1. 기능 : Header 데이타에서 Queue에 저장된 Key 값 추출
|
|
* 2. 처리 개요 :
|
|
* - Transaction Key가 없는경우 LU 이름으로 한다.
|
|
* 3. 주의사항
|
|
*
|
|
**/
|
|
private String getKey(WCAHeader wcaHeader) {
|
|
String sKey = wcaHeader.getKey();
|
|
|
|
if (sKey == null || (sKey != null && sKey.equals(new String(WCAHeader.NULL_TRANKEY)))) {
|
|
myLog.logMsg(MyLog.DEBUG, "getKey] Key is null or empty, So LuName is Key " );
|
|
sKey = wcaHeader.getLUName().trim();
|
|
}
|
|
myLog.logMsg(MyLog.DEBUG, "getKey] Key = (" + sKey + ")");
|
|
|
|
if (sKey == null || (sKey != null && sKey.equals(new String(WCAHeader.NULL_TSNAME)))) {
|
|
myLog.logMsg(MyLog.DEBUG, "getKey] Key, LuName is null or empty" );
|
|
return null;
|
|
}
|
|
|
|
return sKey;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : SoftLink 세션을 통해서 데이터를 수신한다.
|
|
* 2. 처리 개요 :
|
|
* - SoftLink 세션을 통해서 파라미터인 nDataLen 값 만큼 데이터를 수신한다.
|
|
* - 정해진 데이터를 nTimeout시간안에 수신하지 못하면 장애처리 한다.
|
|
* 3. 주의사항
|
|
* - 이 함수를 호출하기 전에 먼저 데이터 길이 필드를 수신한 해야 한다.
|
|
*
|
|
* @param nTimeout 데이터 수신 Timeout
|
|
* @param nDataLen 수신할 데이터 길이
|
|
* @return pBuff 수신된 데이터가 저장된 버퍼
|
|
*/
|
|
public byte[] recvDataField(int nTimeout, int nDataLen) {
|
|
byte[] pBuff = null;
|
|
int nRcvLen = 0;
|
|
int nRemainLen = 0;
|
|
int nBuffPos = 0;
|
|
long lStartTime = 0;
|
|
long lCurrTime = 0;
|
|
|
|
try {
|
|
pBuff = new byte[nDataLen];
|
|
nRemainLen = nDataLen;
|
|
|
|
//sockSoftLink.setSoTimeout(1000);
|
|
sockSoftLink.setSoTimeout(0);
|
|
|
|
lStartTime = new Date().getTime();
|
|
|
|
myLog.logMsg(MyLog.DEBUG, "[Before Receiving Data] ");
|
|
while (nRemainLen > 0) {
|
|
nRcvLen = isSoftLink.read(pBuff, nBuffPos, nRemainLen);
|
|
if (nRcvLen < 0) {
|
|
myLog.logMsg(MyLog.ERROR, "recvDataField] " + WCAException.displayError(WCAException.E_SOFTLINK_NOTCONN, toString()) + " ( nRcvLen = " + nRcvLen + ")");
|
|
if (adapter_logger.isError()) { adapter_logger.error(WCAException.displayError(WCAException.E_SOFTLINK_NOTCONN, toString())); }
|
|
return null;
|
|
}
|
|
else {
|
|
nRemainLen -= nRcvLen;
|
|
nBuffPos += nRcvLen;
|
|
}
|
|
|
|
lCurrTime = new Date().getTime();
|
|
if (lCurrTime - lStartTime > (nTimeout * 1000)) {
|
|
sockSoftLink.setSoTimeout(0);
|
|
if (adapter_logger.isError()) { adapter_logger.error("recvDataField] - " + toString() + " Recv Timeout, StartTime = " + lStartTime + ", CurrTime = " + lCurrTime); }
|
|
myLog.logMsg(MyLog.ERROR, "recvDataField] Recv Timeout, StartTime = " + lStartTime + ", CurrTime = " + lCurrTime);
|
|
return null;
|
|
}
|
|
}
|
|
myLog.logMsg(MyLog.DEBUG, "[After Receiving Data] ");
|
|
sockSoftLink.setSoTimeout(0);
|
|
|
|
return pBuff;
|
|
}
|
|
catch(Exception e) {
|
|
myLog.logMsg(MyLog.ERROR, "recvDataField] Error :" + e.toString());
|
|
if (adapter_logger.isError()) { adapter_logger.error("recvDataField] " + WCAException.E_ETC + "] " + toString() + " Error :" + e.toString()); }
|
|
|
|
try {
|
|
sockSoftLink.setSoTimeout(0);
|
|
}
|
|
catch(SocketException se) {
|
|
myLog.logMsg(MyLog.ERROR, "recvDataField] Error :" + e.toString());
|
|
if (adapter_logger.isError()) { adapter_logger.error("recvDataField] - [" + WCAException.E_ETC + "] " + toString() + " Error :" + e.toString()); }
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public byte[] recvLenthField(int nDataLen) throws Exception {
|
|
byte[] pBuff = null;
|
|
int nRcvLen = 0;
|
|
int nRemainLen = 0;
|
|
int nBuffPos = 0;
|
|
|
|
try {
|
|
pBuff = new byte[nDataLen];
|
|
nRemainLen = nDataLen;
|
|
|
|
//sockSoftLink.setSoTimeout(1000 * WCADefine.DEFAULT_SOCK_RCV_TIMEOUT);
|
|
sockSoftLink.setSoTimeout(0);
|
|
|
|
myLog.logMsg(MyLog.DEBUG, "[Before Receiving Data Length] ");
|
|
while (nRemainLen > 0) {
|
|
nRcvLen = isSoftLink.read(pBuff, nBuffPos, nRemainLen);
|
|
if (nRcvLen < 0) {
|
|
myLog.logMsg(MyLog.ERROR, "recvLenthField] " + WCAException.displayError(WCAException.E_SOFTLINK_NOTCONN, toString()) + " ( nRcvLen = " + nRcvLen + ")");
|
|
if (adapter_logger.isError()) { adapter_logger.error(WCAException.displayError(WCAException.E_SOFTLINK_NOTCONN, toString())); }
|
|
return null;
|
|
}
|
|
else {
|
|
nRemainLen -= nRcvLen;
|
|
nBuffPos += nRcvLen;
|
|
}
|
|
}
|
|
|
|
myLog.logMsg(MyLog.DEBUG, "[After Receiving Data Length] ");
|
|
sockSoftLink.setSoTimeout(0);
|
|
|
|
return pBuff;
|
|
}
|
|
catch (Exception e) {
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : SoftLink TCP 세션 상태 설정
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @param 세션 상태
|
|
* 0 : 연결안됨, 1 : TCP 세션 연결, 2 : TCP 세션 사용중 (사용안함)
|
|
*/
|
|
public void setSessionStat(int nSessStat) {
|
|
this.nSessStat = nSessStat;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : SoftLink TCP 세션 이용 가능 상태 반환
|
|
* 2. 처리 개요 :
|
|
* - SESS_STAT_READY 일 경우 true 반환
|
|
* 3. 주의사항
|
|
*
|
|
* @param 세션 상태
|
|
* 0 : 연결안됨 (SESS_STAT_NOTCONN),
|
|
* 1 : TCP 세션 연결 (SESS_STAT_READY),
|
|
* 2 : TCP 세션 사용중 (SESS_STAT_INUSE - 사용안함)
|
|
*/
|
|
public boolean isAvailable() {
|
|
boolean bAvailable = false;
|
|
|
|
if (nSessStat == WCADefine.SESS_STAT_READY) {
|
|
bAvailable = true;
|
|
}
|
|
else {
|
|
bAvailable = false;
|
|
}
|
|
|
|
return bAvailable;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : Softlink와 연결된 세션수를 반환
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @return Softlink와 연결된 세션수
|
|
**/
|
|
public int getConnectedSessNum() {
|
|
int nSessNum = 0;
|
|
|
|
if (nSessStat > 0) {
|
|
nSessNum++;
|
|
}
|
|
|
|
return nSessNum;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 호스트로 송신한 데이터를 SoftLink 세션을 통해서 호트로 송신한다.
|
|
* 2. 처리 개요 :
|
|
* - 트레이스 파일에 해당 데이터를 트레이스한다.
|
|
* - 데이터의 내용을 호스트로 송신하기 위해 SoftLink 세션으로 송신한다.
|
|
* 3. 주의사항
|
|
* - 트레이스 처리의 동기화를 위해서 myTrc 클래스에 대한 동기화를 수행한다.
|
|
* - 송신 데이터 버퍼 형식 : 길이(4) + Data(n)
|
|
*
|
|
* @param nLen 송신할 데이터의 길이
|
|
* @param pBuff 송신할 데이터가 저장된 버퍼
|
|
* @return nLen 송신된 데이터 길이
|
|
* @exception WCAException
|
|
*/
|
|
public int sendData(int nLen, byte[] pBuff) throws WCAException {
|
|
byte[] pLenBuff = null;
|
|
long lStartTime = 0L, lEndTime = 0L;
|
|
WCAHeader wcaHeader = null;
|
|
|
|
try {
|
|
// 길이에 대한 길이 필드 생성
|
|
// 20090302 Start
|
|
// pLenBuff = MyUtil.getLenBuff(nLen, WCADefine.LEGTH_FIELD_SIZE);
|
|
pLenBuff = setInt(nLen);
|
|
// 20090302 End
|
|
|
|
wcaHeader = new WCAHeader(WCAHeader.WCA_HEADER_LEN, pBuff);
|
|
|
|
// 데이터 트레이스
|
|
/*
|
|
synchronized(myTrc) {
|
|
myTrc.logMsg("WCA -> SoftLink (LEN = " + nLen + ")");
|
|
myTrc.logMsg("WCA Header : " + wcaHeader.toString());
|
|
myTrc.logData(WCADefine.EBCDIC_CODE, nLen, pBuff);
|
|
}
|
|
*/
|
|
|
|
// 길이 필드 및 데이터 송신
|
|
synchronized (osSoftLink) {
|
|
String dateString = formatter.format(ZonedDateTime.now());
|
|
|
|
lStartTime = System.currentTimeMillis();
|
|
osSoftLink.write(pLenBuff, 0, WCADefine.LEGTH_FIELD_SIZE);
|
|
osSoftLink.write(pBuff, 0, nLen);
|
|
osSoftLink.flush();
|
|
lEndTime = System.currentTimeMillis();
|
|
|
|
if (adapter_logger.isDebug()) { adapter_logger.debug(dateString + " : WCA_SENDING_TIME = " + (lEndTime - lStartTime) + ", KEY = "+wcaHeader.getKey()); }
|
|
}
|
|
/*
|
|
synchronized(myTrc) {
|
|
myTrc.logMsg("[After Sending] WCA_SENDING_TIME = " + (lEndTime - lStartTime) + "("+wcaHeader.getKey() + ")");
|
|
myTrc.logMsg("[After Sending] WCA -> SoftLink : " + wcaHeader.toString());
|
|
}
|
|
*/
|
|
nSndCnt++;
|
|
return nLen;
|
|
}
|
|
catch (IOException ioe) {
|
|
adapter_logger.error(WCAException.E_SOFTLINK_SENDERR, ioe);
|
|
throw new WCAException(WCAException.E_SOFTLINK_SENDERR, ioe);
|
|
}
|
|
catch (Exception e) {
|
|
adapter_logger.error(WCAException.E_SOFTLINK_SENDERR, e);
|
|
throw new WCAException(WCAException.E_SOFTLINK_SENDERR, e);
|
|
}
|
|
}
|
|
|
|
// 20090810 Start
|
|
/**
|
|
* 1. 기능 : WCA 어댑터 APP_CODE 명령 전송
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @exception WCAException
|
|
*/
|
|
public void sendWcaSessionAppCode(boolean bSendAdapterInfo) throws WCAException
|
|
{
|
|
int nLen = 0;
|
|
byte[] pBuff = null;
|
|
byte[] pLenBuff = null;
|
|
String sAppCode = "";
|
|
// String sSendWcaAdapterInfo = "0";
|
|
StringBuffer sbAppCode = new StringBuffer();
|
|
|
|
// 20190828 Start
|
|
try {
|
|
/*
|
|
sSendWcaAdapterInfo = AdapterPropManager.getInstance().getProperty(sAdapterName, "SEND_WCA_ADAPTER_INFO");
|
|
if ("1".compareToIgnoreCase(sSendWcaAdapterInfo) == 0) {
|
|
this.sendWcaAdapterInfo();
|
|
}
|
|
*/
|
|
|
|
if (bSendAdapterInfo == true) {
|
|
this.sendWcaAdapterInfo();
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
adapter_logger.error(WCAException.E_SOFTLINK_SENDERR, e);
|
|
}
|
|
// 20190828 End
|
|
|
|
try {
|
|
// 어댑터 프라퍼티에 등록할 경우
|
|
sAppCode = AdapterPropManager.getInstance().getProperty(sAdapterName, "APP_CODE");
|
|
|
|
// For Test
|
|
// sDataCode = "ABC,DEF,XYZ";
|
|
|
|
// APP_CODE 값이 NULL 이거나 길이가 0이라도 Softlink APP 코드 정보를 클리어 하기 위해 보내야 함.
|
|
if (sAppCode == null) {
|
|
myLog.logMsg(MyLog.WARN, "sendWcaSessionAppCode> Data Code is null, So Send Dummy App Code to Softlink");
|
|
sAppCode = "";
|
|
sbAppCode.append(sAppCode);
|
|
}
|
|
else {
|
|
sAppCode = sAppCode.trim();
|
|
if (sAppCode.length() < 3) {
|
|
myLog.logMsg(MyLog.WARN, "sendWcaSessionAppCode> Data Code[" + sAppCode + "] is Invalid, So Send Dummy App Code to Softlink");
|
|
sAppCode = "";
|
|
sbAppCode.append(sAppCode);
|
|
}
|
|
else {
|
|
// 불필요한 공백 삭제
|
|
ArrayList alDataCode = MyUtil.stringTokenizer(sAppCode, ",");
|
|
if (alDataCode != null) {
|
|
for (int i = 0; i < alDataCode.size(); i++) {
|
|
String sTempDataCode = (String)alDataCode.get(i);
|
|
sbAppCode.append(sTempDataCode.trim());
|
|
|
|
// 마지막 항목이 아니면 "," 추가
|
|
if (i != (alDataCode.size() - 1)) {
|
|
sbAppCode.append(",");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
AppCodeCmd cmd = new AppCodeCmd(sbAppCode.toString());
|
|
|
|
pBuff = cmd.getData();
|
|
nLen = pBuff.length;
|
|
|
|
// 길이에 대한 길이 필드 생성
|
|
// 20090302 Start
|
|
// pLenBuff = MyUtil.getLenBuff(nLen, WCADefine.LEGTH_FIELD_SIZE);
|
|
pLenBuff = setInt(nLen);
|
|
// 20090302 End
|
|
|
|
myLog.logMsg(MyLog.WARN, "sendWcaSessionDataCode> App Code = " + sbAppCode.toString());
|
|
myLog.logData(WCADefine.ASCII_CODE, nLen, pBuff);
|
|
|
|
// 길이 필드 및 데이터 송신
|
|
synchronized (osSoftLink) {
|
|
osSoftLink.write(pLenBuff, 0, WCADefine.LEGTH_FIELD_SIZE);
|
|
osSoftLink.write(pBuff, 0, nLen);
|
|
osSoftLink.flush();
|
|
}
|
|
}
|
|
catch (IOException ioe) {
|
|
adapter_logger.error(WCAException.E_SOFTLINK_SENDERR, ioe);
|
|
throw new WCAException(WCAException.E_SOFTLINK_SENDERR, ioe);
|
|
}
|
|
catch (Exception e) {
|
|
adapter_logger.error(WCAException.E_SOFTLINK_SENDERR, e);
|
|
throw new WCAException(WCAException.E_SOFTLINK_SENDERR, e);
|
|
}
|
|
}
|
|
// 20090810 End
|
|
|
|
// 20190828 Start
|
|
/**
|
|
* 1. 기능 : 어댑터 정보 명령 전송
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @exception WCAException
|
|
*/
|
|
public void sendWcaAdapterInfo() throws WCAException {
|
|
int nLen = 0;
|
|
byte[] pBuff = null;
|
|
byte[] pLenBuff = null;
|
|
String sAdptInfo = "";
|
|
|
|
try {
|
|
sAdptInfo = this.sAdapterName;
|
|
|
|
WCAAdapterInfoCmd cmd = new WCAAdapterInfoCmd(sAdptInfo);
|
|
|
|
pBuff = cmd.getData();
|
|
nLen = pBuff.length;
|
|
|
|
// 길이에 대한 길이 필드 생성
|
|
// 20090302 Start
|
|
// pLenBuff = MyUtil.getLenBuff(nLen, WCADefine.LEGTH_FIELD_SIZE);
|
|
pLenBuff = setInt(nLen);
|
|
// 20090302 End
|
|
|
|
myLog.logMsg(MyLog.WARN, "sendWcaAdapterInfo> Adapter Info = " + sAdptInfo);
|
|
myLog.logData(WCADefine.ASCII_CODE, nLen, pBuff);
|
|
|
|
// 길이 필드 및 데이터 송신
|
|
synchronized (osSoftLink) {
|
|
osSoftLink.write(pLenBuff, 0, WCADefine.LEGTH_FIELD_SIZE);
|
|
osSoftLink.write(pBuff, 0, nLen);
|
|
osSoftLink.flush();
|
|
}
|
|
}
|
|
catch (IOException ioe) {
|
|
adapter_logger.error(WCAException.E_SOFTLINK_SENDERR, ioe);
|
|
throw new WCAException(WCAException.E_SOFTLINK_SENDERR, ioe);
|
|
}
|
|
catch (Exception e) {
|
|
adapter_logger.error(WCAException.E_SOFTLINK_SENDERR, e);
|
|
throw new WCAException(WCAException.E_SOFTLINK_SENDERR, e);
|
|
}
|
|
}
|
|
// 20190828 End
|
|
|
|
/**
|
|
* 1. 기능 : 어댑터 상태 명령 전송
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
*
|
|
* @exception WCAException
|
|
*/
|
|
public void sendAdapterStatusData() throws WCAException {
|
|
int nLen = 0;
|
|
byte[] pBuff = null;
|
|
byte[] pLenBuff = null;
|
|
|
|
try {
|
|
// 첫번째 세션만 수행
|
|
if (nSessId != 0) { return; }
|
|
if (this.isBackupSessionPool()) { return; }
|
|
|
|
ManualBackupCmd cmd = new ManualBackupCmd();
|
|
cmd.setAdapterGrpName(this.sAdapterGroupName);
|
|
cmd.setLUGrpName(this.sGroupCode);
|
|
cmd.setDataType(WCAHeader.DATA_TYPE_GET_ADAPTER_STATUS);
|
|
|
|
pBuff = cmd.getData();
|
|
nLen = pBuff.length;
|
|
|
|
// 길이에 대한 길이 필드 생성
|
|
// 20090302 Start
|
|
// pLenBuff = MyUtil.getLenBuff(nLen, WCADefine.LEGTH_FIELD_SIZE);
|
|
pLenBuff = setInt(nLen);
|
|
// 20090302 End
|
|
|
|
// 데이터 트레이스
|
|
/*
|
|
WCAHeader wcaHeader = new WCAHeader(WCAHeader.WCA_HEADER_LEN, pBuff);
|
|
synchronized(myTrc) {
|
|
myTrc.logMsg("WCA -> SoftLink (LEN = " + nLen + ")");
|
|
myTrc.logMsg("WCA Header : " + wcaHeader.toString());
|
|
myTrc.logData(WCADefine.EBCDIC_CODE, nLen, pBuff);
|
|
}
|
|
*/
|
|
|
|
// 길이 필드 및 데이터 송신
|
|
synchronized (osSoftLink) {
|
|
osSoftLink.write(pLenBuff, 0, WCADefine.LEGTH_FIELD_SIZE);
|
|
osSoftLink.write(pBuff, 0, nLen);
|
|
osSoftLink.flush();
|
|
}
|
|
}
|
|
catch (IOException ioe) {
|
|
adapter_logger.error(WCAException.E_SOFTLINK_SENDERR, ioe);
|
|
throw new WCAException(WCAException.E_SOFTLINK_SENDERR, ioe);
|
|
}
|
|
catch (Exception e) {
|
|
adapter_logger.error(WCAException.E_SOFTLINK_SENDERR, e);
|
|
throw new WCAException(WCAException.E_SOFTLINK_SENDERR, e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : Softlink TCP 세션 close
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
**/
|
|
public void closeSoftLink() {
|
|
try {
|
|
try {
|
|
if (nSessStat != WCADefine.SESS_STAT_NOTCONN) {
|
|
// 20200825 Start
|
|
if (isSoftLink != null) {
|
|
try {
|
|
isSoftLink.close();
|
|
isSoftLink = null;
|
|
}
|
|
catch (Exception ignore1) {
|
|
adapter_logger.error("closeSoftLink] - [" + WCAException.E_ETC +"] " + toString() + " isSoftLink.close, Error = " + ignore1.toString());
|
|
}
|
|
}
|
|
|
|
if (osSoftLink != null) {
|
|
try {
|
|
osSoftLink.close();
|
|
osSoftLink = null;
|
|
}
|
|
catch (Exception ignore2) {
|
|
adapter_logger.error("closeSoftLink] - [" + WCAException.E_ETC +"] " + toString() + " osSoftLink.close Error = " + ignore2.toString());
|
|
}
|
|
}
|
|
// 20200825 End
|
|
|
|
sockSoftLink.close();
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
}
|
|
catch (IOException ioe) {
|
|
myLog.logMsg(MyLog.ERROR, "closeSoftLink] - [" + WCAException.E_ETC + "] Error = " + ioe.toString());
|
|
adapter_logger.error("closeSoftLink] - [" + WCAException.E_ETC +"] " + toString() + " Error = " + ioe.toString());
|
|
}
|
|
|
|
// 어댑터 상태 체크
|
|
myLog.logMsg(MyLog.DEBUG, "setAdapterStatus] setting");
|
|
setAdapterStatus(true);
|
|
myLog.logMsg(MyLog.DEBUG, "setAdapterStatus] ending");
|
|
|
|
// 미처리 트랜잭션 출력
|
|
traceRemainTransaction();
|
|
|
|
// 백업 전환
|
|
checkBackupConversion();
|
|
}
|
|
finally {
|
|
myLog.logMsg(MyLog.INFO, "socketClose] SessStat = SESS_STAT_NOTCONN");
|
|
nSessStat = WCADefine.SESS_STAT_NOTCONN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 자동 백업 전환
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
**/
|
|
private void checkBackupConversion() {
|
|
try {
|
|
if (bRunning && !isBackupSessionPool()) {
|
|
// 20091005 Start
|
|
// 백업 Enable Flag가 false 이면 백업 전환 처리를 하지 않는다.
|
|
if (bBackupEnableFlag == false) {
|
|
myLog.logMsg(MyLog.WARN, "checkBackupConversion] - bBackupEnableFlag is " + bBackupEnableFlag);
|
|
return;
|
|
}
|
|
// 20091005 End
|
|
|
|
// 20091005 Start
|
|
/*
|
|
// 백업 모드 이면 return
|
|
if (snaAdapter.getBackupMode(sNodeName, sGroupCode)) return;
|
|
*/
|
|
// 20091005 End
|
|
|
|
myLog.logMsg(MyLog.DEBUG, "setWCAAutoBackup] starting ");
|
|
int nConnectedSessNum = snaAdapter.getConnectedNormalSessNum(sNodeName, sGroupCode);
|
|
myLog.logMsg(MyLog.DEBUG, "setWCAAutoBackup] nConnectedSessNum = " + nConnectedSessNum);
|
|
if (nConnectedSessNum == 0) {
|
|
snaAdapter.setWCAAutoBackup(sNodeName, sGroupCode);
|
|
setAdapterStatus(true);
|
|
}
|
|
|
|
myLog.logMsg(MyLog.DEBUG, "setWCAAutoBackup] ending ");
|
|
}
|
|
}
|
|
catch (WCAException e) {
|
|
myLog.logMsg(MyLog.ERROR, "closeSoftLink] - [" + e.getErrorReturnCode() + "] Error = " + e.toString());
|
|
adapter_logger.error("closeSoftLink] - [" + e.getErrorReturnCode() +"] " + toString() + " Error = " + e.toString());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : Softlink input/output stream close
|
|
* 2. 처리 개요 :
|
|
* 3. 주의사항
|
|
**/
|
|
public void closeLogStream() {
|
|
// 20200825 Start
|
|
// myLog.closeLogStream();
|
|
// myTrc.closeLogStream();
|
|
|
|
if (myLog != null) { myLog.closeLogStream(); }
|
|
if (myTrc != null) { myTrc.closeLogStream(); }
|
|
// 20200825 End
|
|
}
|
|
|
|
int setInt(byte[] buf, int val, int idx) {
|
|
buf[idx++] = (byte)((val & 0xff000000) / 0x1000000);
|
|
buf[idx++] = (byte)((val & 0x00ff0000) / 0x10000);
|
|
buf[idx++] = (byte)((val & 0x0000ff00) / 0x100);
|
|
buf[idx++] = (byte)(val & 0x000000ff);
|
|
|
|
return 4;
|
|
}
|
|
|
|
byte[] setInt(int val) {
|
|
byte[] buf = new byte[4];
|
|
int idx = 0;
|
|
|
|
buf[idx++] = (byte)((val & 0xff000000) / 0x1000000);
|
|
buf[idx++] = (byte)((val & 0x00ff0000) / 0x10000);
|
|
buf[idx++] = (byte)((val & 0x0000ff00) / 0x100);
|
|
buf[idx++] = (byte)(val & 0x000000ff);
|
|
|
|
return buf;
|
|
}
|
|
|
|
int setInt2(byte[] buf, int val, int idx) {
|
|
buf[idx++] = (byte)(val & 0x000000ff);
|
|
buf[idx++] = (byte)((val & 0x0000ff00) / 0x100);
|
|
buf[idx++] = (byte)((val & 0x00ff0000) / 0x10000);
|
|
buf[idx++] = (byte)((val & 0xff000000) / 0x1000000);
|
|
|
|
return 4;
|
|
}
|
|
|
|
static int getInt(byte[] buf, int idx) {
|
|
int b1 = 0, b2 = 0, b3 = 0, b4 = 0;
|
|
|
|
b1 = (buf [idx] >= 0) ? buf[idx] : 0x100 + buf[idx];
|
|
b2 = (buf [idx + 1] >= 0) ? buf[idx + 1] : 0x100 + buf[idx + 1];
|
|
b3 = (buf [idx + 2] >= 0) ? buf[idx + 2] : 0x100 + buf[idx + 2];
|
|
b4 = (buf [idx + 3] >= 0) ? buf[idx + 3] : 0x100 + buf[idx + 3];
|
|
|
|
return b1 * 0x1000000 + b2 * 0x10000 + b3 * 0x100 + b4;
|
|
}
|
|
} |