base
This commit is contained in:
@@ -0,0 +1,325 @@
|
||||
|
||||
Revision 1507
|
||||
-------------------
|
||||
수정일 : 2020-10-05
|
||||
수정자 : 유희곤
|
||||
|
||||
- CHG: FreeBSD 12.x 컴파일시 발생하는 warning 코드 수정 (#33225)
|
||||
- FreeBSD 12.x 의 gcc 9.3 컴파일시 sprintf 사용 관련 buffer size 문제로 warning 발생
|
||||
- flow 상으로는 buffer overflow 발생 가능성 없지만.. 컴파일시마다 warning 발생하여 수정 처리
|
||||
- 수정파일: ArecaWrapper.cpp
|
||||
|
||||
|
||||
Revision 1489
|
||||
-------------------
|
||||
수정일 : 2020-01-10
|
||||
수정자 : 유희곤
|
||||
|
||||
- BUG: 불필요 "Battery Module Failed" event 미전송 관련 버그 수정 (#32911)
|
||||
- 실제로 Module 단어와 Failed 단어 사이에 공백이 3개 존재
|
||||
- 이로 인해 해당 event 가 계속 전송되는 상황 발견됨
|
||||
- 이에 Battery Module" check 후 Failed 문자열 check 하도록 수정
|
||||
- 수정파일: Child.cpp
|
||||
|
||||
|
||||
Revision 1472
|
||||
-------------------
|
||||
수정일 : 2019-09-16
|
||||
수정자 : 유희곤
|
||||
|
||||
- CHG: HTTP 관련 줄바꿈문자 LF->CR+LF 변경 (#32794)
|
||||
- CVE-2016-8743 이슈에 따라 Apache 2.2.32 버전부터 HTTP header 상에서
|
||||
- 줄바꿈문자가 CR+LF 가 아닌 경우 HTTP 400 응답 발생
|
||||
- 특히 최신 GMS 와 연동시 Apache 최신 버전 설치로 이와 같은 문제 발생 가능
|
||||
- 이를 해결하기 위해 기존 줄바꿈 문자 \n -> \r\n 으로 변경처리
|
||||
- 수정파일: SmsSender.cpp
|
||||
|
||||
- CHG: version info 변경
|
||||
- version 3.4.0 => 3.5.0
|
||||
|
||||
- NEW: 불필요 "Battery Module Failed" evnet 는 운영자에게 전송하지 않도록 수정 (#32795)
|
||||
- 운영자 요청으로 RAID event 중 "Battery Module Failed" event 는
|
||||
- 운영자에게 notify 되지 않도록 수정
|
||||
- 수정파일: Child.cpp
|
||||
|
||||
|
||||
Revision 1336
|
||||
-------------------
|
||||
수정일 : 2016-1-22
|
||||
수정자 : 노경민
|
||||
|
||||
- BUG: 초기화 실패 및 수집된 모든 이벤트 전송 불가
|
||||
- 내부적으로 사용하고 있는 자료 구조에 접근 문제
|
||||
- 메세지 생성 버퍼에 대한 overflow
|
||||
|
||||
|
||||
Revision 1317
|
||||
-------------------
|
||||
수정일 : 2015-12-29
|
||||
수정자 : 노경민
|
||||
|
||||
- BUG: 비정상 종료 현상
|
||||
- 이벤트 SMS 장비로 전송 중 비정상 종료 현상 발생
|
||||
- list에 대한 컨트롤 로직에서 잘못된 포인트 참조 발생
|
||||
|
||||
- BUG: 실행 불가능
|
||||
- FreeBSD 6.2 장비에 동작하지 않는 버그
|
||||
- 현재 적용된 Araca library 문제
|
||||
- Revision 0970 적용 처리
|
||||
- FreeBSD 10.x 정동 동작 확인 (version 1.20.00.28 2013-09-13 까지 정상 동작 확인)
|
||||
|
||||
- BUG: 이벤트 타임 오류
|
||||
- Araca library에서 리턴되는 타임을 time_t로 변경 중 오류 발생
|
||||
|
||||
- BUG: 발생된 메일에 이벤트 로그 미출력
|
||||
- GMS 장비에 UDP receive size 문제
|
||||
- send size 1400 byte 변경함
|
||||
|
||||
- CHG: 추가 수정
|
||||
- 로그 객체 변경
|
||||
- 코어 덤프 설정 로직 삭제
|
||||
- 소켓 객체 변경
|
||||
|
||||
|
||||
Revision 1210
|
||||
-------------------
|
||||
수정일 : 2015-06-26
|
||||
수정자 : 김오종
|
||||
|
||||
- BUG: 일부 장비에서 areca event를 정상적으로 가져오지 못하는 현상 수정 필요
|
||||
- event lelvel 별로 event 수집의도로 작성된 코드가 의미 없어서 제거처리 함(ArecaWrapper.cpp)
|
||||
|
||||
Revision 1097
|
||||
-------------------
|
||||
수정일 : 2014-10-28
|
||||
수정자 : 김오종
|
||||
|
||||
- CHG: raid card의 이벤트 중 메세지가 정의 되지 않은 이벤트 발생시 데몬이 죽는 현상 발생
|
||||
- 이벤트 메세지 정의가 되어 있지 않은 경우에 대한 처리 추가(ArecaWrapper.cpp)
|
||||
|
||||
Revision 1095
|
||||
-------------------
|
||||
수정일 : 2014-10-22
|
||||
수정자 : 유희곤
|
||||
|
||||
- CHG: GMS 에서 사용하는 arcmond_client 관련 수정
|
||||
- httpd error_log 상에 불필요한 로그 발생 코드 수정 ( Client.cpp)
|
||||
- gmake client
|
||||
- GMS 에서만 필요한 binary 로서 실제 arcmond 와는 연관 없음.
|
||||
- 따라서 binary tagging 등의 작업은 수행 안함.
|
||||
|
||||
|
||||
Revision 1093
|
||||
-------------------
|
||||
수정일 : 2014-10-17
|
||||
수정자 : 김오종
|
||||
|
||||
- CHG: version info 변경
|
||||
- version 3.3.0 => 3.4.0
|
||||
|
||||
Revision 1092
|
||||
-------------------
|
||||
수정일 : 2014-10-17
|
||||
수정자 : 김오종
|
||||
|
||||
- CHG: external library 현행화
|
||||
- http://www.areca.com.tw/support/main.htm
|
||||
- http://www.areca.us/support/download/API/20130320-342.zip
|
||||
|
||||
Revision 0970
|
||||
-------------------
|
||||
수정일 : 2014-03-27
|
||||
수정자 : 신순영
|
||||
|
||||
- CHG: Makefile 파일 수정
|
||||
- FreeBSD 버전 상관없이 무조건 환경설정을 util.conf 를 로딩하도록 수정
|
||||
|
||||
|
||||
Revision 0967
|
||||
-------------------
|
||||
수정일 : 2014-03-17
|
||||
수정자 : 신순영
|
||||
|
||||
- CHG: Makefile 파일 수정
|
||||
- FreeBSD 10.x 에서 환경설정을 util.conf 를 로딩하도록 처리
|
||||
|
||||
- CHG: 기타
|
||||
- GCC 버전업에 따른 warning 발생 관련 Makefile 상에서 -Wimplicit 옵션 제거
|
||||
- 기존 3.1.0 -> 3.3.0 으로 버전 변경 처리
|
||||
|
||||
|
||||
Revision 0901
|
||||
-------------------
|
||||
수정일 : 2013-10-18
|
||||
수정자 : 김오종
|
||||
|
||||
- CHG: gms web에서 전체 message를 수신할수 없는 상태인것을 확인했으나 gsm web 수정보다는 최근 100건만 보내는 것으로 해결 함.
|
||||
- UdpListener.cpp 의 CUdpListener::Execute() 함수 내에서 수정
|
||||
|
||||
Revision 0674
|
||||
-------------------
|
||||
수정일 : 2012-02-09
|
||||
수정자 : 신순영
|
||||
|
||||
- BUG: lib/Logger.cpp 파일 수정
|
||||
- gcc 4.4.5 버전에서 발생하는 parameter type에 따른 문제 수정
|
||||
|
||||
- CHG: Makefile 상의 버전정보 관리 방법 변경
|
||||
- 목표 버전 변경으로 인한 ver 3.1.0 으로 변경
|
||||
|
||||
|
||||
Revision 0673
|
||||
-------------------
|
||||
수정일 : 2012-02-09
|
||||
수정자 : 신순영
|
||||
|
||||
- BUG: lib/Config.h 파일 수정
|
||||
- gcc 4.4.5 버전에서 발생하는 parameter type에 따른 문제 수정
|
||||
|
||||
- CHG:
|
||||
1. 컴파일시 불필요한 warning 제거
|
||||
|
||||
|
||||
Revision 0585
|
||||
-------------------
|
||||
수정일 : 2011-07-27
|
||||
수정자 : 장희준
|
||||
|
||||
- CHG: Make 파일 수정
|
||||
- AutoDisableUpload.o 추가
|
||||
|
||||
|
||||
Revision 0584
|
||||
-------------------
|
||||
수정일 : 2011-07-27
|
||||
수정자 : 장희준
|
||||
|
||||
- ADD: 자동 업로드 방지 기능 추가
|
||||
- AutoDisableUpload.h AutoDisableUpload.cpp 파일 추가
|
||||
- Child.cpp 파일의 ChildMain()에서 자동 업로드 방지 기능 호출
|
||||
- 자동 업로드 방지 이벤트 대상은 아래와 같음.
|
||||
- Volume Degraded, RaidSet Degraded, Rebuild RaidSet, Device Failed, Start Rebuilding
|
||||
|
||||
|
||||
Revision 0529
|
||||
-------------------
|
||||
수정일 : 2011-05-03
|
||||
수정자 : 유희곤
|
||||
|
||||
- BUG: lib/BaseSocket.cpp ConversionAddr() 함수 수정
|
||||
- ConversionAddr() 함수에서 gethostbyname() 함수 사용으로 인한 Thread-Safe 문제 발생
|
||||
- Multi Thread App에서 요청한 장비와 다른 장비로 접속하는 문제가 발견되었으며
|
||||
- 이로인해 Contents 전송, 관리 부분에서 문제가 발생할 수 있어 수정 처리함.
|
||||
- 본 문제는 Thread Safe 한 getaddrinfo() 함수 사용으로 변경 처리함.
|
||||
|
||||
|
||||
Revision 443
|
||||
-------------------
|
||||
수정일 : 2010-12-03
|
||||
수정자 : 장희준
|
||||
|
||||
arcmond2 revision 정보 중복으로 다시 commit.
|
||||
|
||||
|
||||
Revision 440
|
||||
-------------------
|
||||
수정일 : 2010-12-03
|
||||
수정자 : 장희준
|
||||
|
||||
- CHG: Makefile 수정
|
||||
- gmake install 시에 Makefile에 install 경로가 없어서 install 경로 설정
|
||||
- arcmond.conf을 사용하지 않는데 arcmond.conf을 install 하고 있어서 설정
|
||||
파일 install 삭제
|
||||
|
||||
|
||||
Revision 0399
|
||||
-------------------
|
||||
수정일 : 2010-11-17
|
||||
수정자 : 김오종
|
||||
|
||||
- BUG: 메모리 leak 발생 가능 함수 수정.
|
||||
- CArecaWrapper::GetEvent() 함수와 CArecaWrapper::DiscoveryDevice()함수 수정.
|
||||
- Logging 메세지 철자 수정.
|
||||
|
||||
- CHG: Makefile 상의 버전정보 관리 방법 변경
|
||||
- 목표 버전 변경으로 인한 ver 3.0.1 로 변경
|
||||
|
||||
Revision 0322
|
||||
-------------------
|
||||
수정일 : 2010-08-02
|
||||
수정자 : 김오종
|
||||
|
||||
- BUG: CBaseSocket::Read() 함수상의 문법관련 버그 수정
|
||||
- 156 Line상의 잘못된 대입 연산자를 비교연산자로 수정처리.
|
||||
|
||||
Revision 0307
|
||||
-------------------
|
||||
수정일 : 2010-07-12
|
||||
수정자 : 김오종
|
||||
|
||||
- CHG:
|
||||
1. Revision 306 커밋 이슈와 관련된 부분에서 REPEAT_ALLOW_TIME 60을 제거.
|
||||
- 불필요한 DEBUG 옵션에서 반복된 메세지처리 시간을 제거처리 함.
|
||||
|
||||
Revision 0306
|
||||
-------------------
|
||||
수정일 : 2010-07-12
|
||||
수정자 : 김오종
|
||||
|
||||
- CHG:
|
||||
1. makefile내용 변경.
|
||||
- 기본 DEBUG로 커밋되어 있어 실수 유발가능성이 있다.
|
||||
|
||||
Revision 0301
|
||||
-------------------
|
||||
수정일 : 2010-07-08
|
||||
수정자 : 김오종
|
||||
|
||||
- BUG:
|
||||
1. arcmond_client 요청에 대한 udp response에서 마지막 한 byte가 누락 되는 버그 수정.
|
||||
|
||||
Revision 0294
|
||||
-------------------
|
||||
수정일 : 2010-07-05
|
||||
수정자 : 김오종
|
||||
|
||||
- BUG:
|
||||
1.NO EVENT 송신 시에 첫 번째 필드가 '0'으로 보내져야 정상상황에서 이벤트가 없는 것으로 판단됨.
|
||||
최종적으로 php소스에서 '0'이 오면 정상으로 처리 중인 것을 확인.
|
||||
- 첫 번째 필드를 '1'=>'0' 으로 변경.
|
||||
2.UDP 송신함수인CUdpListener::SendMsg()함수 버그 발견.
|
||||
- 해당 함수 호출시 두 번째 인자는 메세지의 길이를 입력해야함에도 불구하고, szSendBuffer사이의 기본크기를 인자로사용 함.
|
||||
=> 두 번째 인자를 strlen(szSendBuffer) 로 변경 함.
|
||||
- 해당 함수내에 전송요청한 바이트만큼 확인하는 코드에서 do~ while문의 조건을 (nWrite >= 0) 으로 사용하여 마지막에 한 byte가 더 전송됨을 확인 함.
|
||||
=> (nWrite >= 0) 를 (nWrite > 0)로 변경 함.
|
||||
|
||||
|
||||
Revision 0293
|
||||
-------------------
|
||||
수정일 : 2010-07-02
|
||||
수정자 : 김오종
|
||||
|
||||
- BUG: - conf 파일의 디폴트 값을 가져오는 부분에서 clear()하지 않아 영향이 있었음.
|
||||
|
||||
Revision 0288
|
||||
-------------------
|
||||
수정일 : 2010-07-02
|
||||
수정자 : 김오종
|
||||
|
||||
- NEW: SVN 신규 등록
|
||||
- 필요파일 누락으로 추가 함.
|
||||
-> libarclib32.a, libarclib64.a
|
||||
|
||||
Revision 0287
|
||||
-------------------
|
||||
수정일 : 2010-07-02
|
||||
수정자 : 김오종
|
||||
|
||||
- NEW: SVN 신규 등록
|
||||
- 기존 svn://211.38.137.33/work/trunk/raidmond 에 존재하는 개발 완료 소스 (Rev 987)를 SVN 에 정식버전으로 등록함.
|
||||
- 본 버전은 개발 및 성능 테스트를 완료한 버전으로 areca raid card의 상태를 모니터링하는 기능을 함.
|
||||
- 단 현재 버전은 FreeBSD 5.4, 6.2 버전상에서만 테스트되었으며 다른 OS 로 포팅 처리시 코드를 재확인해야 함.
|
||||
|
||||
- NEW: History 저장을 위한 Changelog.txt 파일 추가
|
||||
- 앞으로 각 작업에 대한 로그를 확인하도록 Changelog.txt 파일을 추가
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
#****************************************************************************
|
||||
# Makefile for ftsd ( FHS RAID Monitor Daemon)
|
||||
# -----------------------------------------
|
||||
#
|
||||
# begin : 2010/05/18
|
||||
# copyright : (C) 2005 SolutionBox Inc.
|
||||
# author : Service 1 Team
|
||||
# email : svc1@solbox.com
|
||||
# version : 3.0.0
|
||||
#
|
||||
# CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
# Redistribution and use in source and binary forms, with or with out
|
||||
# modification, are not permitted in outside of SolutionBox Inc.
|
||||
#*****************************************************************************
|
||||
|
||||
SUBDIRS = lib src
|
||||
|
||||
.PHONY: all $(SUBDIRS)
|
||||
|
||||
|
||||
all: $(SUBDIRS)
|
||||
sync;
|
||||
|
||||
|
||||
$(SUBDIRS):
|
||||
$(MAKE) all -C $@
|
||||
|
||||
|
||||
install:
|
||||
@for dir in $(SUBDIRS); do (cd $$dir; $(MAKE) install); done
|
||||
|
||||
|
||||
clean:
|
||||
@for dir in $(SUBDIRS); do (cd $$dir; $(MAKE) clean); done
|
||||
|
||||
|
||||
# End of Makefile
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
+2761
File diff suppressed because it is too large
Load Diff
+304
@@ -0,0 +1,304 @@
|
||||
#ifndef _ARCLIBS_H
|
||||
#define _ARCLIBS_H
|
||||
|
||||
/********************************************************/
|
||||
/*
|
||||
/* Data Structures & Function prototypes for S.M.A.R.T
|
||||
/*
|
||||
/********************************************************/
|
||||
|
||||
#include "arclib.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
|
||||
#define MAX_DATA_LENGTH 512
|
||||
#define SHORT_SELF_TEST 1
|
||||
#define EXTENDED_SELF_TEST 2
|
||||
|
||||
/*
|
||||
Attribute ID Numbers
|
||||
Any non-zero value in the Attribute ID Number indicates an active attribute. The device supports the
|
||||
following Attribute ID Numbers.
|
||||
|
||||
ID Attribute Name
|
||||
=============================================
|
||||
199 Ultra DMA CRC Error Count
|
||||
198 Off-line Scan Uncorrectable Sector Count
|
||||
197 Current Pending Sector Count
|
||||
196 Reallocation Event Count
|
||||
194 Temperature
|
||||
193 Load Cycle Count
|
||||
192 Power-off Retract Count
|
||||
12 Device Power Cycle Count
|
||||
10 Spin Retry Count
|
||||
9 Power-on Hours Count
|
||||
8 Seek Time Performance
|
||||
7 Seek Error Rate
|
||||
5 Reallocated Sector Count
|
||||
4 Start/Stop Count
|
||||
3 Spin Up Time
|
||||
2 Throughput Performance
|
||||
1 Raw Read Error Rate
|
||||
0 Indicates that this entry in the data structure is not used
|
||||
|
||||
|
||||
Status Flag definitions
|
||||
Bit Definition
|
||||
0 Pre-failure/advisory bit
|
||||
0 An attribute value less than or equal to its corresponding attribute threshold indicates an
|
||||
advisory condition where the usage or age of the device has exceeded its intended
|
||||
design life period.
|
||||
1 An attribute value less than or equal to its corresponding attribute threshold indicates a
|
||||
pre-Failure condition where imminent loss of data is being predicted.
|
||||
1 On-line Collective bit
|
||||
0 The attribute value is updated only during Off-line testing.
|
||||
1 The attribute value is updated during On-line testing or during both On-line and Off-line
|
||||
testing.
|
||||
2 - 5 Vendor specific
|
||||
6 - 15 Reserved (0)
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
The following defines the 12 bytes that make up the information for each Attribute entry in the Device
|
||||
Attribute Data Structure.
|
||||
*/
|
||||
typedef struct _DEVICE_ATTR_DATA // Individual Attribute Data Structure
|
||||
{
|
||||
BYTE id; // 0x00, Attribute ID Number (01h to FFh)
|
||||
BYTE status[2]; // 0x01, Status flags
|
||||
BYTE value; // 0x03, Attribute Value (valid values from 01h to FDh)
|
||||
BYTE vendor_spec[8]; // 0x04, Vendor Specific
|
||||
}sDEVICE_ATTR_DATA, *pDEVICE_ATTR_DATA; // total 12 bytes
|
||||
|
||||
/*
|
||||
The following defines the 512 bytes that make up the Attribute Value information. This data structure is
|
||||
accessed by the host in its entirety using the SMART Read Attribute Values subcommand. All multibyte
|
||||
fields shown in these data structures are in byte ordering, that is, the least significant byte occupies the
|
||||
lowest numbered byte address location in the field.
|
||||
*/
|
||||
typedef struct _SMART_ATTR_DATA // Device Attributes Data Structure
|
||||
{
|
||||
BYTE rev_num[2]; // 0x00 Data Structure Revision Number
|
||||
sDEVICE_ATTR_DATA device_attr_data[30]; // 0x02 Device Attribute, from 1st~30th
|
||||
BYTE dc_status; // 0x16A, Off¡Vline data collection status
|
||||
BYTE st_status; // 0x16B, Self¡Vtest execution status
|
||||
BYTE total_time_for_dc[2]; // 0x16C, Total time in seconds to complete off¡Vline data collection activity
|
||||
BYTE vendor_spec1; // 0x16E, Vendor specific
|
||||
BYTE dc_capability; // 0x16F, Off¡Vline data collection capability
|
||||
BYTE smart_cap[2]; // 0x170, SMART capability
|
||||
BYTE smart_error_log_cap; // 0x172, SMART device error logging capability
|
||||
BYTE st_failure_check_point; // 0x173, Self¡Vtest failure check point
|
||||
BYTE short_st_completion_time; // 0x174, Short self¡Vtest completion time in minutes
|
||||
BYTE extended_st_completion_time; // 0x175, Extended self¡Vtest completion time in minutes
|
||||
BYTE reserved[12]; // 0x176, Reserved
|
||||
BYTE vendor_spec2[125]; // 0x182, Vendor specific
|
||||
BYTE checksum; // 0x1FF, Data structure checksum
|
||||
|
||||
}sSMART_ATTR_DATA, *pSMART_ATTR_DATA; // total 512 bytes
|
||||
|
||||
/*
|
||||
The following defines the 12 bytes that make up the information for each Threshold entry in the Device
|
||||
Attribute Thresholds Data Structure. Attribute entries in the Individual Threshold Data Structure is in the
|
||||
same order and correspond to the entries in the Individual Attribute Data Structure.
|
||||
*/
|
||||
typedef struct _DEVICE_ATTR_THRE_DATA // Individual Thresholds Data Structure
|
||||
{
|
||||
BYTE id; // 0x00, Attribute ID Number (01h to FFh)
|
||||
BYTE threshold; // 0x01, Attribute Threshold
|
||||
BYTE reserved[10]; // 0x02, Reserved (00h)
|
||||
}sDEVICE_ATTR_THRE_DATA, *pDEVICE_ATTR_THRE_DATA; // total 12 bytes
|
||||
|
||||
/*
|
||||
The following defines the 512 bytes that make up the Attribute Threshold information. This data structure
|
||||
is accessed by the host in its entirety using the SMART Read Attribute Thresholds. All multibyte fields
|
||||
shown in these data structures are in byte ordering, that is, the least significant byte occupies the lowest
|
||||
numbered byte address location in the field.
|
||||
The sequence of active Attribute Thresholds will appear in the same order as their corresponding
|
||||
Attribute Values.
|
||||
*/
|
||||
typedef struct _SMART_ATTR_THRE_DATA // Device Attribute Thresholds Data Structure
|
||||
{
|
||||
BYTE rev_num[2]; // 0x00, Data Structure Revision Number
|
||||
sDEVICE_ATTR_THRE_DATA device_attr_data[30]; // 0x02, Device Attribute, from 1st~30th
|
||||
BYTE reserved[18]; // 0x16A, Reserved
|
||||
BYTE vendor_spec[131]; // 0x17C, Vendor specific
|
||||
BYTE checksum; // 0x1FF, Data structure checksum
|
||||
}sSMART_ATTR_THRE_DATA, *pSMART_ATTR_THRE_THRE_DATA; // total 512 bytes
|
||||
|
||||
|
||||
/*
|
||||
Command data structure
|
||||
Data format of each command data structure is shown below.
|
||||
*/
|
||||
typedef struct _COMMAND_DATA
|
||||
{
|
||||
BYTE dev_control_reg; // 0x00, Device Control register
|
||||
BYTE features_reg; // 0x01, Features register
|
||||
BYTE sector_count_reg; // 0x02, Sector count register
|
||||
BYTE sector_number_reg; // 0x03, Sector number register
|
||||
BYTE cylinder_low_reg; // 0x04, Cylinder Low register
|
||||
BYTE cylinder_high_reg; // 0x05, Cylinder High register
|
||||
BYTE head_reg; // 0x06, Device/Head register
|
||||
BYTE command_reg; // 0x07, Command register
|
||||
BYTE time_stamp[4]; // 0x08, Timestamp(ms from Power On)
|
||||
}sCOMMAND_DATA, *pCOMMAND_DATA; // total 12 bytes
|
||||
|
||||
/*
|
||||
Error data structure:
|
||||
Data format of error data structure is shown below.
|
||||
The state field contains a value indicating the device state when the command was issued to the device.
|
||||
xBh-xFh Vendor specific
|
||||
x5h-xAh Reserved
|
||||
x4h SMART Off-line or Self-test
|
||||
x3h Active/Idle
|
||||
x2h Standby
|
||||
x1h Sleep
|
||||
x0h Unknown
|
||||
Value
|
||||
*/
|
||||
|
||||
typedef struct _ERROR_DATA
|
||||
{
|
||||
BYTE reserved; // 0x00, Reserved
|
||||
BYTE error_reg; // 0x01, Error register
|
||||
BYTE sector_count_reg; // 0x02, Sector count register
|
||||
BYTE sector_number_reg; // 0x03, Sector number register
|
||||
BYTE cylinder_low_reg; // 0x04, Cylinder Low register
|
||||
BYTE cylinder_high_reg; // 0x05, Cylinder High register
|
||||
BYTE head_reg; // 0x06, Device/Head register
|
||||
BYTE status_reg; // 0x07, Status register
|
||||
BYTE extended_error_data[19]; //0x08, Extended error data (vendor specific)
|
||||
BYTE state; // 0x1B, State
|
||||
BYTE life_timestamp[2]; // 0x1C Life timestamp (hours)
|
||||
}sERROR_DATA, *pERROR_DATA; // total 30 bytes
|
||||
|
||||
|
||||
/*
|
||||
Error log data structure
|
||||
Data format of error data structure is shown below.
|
||||
*/
|
||||
typedef struct _ERROR_LOG_DATA
|
||||
{
|
||||
sCOMMAND_DATA command_data[5]; // 0x00, Command data structure, from 1~5
|
||||
sERROR_DATA error_data; // 0x3C, Error data structure
|
||||
}sERROR_LOG_DATA, *pERROR_LOG_DATA; // total 90 bytes
|
||||
|
||||
|
||||
/*
|
||||
The following figure defines the 512 bytes that make up the SMART error log sector. All multibyte fields
|
||||
shown in these data structures are in byte ordering.
|
||||
*/
|
||||
typedef struct _SMART_ERROR_LOG_SECTOR
|
||||
{
|
||||
BYTE version; // 0x00, SMART error log version
|
||||
BYTE pointer; // 0x01, Error log pointer
|
||||
sERROR_LOG_DATA log_data[5]; // 0x02, 1st~5th error log data structure
|
||||
BYTE device_error_count[2]; // 0x1C4, Device error count
|
||||
BYTE reserved[57]; // 0x1C6, Reserved
|
||||
BYTE checksum; // 0x1FF, Data structure checksum
|
||||
|
||||
}sSMART_ERROR_LOG_SECTOR, *pSMART_ERROR_LOG_SECTOR; // total 512 bytes
|
||||
|
||||
|
||||
/*
|
||||
The data structure contains the descriptor of Self-test that the device has performed. Each descriptor is
|
||||
24 bytes long and the self-test data structure is capable of containing up to 21 descriptors.
|
||||
After 21 descriptors have been recorded, the oldest descriptor will be overwritten with a new descriptor.
|
||||
The self-test log pointer points to the most recent descriptor. When there is no descriptor, the value is 0.
|
||||
When there is descriptor(s) the value is 1 through 21.
|
||||
*/
|
||||
typedef struct _SELF_TEST_LOG_DESCRIPTOR
|
||||
{
|
||||
BYTE number; // 0x00, Self-test number
|
||||
BYTE exe_status; // 0x01, Self-test execution status
|
||||
BYTE life_time[2]; // 0x02, Life time power on hours
|
||||
BYTE st_failure_check_point; // 0x04, Self-test failure check point
|
||||
BYTE lba_of_first_failure[4];// 0x05, LBA of first failure
|
||||
BYTE vendor_spec[15]; // 0x06, Vendor specific
|
||||
|
||||
}sSELF_TEST_LOG_DESCRIPTOR, *pSELF_TEST_LOG_DESCRIPTOR; // total 24 bytes
|
||||
|
||||
|
||||
/*
|
||||
Self-test log data structure
|
||||
The following figure defines the 512 bytes that make up the Self-test log sector. All multibyte fields shown
|
||||
in these data structures are in byte ordering.
|
||||
*/
|
||||
|
||||
typedef struct _SELF_TEST_LOG_DATA
|
||||
{
|
||||
BYTE reversion[2]; // 0x00, Data structure revision
|
||||
sSELF_TEST_LOG_DESCRIPTOR descriptor[21]; // 0x02, descriptors
|
||||
BYTE vendor_spec[2]; // 0x1FA, Vendor specific
|
||||
BYTE pointer; // 0x1FC, Self-test log pointer
|
||||
BYTE reserved[2]; // 0x1FD, Reserved
|
||||
BYTE checksum; // 0x1FF, Data structure checksum
|
||||
}sSELF_TEST_LOG_DATA, *pSELF_TEST_LOG_DATA; // total 512 bytes
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
class ARCLIB_API CArclibSMART : public CArclib
|
||||
{
|
||||
#else
|
||||
class CArclibSMART : public CArclib
|
||||
{
|
||||
#endif
|
||||
public:
|
||||
|
||||
// (O): Implemented
|
||||
// (X): Not Implemented
|
||||
enum
|
||||
{
|
||||
R_SMART_DATA = 0, // (O)Read smart data
|
||||
R_THLD_DATA, // (O)Read threshold data
|
||||
ED_AUTOSAVE, // (X)Enable/disable autosave
|
||||
S_ATTR, // (X)Save attribute
|
||||
EXE_OFFLINE, // (O)Execute offline
|
||||
R_LOG, // (X)Read log
|
||||
W_LOG, // (X)Write log
|
||||
RESERVED1,
|
||||
E_SMART, // (O)Enable SMART
|
||||
D_SMART, // (O)Disable SMART
|
||||
RET_SMART_STATUS, // (X)Return SMART status
|
||||
ED_AUTO_OFFLINE, // (X)Enable/Disable automatic offline
|
||||
RESERVED2,
|
||||
RESERVED3,
|
||||
RESERVED4,
|
||||
RESERVED5,
|
||||
RW_TEST, // (O)Read/Write test
|
||||
STOP_RW_TEST, // (O)Stop Read/Write test
|
||||
CHECK_RW_RESULT, // (O)Check Read/Write Result
|
||||
RESERVED6
|
||||
};
|
||||
|
||||
//################################################################################################
|
||||
// Function: ArcExeSMART
|
||||
// Parameters: (i) cmd: the commands listed above
|
||||
// (i) drv: drive# where the SMART command is being executed
|
||||
// (i) params: The options for EXE_OFFLINE, RW_TEST only.
|
||||
// for EXE_OFFLINE: value SHORT_SELF_TEST indicates short self-test
|
||||
// value EXTENDED_SELF_TEST indicates extended self-test
|
||||
// for RW_TEST: percentage of RW_TEST
|
||||
// (o) data: The option for R_SMART_DATA, R_THLD_DATA, CHECK_RW_RESULT only.
|
||||
// the SMART data returned from the drive that indicates by drv,
|
||||
// the memory allocation of 'data' is the responsibility of the
|
||||
// calling thread, and it's size should be >= 512 bytes
|
||||
//################################################################################################
|
||||
ARC_STATUS ArcExeSMART(int cmd, BYTE drv, BYTE params, PBYTE data);
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
#ifndef _COMMDEF_H_
|
||||
#define _COMMDEF_H_
|
||||
|
||||
#if !defined(__solaris__) && defined(__sun__)
|
||||
#define __solaris__
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef ARCLIB_EXPORTS
|
||||
#define ARCLIB_API
|
||||
#else
|
||||
#define ARCLIB_API
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef int8_t
|
||||
typedef signed char int8_t;
|
||||
#endif
|
||||
#ifndef u_int8_t
|
||||
typedef unsigned char u_int8_t;
|
||||
#endif
|
||||
#ifndef int16_t
|
||||
typedef signed short int16_t;
|
||||
#endif
|
||||
#ifndef u_int16_t
|
||||
typedef unsigned short u_int16_t;
|
||||
#endif
|
||||
#ifndef int32_t
|
||||
typedef signed int int32_t;
|
||||
#endif
|
||||
#ifndef u_int32_t
|
||||
typedef unsigned int u_int32_t;
|
||||
#endif
|
||||
#ifndef int64_t
|
||||
typedef long long int64_t;
|
||||
#endif
|
||||
#ifndef u_int64_t
|
||||
typedef unsigned long long u_int64_t;
|
||||
#endif
|
||||
#endif // end of _WIN32
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__)
|
||||
#define __unix_like__ 1
|
||||
#include <stdio.h> //Standard input/output definitions
|
||||
#include <string.h> //String function definitions
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h> //waitpid() and wait()
|
||||
#ifdef __linux__
|
||||
#include <linux/serial.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h> // File control definitions
|
||||
#include <errno.h> // Error number definitions
|
||||
#include <termios.h> // POSIX terminal control definitions
|
||||
#include <unistd.h> // fork()
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h> // inet_addr(...)
|
||||
#include <netdb.h>
|
||||
#include <strings.h>
|
||||
#include <syslog.h>
|
||||
#endif // end of defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__)
|
||||
|
||||
#ifdef __solaris__
|
||||
typedef unsigned char u_int8_t;
|
||||
typedef unsigned short u_int16_t;
|
||||
typedef unsigned long u_int32_t;
|
||||
typedef unsigned long long u_int64_t;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef _DOS
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <conio.h>
|
||||
#include <dos.h>
|
||||
#include <memory.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#ifndef int8_t
|
||||
typedef signed char int8_t;
|
||||
#endif
|
||||
#ifndef u_int8_t
|
||||
typedef unsigned char u_int8_t;
|
||||
#endif
|
||||
#ifndef int16_t
|
||||
typedef signed int int16_t;
|
||||
#endif
|
||||
#ifndef u_int16_t
|
||||
typedef unsigned int u_int16_t;
|
||||
#endif
|
||||
#ifndef int32_t
|
||||
typedef signed long int32_t;
|
||||
#endif
|
||||
#ifndef u_int32_t
|
||||
typedef unsigned long u_int32_t;
|
||||
#endif
|
||||
#endif // end of _DOS
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef IN
|
||||
#define IN
|
||||
#endif
|
||||
#ifndef OUT
|
||||
#define OUT
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#ifndef BOOL
|
||||
#define BOOL int8_t
|
||||
#endif
|
||||
#ifndef CHAR
|
||||
#define CHAR int8_t
|
||||
#endif
|
||||
#ifndef UCHAR
|
||||
#define UCHAR u_int8_t
|
||||
#endif
|
||||
#ifndef BYTE
|
||||
#define BYTE u_int8_t
|
||||
#endif
|
||||
#ifndef PBYTE
|
||||
#define PBYTE u_int8_t *
|
||||
#endif
|
||||
#ifndef WORD
|
||||
#define WORD u_int16_t
|
||||
#endif
|
||||
#ifndef DWORD
|
||||
#define DWORD u_int32_t
|
||||
#endif
|
||||
#ifndef LONG
|
||||
#define LONG int32_t
|
||||
#endif
|
||||
#ifndef ULONG
|
||||
#define ULONG uint32_t
|
||||
#endif
|
||||
#ifndef LVOID
|
||||
#define LVOID void *
|
||||
#endif
|
||||
#ifndef LPVOID
|
||||
#define LPVOID void *
|
||||
#endif
|
||||
#ifndef HANDLE
|
||||
#define HANDLE int
|
||||
#endif
|
||||
#ifndef SOCKET
|
||||
#define SOCKET int
|
||||
#endif
|
||||
#ifndef SOCKET_ERROR
|
||||
#define SOCKET_ERROR -1
|
||||
#endif
|
||||
#ifndef INVALID_SOCKET
|
||||
#define INVALID_SOCKET -1
|
||||
#endif
|
||||
#endif // end of _WIN32
|
||||
#endif //end of _COMMDEF_H_
|
||||
@@ -0,0 +1,75 @@
|
||||
//
|
||||
// @APPLE_LICENSE_HEADER_START@
|
||||
//
|
||||
// Copyright (c) 2005, 2006 Apple Computer, Inc. All Rights Reserved.
|
||||
//
|
||||
// This file contains Original Code and/or Modifications of Original Code
|
||||
// as defined in and that are subject to the Apple Public Source License
|
||||
// Version 2.0 (the 'License'). You may not use this file except in
|
||||
// compliance with the License. Please obtain a copy of the License at
|
||||
// http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
// file.
|
||||
//
|
||||
// The Original Code and all software distributed under the License are
|
||||
// distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
// EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
// INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
// Please see the License for the specific language governing rights and
|
||||
// limitations under the License.
|
||||
//
|
||||
// @APPLE_LICENSE_HEADER_END@
|
||||
|
||||
// $Id: darwin_userclient.h,v 1.3 2006/01/15 21:19:30 msmith Exp $
|
||||
|
||||
#ifndef __DARWINUSERCLIENT_H__
|
||||
#define __DARWINUSERCLIENT_H__
|
||||
|
||||
// XXX trim these includes
|
||||
#include <iostream>
|
||||
#include <pthread.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <errno.h> /* Error number definitions */
|
||||
#include <unistd.h> /* fork() */
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "commdef.h"
|
||||
#include "interface.h"
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
|
||||
class DarwinUserClientInterface : public ArcInterface
|
||||
{
|
||||
public:
|
||||
DarwinUserClientInterface();
|
||||
~DarwinUserClientInterface();
|
||||
|
||||
bool init(const int nPort);
|
||||
int send(sIF_CMD_BLOCK *ifData);
|
||||
int recv(sIF_CMD_BLOCK *ifData);
|
||||
int syncSend(sIF_CMD_BLOCK *ifData);
|
||||
void requirelock();
|
||||
void releaselock();
|
||||
bool ClearReadBuffer();
|
||||
bool ClearWriteBuffer();
|
||||
bool ClearReadWriteBuffer();
|
||||
int getMTU();
|
||||
void *getDeviceHandle();
|
||||
|
||||
private:
|
||||
io_connect_t connectionPort;
|
||||
bool controllerIsOpen;
|
||||
pthread_mutex_t mtx;
|
||||
};
|
||||
|
||||
#endif // __DARWINUSERCLIENT_H__
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
#ifndef _DOSPCI_H_
|
||||
#define _DOSPCI_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include "commdef.h"
|
||||
#include "if.h"
|
||||
#include "stdio.h"
|
||||
#include "memory.h"
|
||||
|
||||
|
||||
extern int ttchk( void ); /* Return count of received characters */
|
||||
extern void ttos(unsigned char ptr[], int len);
|
||||
extern int ttinc( void ); /* Input a character from circular buffer */
|
||||
extern void serini( void ); /* Initialize the com port for interrupts */
|
||||
extern unsigned long GetDword(unsigned);
|
||||
extern void SetDword(unsigned, unsigned long);
|
||||
extern InProtectedMode();
|
||||
extern find_lindsay();
|
||||
extern SetA20();
|
||||
|
||||
|
||||
class DosPciInterface : public ArcInterface
|
||||
{
|
||||
public:
|
||||
DosPciInterface();
|
||||
~DosPciInterface();
|
||||
int init(const char nPortNum);
|
||||
int send(sIF_CMD_BLOCK *ifData);
|
||||
int recv(sIF_CMD_BLOCK *ifData);
|
||||
int syncSend(sIF_CMD_BLOCK *ifData);
|
||||
void *getDeviceHandle();
|
||||
int getMTU();
|
||||
void requirelock();
|
||||
void releaselock();
|
||||
void setTimeOut(int nSec);
|
||||
|
||||
private:
|
||||
BOOL ClearReadBuffer();
|
||||
BOOL ClearWriteBuffer();
|
||||
BOOL ClearReadWriteBuffer();
|
||||
int nTimeOut; // in seconds
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
|
||||
#ifndef _ETHERNET_H_
|
||||
#define _ETHERNET_H_
|
||||
|
||||
#include "commdef.h"
|
||||
#include "interface.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Winsock2.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
class ARCLIB_API EthernetInterface : public ArcInterface
|
||||
#else
|
||||
class EthernetInterface : public ArcInterface
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
EthernetInterface();
|
||||
~EthernetInterface();
|
||||
bool init(const char *szIPAddr, short nPort = 7890);
|
||||
int send(sIF_CMD_BLOCK *ifData);
|
||||
int recv(sIF_CMD_BLOCK *ifData);
|
||||
int syncSend(sIF_CMD_BLOCK *ifData);
|
||||
int getMTU();
|
||||
|
||||
// helper functions
|
||||
public:
|
||||
void *getDeviceHandle();
|
||||
SOCKET getSocket();
|
||||
|
||||
private:
|
||||
BOOL ClearReadBuffer();
|
||||
BOOL ClearWriteBuffer();
|
||||
BOOL ClearReadWriteBuffer();
|
||||
int WaitForReply(SOCKET s, long time_sec, long time_usec);
|
||||
SOCKET m_socket;
|
||||
#ifdef _WIN32
|
||||
CRITICAL_SECTION m_cs;
|
||||
void requirelock()
|
||||
{
|
||||
EnterCriticalSection(&m_cs);
|
||||
}
|
||||
void releaselock()
|
||||
{
|
||||
LeaveCriticalSection(&m_cs);
|
||||
}
|
||||
#elif defined(__unix_like__)
|
||||
|
||||
#endif
|
||||
struct sockaddr_in agentaddr;
|
||||
struct sockaddr_in manager_addr;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
#ifndef __FREEBSDSCSI_H__
|
||||
#define __FREEBSDSCSI_H__
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <pthread.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <errno.h> /* Error number definitions */
|
||||
#include <unistd.h> /* fork() */
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
|
||||
#include <cam/cam.h>
|
||||
#include <cam/cam_debug.h>
|
||||
#include <cam/cam_ccb.h>
|
||||
#include <cam/scsi/scsi_all.h>
|
||||
#include <cam/scsi/scsi_da.h>
|
||||
#include <cam/scsi/scsi_pass.h>
|
||||
#include <cam/scsi/scsi_message.h>
|
||||
#include <camlib.h>
|
||||
|
||||
|
||||
#include "commdef.h"
|
||||
#include "interface.h"
|
||||
#include "arclib.h"
|
||||
|
||||
#define SCSI_INQUIRY 0x12
|
||||
#define SCSI_WRITE_BUF 0x3B
|
||||
#define SCSI_READ_BUF 0x3C
|
||||
#define SENSE_LEN 14
|
||||
#define CDB_SIZE 10
|
||||
#define BUF_SIZE 2048
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE ErrorCode; // Error Code (70H or 71H)
|
||||
BYTE SegmentNum; // Number of current segment descriptor
|
||||
BYTE SenseKey; // Sense Key(See bit definitions too)
|
||||
BYTE InfoByte0; // Information MSB
|
||||
BYTE InfoByte1; // Information MID
|
||||
BYTE InfoByte2; // Information MID
|
||||
BYTE InfoByte3; // Information LSB
|
||||
BYTE AddSenLen; // Additional Sense Length
|
||||
BYTE ComSpecInf0; // Command Specific Information MSB
|
||||
BYTE ComSpecInf1; // Command Specific Information MID
|
||||
BYTE ComSpecInf2; // Command Specific Information MID
|
||||
BYTE ComSpecInf3; // Command Specific Information LSB
|
||||
BYTE AddSenseCode; // Additional Sense Code
|
||||
BYTE AddSenQual; // Additional Sense Code Qualifier
|
||||
BYTE FieldRepUCode; // Field Replaceable Unit Code
|
||||
BYTE SenKeySpec15; // Sense Key Specific 15th byte
|
||||
BYTE SenKeySpec16; // Sense Key Specific 16th byte
|
||||
BYTE SenKeySpec17; // Sense Key Specific 17th byte
|
||||
BYTE AddSenseBytes; // Additional Sense Bytes
|
||||
} sSENSE_DATA_FMT, *pSENSE_DATA_FMT;
|
||||
|
||||
class FreeBSDSCSIInterface : public ArcInterface
|
||||
{
|
||||
public:
|
||||
FreeBSDSCSIInterface();
|
||||
~FreeBSDSCSIInterface();
|
||||
bool init(const int nScsiPort);
|
||||
int send(sIF_CMD_BLOCK *ifData);
|
||||
int recv(sIF_CMD_BLOCK *ifData);
|
||||
int syncSend(sIF_CMD_BLOCK *ifData);
|
||||
int syncSend(const char *outBuf, int outLen, char *inBuf, int inLen, void *extdata = 0);
|
||||
void requirelock();
|
||||
void releaselock();
|
||||
int getMTU();
|
||||
void *getDeviceHandle();
|
||||
|
||||
private:
|
||||
HANDLE m_hScsi;
|
||||
cam_device *arc_device;
|
||||
int fd;
|
||||
pthread_mutex_t mut;
|
||||
};
|
||||
|
||||
#endif
|
||||
Vendored
+308
@@ -0,0 +1,308 @@
|
||||
#ifndef _INTERFACE_H_
|
||||
#define _INTERFACE_H_
|
||||
|
||||
#include "commdef.h"
|
||||
|
||||
// the error code the INTERFACE returned,
|
||||
// if no error occurred, return the bytes sent or read
|
||||
//
|
||||
#define IF_OK (0)
|
||||
#define IF_MORE_DATA (-1)
|
||||
#define IF_FAIL_READ (-2)
|
||||
#define IF_FAIL_WRITE (-3)
|
||||
#define IF_NEED_RETRY (-4)
|
||||
#define IF_OVER_MTU_SIZE (-5)
|
||||
#define IF_FAIL_PARAMETER (-6)
|
||||
#define IF_READ_TIMEOUT (-7)
|
||||
#define IF_WRITE_TIMEOUT (-8)
|
||||
#define IF_CTLR_FAILED (-9)
|
||||
|
||||
|
||||
// rwflag
|
||||
#define IF_WRITE_ONLY 0x01 // just do the operation of send
|
||||
#define IF_READ_ONLY 0x02 // just do the operation of read
|
||||
#define IF_RAW_READ 0x04
|
||||
#define IF_RAW_WRITE 0x08
|
||||
#define IF_SAS 0x10
|
||||
|
||||
|
||||
// THE BELOW BLOCK IS ONLY FOR INTERNAL USE
|
||||
/************************************************************************************/
|
||||
enum
|
||||
{
|
||||
GUI_SET_SERIAL = 0x10,
|
||||
GUI_SET_VENDOR,
|
||||
GUI_SET_MODEL,
|
||||
GUI_IDENTIFY,
|
||||
GUI_CHECK_PASSWORD,
|
||||
GUI_LOGOUT,
|
||||
GUI_HTTP,
|
||||
GUI_SET_ETHERNET_ADDR,
|
||||
GUI_SET_LOGO,
|
||||
GUI_POLL_EVENT,
|
||||
GUI_GET_EVENT,
|
||||
GUI_GET_HW_MONITOR,
|
||||
GUI_SMART_TEST,
|
||||
GUI_SET_TIME,
|
||||
GUI_SNMP,
|
||||
GUI_MISC, // 0x1F
|
||||
|
||||
GUI_GET_INFO_R = 0x20,
|
||||
GUI_GET_INFO_V,
|
||||
GUI_GET_INFO_P,
|
||||
GUI_GET_INFO_S,
|
||||
GUI_CLEAR_EVENT,
|
||||
|
||||
GUI_MUTE_BEEPER = 0x30,
|
||||
GUI_BEEPER_SETTING,
|
||||
GUI_SET_PASSWORD,
|
||||
GUI_HOST_INTERFACE_MODE,
|
||||
GUI_REBUILD_PRIORITY,
|
||||
GUI_MAX_ATA_MODE,
|
||||
GUI_RESET_CONTROLLER,
|
||||
GUI_COM_PORT_SETTING,
|
||||
GUI_NO_OPERATION,
|
||||
GUI_DHCP_IP,
|
||||
|
||||
GUI_CREATE_PASS_THROUGH = 0x40,
|
||||
GUI_MODIFY_PASS_THROUGH,
|
||||
GUI_DELETE_PASS_THROUGH,
|
||||
GUI_IDENTIFY_DEVICE,
|
||||
|
||||
GUI_CREATE_RAIDSET = 0x50,
|
||||
GUI_DELETE_RAIDSET,
|
||||
GUI_EXPAND_RAIDSET,
|
||||
GUI_ACTIVATE_RAIDSET,
|
||||
GUI_CREATE_HOT_SPARE,
|
||||
GUI_DELETE_HOT_SPARE,
|
||||
|
||||
GUI_CREATE_VOLUME = 0x60,
|
||||
GUI_MODIFY_VOLUME,
|
||||
GUI_DELETE_VOLUME,
|
||||
GUI_START_CHECK_VOLUME,
|
||||
GUI_STOP_CHECK_VOLUME
|
||||
};
|
||||
|
||||
// Application specific
|
||||
enum
|
||||
{
|
||||
GUI_RAW_READ_WRITE = 0xEC,
|
||||
GUI_RAW_READ = 0xED,
|
||||
GUI_RAW_WRITE = 0xEE,
|
||||
GUI_SET_ENCLOSURE_UNIT_SERIAL,
|
||||
GUI_GET_TCPPORT,
|
||||
GUI_GET_COMATTR,
|
||||
|
||||
// status code
|
||||
GUI_WOULDBLOCK,
|
||||
GUI_TIMEOUT
|
||||
};
|
||||
/****************************************************************************************/
|
||||
|
||||
//
|
||||
// Library returned status
|
||||
//
|
||||
#define ARC_STATUS int
|
||||
#define ARC_SUCCESS 0x00 // Operation succeeded
|
||||
#define ARC_FAILURE 0x01 // Operation failed
|
||||
#define ARC_RETURN_FRAME_ERROR 0x02 // The library does not recognize the returned data
|
||||
// (including invalid data header, length or checksum, etc...)
|
||||
#define ARC_INVALID_COM_HANDLE 0x03 // Invalid RS-232 handle
|
||||
#define ARC_DATA_TRANSMIT_ERROR 0x04 // Failed to write to media
|
||||
#define ARC_DATA_RECEIVE_ERROR 0x05 // Failed to read from media( no response from raid subsystem)
|
||||
#define ARC_PARAMETER_ERROR 0x06 // The wrong parameter(s)
|
||||
#define ARC_OPENFILE_ERROR 0x07 // Failed to open file
|
||||
#define ARC_PASSWORD_REQUIRED 0x08 // Password required
|
||||
#define ARC_INVALID_PASSWORD 0x09 // Wrong password
|
||||
#define ARC_INSUFFICIENT_MEM 0x0A // Memory too small
|
||||
#define ARC_CANT_ALLOC_MEM 0x0B // Failed to allocate necessary memory
|
||||
#define ARC_BUFFER_TOO_SMALL 0x0C // The buffer is too small to put the returned data
|
||||
#define ARC_SOCKET_ERROR 0x0D // Socket error
|
||||
#define ARC_INVALID_SOCKET 0x0E // Invalid socket
|
||||
#define ARC_INIT_COM_ERROR 0x0F // Failed to open COM port
|
||||
#define ARC_SOCKET_STARTUP_ERROR 0x10 // Failed to init socket
|
||||
#define ARC_INVALID_INTERFACE 0x11 // Invalid interface
|
||||
#define ARC_NO_SUCH_DEVICE 0x12 // Device not found( including raidset, volumeset, physical drive )
|
||||
#define ARC_DATA_TRANSMIT_TIMEOUT 0x13 // Failed to write to media in a given time
|
||||
#define ARC_DATA_RECEIVE_TIMEOUT 0x14 // Failed to read from media in a given time
|
||||
#define ARC_CTLR_FAILURE 0x15 // Controller failure or inactive
|
||||
#define ARC_UNKNOWN_ERROR 0x3F // Unknown error
|
||||
|
||||
// RAID controller returned status
|
||||
#define GUI_OK 0x41 // Operation successed
|
||||
#define GUI_RAIDSET_NOT_NORMAL 0x42
|
||||
#define GUI_VOLUMESET_NOT_NORMAL 0x43
|
||||
#define GUI_NO_RAIDSET 0x44
|
||||
#define GUI_NO_VOLUMESET 0x45
|
||||
#define GUI_NO_PHYSICAL_DRIVE 0x46
|
||||
#define GUI_PARAMETER_ERROR 0x47
|
||||
#define GUI_UNSUPPORTED_COMMAND 0x48
|
||||
#define GUI_DISK_CONFIG_CHANGED 0x49
|
||||
#define GUI_INVALID_PASSWORD 0x4a
|
||||
#define GUI_NO_DISK_SPACE 0x4b
|
||||
#define GUI_CHECKSUM_ERROR 0x4c
|
||||
#define GUI_PASSWORD_REQUIRED 0x4d
|
||||
#define GUI_NO_MORE_DATA 0x4e // Internal use only
|
||||
#define GUI_INTERNAL_ERROR 0x4f
|
||||
#define GUI_FIRMWARE_CRC_ERROR 0x50
|
||||
#define GUI_FIRMWARE_INVALID 0x51
|
||||
#define GUI_FIRMWARE_UPDATE_FAILED 0x52
|
||||
#define GUI_FIRMWARE_NO_HDD 0x53
|
||||
#define GUI_END_OF_DATA 0x54
|
||||
|
||||
typedef int (*fn_decode_frame)(unsigned char *buf, int len);
|
||||
typedef unsigned char (*fn_decode_cs)(unsigned char *buf, int len);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// for internal use only
|
||||
//
|
||||
typedef struct _IF_CMD_BLOCK
|
||||
{
|
||||
unsigned long timeout; // [in]in milliseconds
|
||||
unsigned long rwflag; // [in]the flag which control the behavior of read/write
|
||||
const char *outBuf; // [in] the output data buffer to be sent
|
||||
unsigned long outLen; // [in] the output data buffer size
|
||||
char *inBuf; // [out] the input data buffer to put the firmware returned data
|
||||
unsigned long inLen; // [out] the input data buffer size
|
||||
unsigned long io_status;// [out] the status of i/o
|
||||
fn_decode_frame df; // [in]
|
||||
fn_decode_cs dc; // [in]
|
||||
}sIF_CMD_BLOCK, *pIF_CMD_BLOCK;
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
class ARCLIB_API ArcInterface
|
||||
#else
|
||||
class ArcInterface
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
virtual ~ArcInterface()
|
||||
{
|
||||
}
|
||||
virtual int send(sIF_CMD_BLOCK *ifData) = 0;
|
||||
virtual int recv(sIF_CMD_BLOCK *ifData) = 0;
|
||||
virtual int syncSend(sIF_CMD_BLOCK *ifData) = 0;
|
||||
|
||||
//
|
||||
// MTU: Maximum transmission unit
|
||||
// the size (in bytes) of the largest packet that this layer can carry out.
|
||||
//
|
||||
virtual int getMTU() = 0;
|
||||
virtual void *getDeviceHandle() = 0;
|
||||
|
||||
// These two member functions will be called by the syncSend() member function
|
||||
// to ensure the synchronization of send() and recv() to the single controller.
|
||||
// The requirelock() will be called before the send(),
|
||||
// and releaselock() will be called after the recv().
|
||||
virtual void requirelock(){}
|
||||
virtual void releaselock(){}
|
||||
|
||||
virtual int getFirmSpec()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set the timeout for interface read operation
|
||||
void setTimeOut(int nSec)
|
||||
{
|
||||
if(nSec > 0)
|
||||
{
|
||||
nTimeOut = nSec;
|
||||
}
|
||||
}
|
||||
|
||||
int getTimeOut()
|
||||
{
|
||||
return nTimeOut;
|
||||
}
|
||||
|
||||
private:
|
||||
int nTimeOut;
|
||||
};
|
||||
|
||||
|
||||
typedef void (*CMD_CALLBACK)(void *data);
|
||||
|
||||
|
||||
typedef enum _SRC_SOURCE
|
||||
{
|
||||
SRC_UNKNOWN = -1,
|
||||
SRC_COMM = 0,
|
||||
SRC_DRIVER,
|
||||
SRC_INBAND,
|
||||
SRC_ETHERNET,
|
||||
SRC_DRIVER_ODIN,
|
||||
SRC_TOTAL
|
||||
};
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
class ARCLIB_API CArclibObj
|
||||
#else
|
||||
class CArclibObj
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
CArclibObj()
|
||||
{
|
||||
m_Source = SRC_UNKNOWN;
|
||||
}
|
||||
|
||||
virtual ~CArclibObj() {}
|
||||
public:
|
||||
unsigned long m_Source;
|
||||
};
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
class ARCLIB_API CArclibBase : public CArclibObj
|
||||
#else
|
||||
class CArclibBase : public CArclibObj
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
CArclibBase()
|
||||
{
|
||||
m_Interface = NULL;
|
||||
m_CallBackFunc = NULL;
|
||||
}
|
||||
|
||||
virtual ~CArclibBase()
|
||||
{
|
||||
if(m_Interface)
|
||||
{
|
||||
delete m_Interface;
|
||||
m_Interface = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ArcSetCallBack(CMD_CALLBACK pFunc)
|
||||
{
|
||||
m_CallBackFunc = pFunc;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
Function Name: ArcInitSession
|
||||
Function: Startup areca library by assigning an interface to it
|
||||
Input: 1. ArcInterface
|
||||
Output: None.
|
||||
Return Values: 1. ARC_STATUS
|
||||
Note: This function should be called before any member functions be called
|
||||
************************************************************************************/
|
||||
virtual ARC_STATUS ArcInitSession(ArcInterface *Interface)
|
||||
{
|
||||
m_Interface = Interface;
|
||||
return ARC_SUCCESS;
|
||||
}
|
||||
|
||||
protected:
|
||||
ArcInterface *m_Interface; // The communication path to the raid-subsystem
|
||||
CMD_CALLBACK m_CallBackFunc;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
#ifndef _INTERFACE_H_
|
||||
#define _INTERFACE_H_
|
||||
|
||||
#include "commdef.h"
|
||||
|
||||
// the error code the INTERFACE returned,
|
||||
// if no error occurred, return the bytes sent or read
|
||||
//
|
||||
#define IF_OK (0)
|
||||
#define IF_MORE_DATA (-1)
|
||||
#define IF_FAIL_READ (-2)
|
||||
#define IF_FAIL_WRITE (-3)
|
||||
#define IF_NEED_RETRY (-4)
|
||||
#define IF_OVER_MTU_SIZE (-5)
|
||||
#define IF_FAIL_PARAMETER (-6)
|
||||
#define IF_READ_TIMEOUT (-7)
|
||||
#define IF_WRITE_TIMEOUT (-8)
|
||||
|
||||
|
||||
// rwflag
|
||||
#define IF_WRITE_ONLY 0x01 // just do the operation of send
|
||||
#define IF_READ_ONLY 0x02 // just do the operation of read
|
||||
#define IF_RAW_READ_WRITE 0x04 // do the raw data r/w
|
||||
#define IF_SAS 0x08
|
||||
|
||||
|
||||
typedef int (*fn_decode_frame)(unsigned char *buf, int len);
|
||||
typedef unsigned char (*fn_decode_cs)(unsigned char *buf, int len);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// for internal use only
|
||||
//
|
||||
typedef struct _IF_CMD_BLOCK
|
||||
{
|
||||
unsigned long timeout; // [in]in milliseconds
|
||||
unsigned long rwflag; // [in]the flag which control the behavior of read/write
|
||||
const char *outBuf; // [in] the output data buffer to be sent
|
||||
unsigned long outLen; // [in] the output data buffer size
|
||||
char *inBuf; // [out] the input data buffer to put the firmware returned data
|
||||
unsigned long inLen; // [out] the input data buffer size
|
||||
fn_decode_frame df; // [in]
|
||||
fn_decode_cs dc; // [in]
|
||||
}sIF_CMD_BLOCK, *pIF_CMD_BLOCK;
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
class ARCLIB_API ArcInterface
|
||||
#else
|
||||
class ArcInterface
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
virtual ~ArcInterface()
|
||||
{
|
||||
}
|
||||
virtual int send(sIF_CMD_BLOCK *ifData) = 0;
|
||||
virtual int recv(sIF_CMD_BLOCK *ifData) = 0;
|
||||
virtual int syncSend(sIF_CMD_BLOCK *ifData) = 0;
|
||||
|
||||
//
|
||||
// MTU: Maximum transmission unit
|
||||
// the size (in bytes) of the largest packet that this layer can carry out.
|
||||
//
|
||||
virtual int getMTU() = 0;
|
||||
virtual void *getDeviceHandle() = 0;
|
||||
|
||||
// These two member functions will be called by the syncSend() member function
|
||||
// to ensure the synchronization of send() and recv() to the single controller.
|
||||
// The requirelock() will be called before the send() called,
|
||||
// and releaselock() will be called after the recv() called.
|
||||
virtual void requirelock(){}
|
||||
virtual void releaselock(){}
|
||||
|
||||
|
||||
// set the timeout for interface read operation
|
||||
void setTimeOut(int nSec)
|
||||
{
|
||||
if(nSec > 0)
|
||||
{
|
||||
nTimeOut = nSec;
|
||||
}
|
||||
}
|
||||
|
||||
int getTimeOut()
|
||||
{
|
||||
return nTimeOut;
|
||||
}
|
||||
|
||||
private:
|
||||
int nTimeOut;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
#ifndef _LINUXCOMM_H_
|
||||
#define _LINUXCOMM_H_
|
||||
|
||||
#include "commdef.h"
|
||||
#include "interface.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
class LinuxCommInterface : public ArcInterface
|
||||
{
|
||||
public:
|
||||
LinuxCommInterface();
|
||||
~LinuxCommInterface();
|
||||
bool init(const char nPortNum, char nBaudRate = 7, char nStopBit = 0);
|
||||
int send(sIF_CMD_BLOCK *ifData);
|
||||
int recv(sIF_CMD_BLOCK *ifData);
|
||||
int syncSend(sIF_CMD_BLOCK *ifData);
|
||||
void requirelock();
|
||||
void releaselock();
|
||||
int getMTU();
|
||||
void *getDeviceHandle();
|
||||
|
||||
public:
|
||||
BOOL ClearReadWriteBuffer();
|
||||
int m_hComm;
|
||||
int fd;
|
||||
pthread_mutex_t mut;
|
||||
};
|
||||
|
||||
#endif
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
#ifndef __LINUXIOCTL_H__
|
||||
#define __LINUXIOCTL_H__
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <pthread.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <errno.h> /* Error number definitions */
|
||||
#include <unistd.h> /* fork() */
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef __linux__
|
||||
#include <scsi/sg.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "commdef.h"
|
||||
#include "interface.h"
|
||||
|
||||
|
||||
/*DeviceType*/
|
||||
#define ARECA_SATA_RAID 0x90000000
|
||||
/*FunctionCode*/
|
||||
#define FUNCTION_READ_RQBUFFER 0x0801
|
||||
#define FUNCTION_WRITE_WQBUFFER 0x0802
|
||||
#define FUNCTION_CLEAR_RQBUFFER 0x0803
|
||||
#define FUNCTION_CLEAR_WQBUFFER 0x0804
|
||||
#define FUNCTION_CLEAR_ALLQBUFFER 0x0805
|
||||
#define FUNCTION_RETURN_CODE_3F 0x0806
|
||||
#define FUNCTION_SAY_HELLO 0x0807
|
||||
|
||||
#if defined(__linux__) || defined (__solaris__)
|
||||
/* ARECA IO CONTROL CODE*/
|
||||
#define ARCMSR_IOCTL_READ_RQBUFFER ARECA_SATA_RAID | FUNCTION_READ_RQBUFFER
|
||||
#define ARCMSR_IOCTL_WRITE_WQBUFFER ARECA_SATA_RAID | FUNCTION_WRITE_WQBUFFER
|
||||
#define ARCMSR_IOCTL_CLEAR_RQBUFFER ARECA_SATA_RAID | FUNCTION_CLEAR_RQBUFFER
|
||||
#define ARCMSR_IOCTL_CLEAR_WQBUFFER ARECA_SATA_RAID | FUNCTION_CLEAR_WQBUFFER
|
||||
#define ARCMSR_IOCTL_CLEAR_ALLQBUFFER ARECA_SATA_RAID | FUNCTION_CLEAR_ALLQBUFFER
|
||||
#define ARCMSR_IOCTL_RETURN_CODE_3F ARECA_SATA_RAID | FUNCTION_RETURN_CODE_3F
|
||||
#define ARCMSR_IOCTL_SAY_HELLO ARECA_SATA_RAID | FUNCTION_SAY_HELLO
|
||||
#elif __FreeBSD__
|
||||
#define ARCMSR_IOCTL_READ_RQBUFFER _IOWR('F', FUNCTION_READ_RQBUFFER, sSRB_BUFFER)
|
||||
#define ARCMSR_IOCTL_WRITE_WQBUFFER _IOWR('F', FUNCTION_WRITE_WQBUFFER, sSRB_BUFFER)
|
||||
#define ARCMSR_IOCTL_CLEAR_RQBUFFER _IOWR('F', FUNCTION_CLEAR_RQBUFFER, sSRB_BUFFER)
|
||||
#define ARCMSR_IOCTL_CLEAR_WQBUFFER _IOWR('F', FUNCTION_CLEAR_WQBUFFER, sSRB_BUFFER)
|
||||
#define ARCMSR_IOCTL_CLEAR_ALLQBUFFER _IOWR('F', FUNCTION_CLEAR_ALLQBUFFER, sSRB_BUFFER)
|
||||
#define ARCMSR_IOCTL_RETURN_CODE_3F _IOWR('F', FUNCTION_RETURN_CODE_3F, sSRB_BUFFER)
|
||||
#define ARCMSR_IOCTL_SAY_HELLO _IOWR('F', FUNCTION_SAY_HELLO, sSRB_BUFFER)
|
||||
#endif
|
||||
|
||||
|
||||
/* ARECA IOCTL ReturnCode */
|
||||
#define ARCMSR_IOCTL_RETURNCODE_OK 0x01
|
||||
#define ARCMSR_IOCTL_RETURNCODE_ERROR 0x06
|
||||
#define ARCMSR_IOCTL_RETURNCODE_3F 0x3F
|
||||
|
||||
|
||||
typedef struct _SRB_IO_CONTROL
|
||||
{
|
||||
unsigned int HeaderLength;
|
||||
UCHAR Signature[8];
|
||||
unsigned int Timeout;
|
||||
unsigned int ControlCode;
|
||||
unsigned int ReturnCode;
|
||||
unsigned int Length;
|
||||
} sSRB_IO_CONTROL, *pSRB_IO_CONTROL;
|
||||
|
||||
typedef struct _SRB_BUFFER
|
||||
{
|
||||
sSRB_IO_CONTROL srbioctl; // ioctl header
|
||||
UCHAR ioctldatabuffer[1032]; // areca gui program does not accept more than 1031 byte
|
||||
} sSRB_BUFFER, *pSRB_BUFFER;
|
||||
|
||||
|
||||
class LinuxIoctlInterface : public ArcInterface
|
||||
{
|
||||
public:
|
||||
LinuxIoctlInterface();
|
||||
~LinuxIoctlInterface();
|
||||
bool init(const int nScsiPort);
|
||||
int send(sIF_CMD_BLOCK *ifData);
|
||||
int recv(sIF_CMD_BLOCK *ifData);
|
||||
int syncSend(sIF_CMD_BLOCK *ifData);
|
||||
void requirelock();
|
||||
void releaselock();
|
||||
int getMTU();
|
||||
void *getDeviceHandle();
|
||||
private:
|
||||
BOOL ClearReadBuffer();
|
||||
BOOL ClearWriteBuffer();
|
||||
BOOL ClearReadWriteBuffer();
|
||||
HANDLE m_hScsi;
|
||||
int fd;
|
||||
pthread_mutex_t mut;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef __LINUX_PASS_IOCTL_H__
|
||||
#define __LINUX_PASS_IOCTL_H__
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <pthread.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <errno.h> /* Error number definitions */
|
||||
#include <unistd.h> /* fork() */
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef __linux__
|
||||
#include <scsi/sg.h>
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_ioctl.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "commdef.h"
|
||||
#include "interface.h"
|
||||
#include "arclib.h"
|
||||
|
||||
#define SCSI_INQUIRY 0x12
|
||||
#define SCSI_WRITE_BUF 0x3B
|
||||
#define SCSI_READ_BUF 0x3C
|
||||
#define SENSE_LEN 14
|
||||
#define CDB_SIZE 10
|
||||
#define BUF_SIZE 2048
|
||||
|
||||
|
||||
|
||||
class LinuxPassIoctlInterface : public ArcInterface
|
||||
{
|
||||
public:
|
||||
LinuxPassIoctlInterface();
|
||||
~LinuxPassIoctlInterface();
|
||||
bool init(const int nScsiPort);
|
||||
int send(sIF_CMD_BLOCK *ifData);
|
||||
int recv(sIF_CMD_BLOCK *ifData);
|
||||
int syncSend(sIF_CMD_BLOCK *ifData);
|
||||
void requirelock();
|
||||
void releaselock();
|
||||
BOOL ClearReadBuffer();
|
||||
BOOL ClearWriteBuffer();
|
||||
BOOL ClearReadWriteBuffer();
|
||||
int getMTU();
|
||||
void *getDeviceHandle();
|
||||
public:
|
||||
HANDLE m_hScsi;
|
||||
int fd;
|
||||
pthread_mutex_t mut;
|
||||
};
|
||||
|
||||
#endif
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
#ifndef __LINUXSCSI_H__
|
||||
#define __LINUXSCSI_H__
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <pthread.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <errno.h> /* Error number definitions */
|
||||
#include <unistd.h> /* fork() */
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef __linux__
|
||||
#include <scsi/sg.h>
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_ioctl.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "commdef.h"
|
||||
#include "interface.h"
|
||||
#include "arclib.h"
|
||||
|
||||
#define SCSI_INQUIRY 0x12
|
||||
#define SCSI_WRITE_BUF 0x3B
|
||||
#define SCSI_READ_BUF 0x3C
|
||||
#define SENSE_LEN 14
|
||||
#define CDB_SIZE 10
|
||||
#define BUF_SIZE 2048
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int inlen; // [i] Length of data written to device
|
||||
int outlen; // [i] Length of data read from device
|
||||
char cdb[CDB_SIZE]; // [i] SCSI command (6 <= x <= 16)
|
||||
// [o] Data read from device starts here
|
||||
// [o] On error, sense buffer starts here
|
||||
char buf[4100]; // [i] Data written to device starts here
|
||||
}sSRB_BUF, *pSRB_BUF;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE ErrorCode; // Error Code (70H or 71H)
|
||||
BYTE SegmentNum; // Number of current segment descriptor
|
||||
BYTE SenseKey; // Sense Key(See bit definitions too)
|
||||
BYTE InfoByte0; // Information MSB
|
||||
BYTE InfoByte1; // Information MID
|
||||
BYTE InfoByte2; // Information MID
|
||||
BYTE InfoByte3; // Information LSB
|
||||
BYTE AddSenLen; // Additional Sense Length
|
||||
BYTE ComSpecInf0; // Command Specific Information MSB
|
||||
BYTE ComSpecInf1; // Command Specific Information MID
|
||||
BYTE ComSpecInf2; // Command Specific Information MID
|
||||
BYTE ComSpecInf3; // Command Specific Information LSB
|
||||
BYTE AddSenseCode; // Additional Sense Code
|
||||
BYTE AddSenQual; // Additional Sense Code Qualifier
|
||||
BYTE FieldRepUCode; // Field Replaceable Unit Code
|
||||
BYTE SenKeySpec15; // Sense Key Specific 15th byte
|
||||
BYTE SenKeySpec16; // Sense Key Specific 16th byte
|
||||
BYTE SenKeySpec17; // Sense Key Specific 17th byte
|
||||
BYTE AddSenseBytes; // Additional Sense Bytes
|
||||
} sSENSE_DATA_FMT, *pSENSE_DATA_FMT;
|
||||
|
||||
class LinuxSCSIInterface : public ArcInterface
|
||||
{
|
||||
public:
|
||||
LinuxSCSIInterface();
|
||||
~LinuxSCSIInterface();
|
||||
bool init(const int nScsiPort);
|
||||
int send(sIF_CMD_BLOCK *ifData);
|
||||
int recv(sIF_CMD_BLOCK *ifData);
|
||||
int syncSend(sIF_CMD_BLOCK *ifData);
|
||||
void requirelock();
|
||||
void releaselock();
|
||||
int getMTU();
|
||||
void *getDeviceHandle();
|
||||
|
||||
public:
|
||||
HANDLE m_hScsi;
|
||||
int fd;
|
||||
pthread_mutex_t mut;
|
||||
};
|
||||
|
||||
#endif
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
#ifndef _SASBASE_H
|
||||
#define _SASBASE_H
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
enum _SAS_ATTRIBUTE_ITEMS
|
||||
{
|
||||
SAS_READ_RECOVERED_WO_DELAY,
|
||||
SAS_READ_RECOVERED_W_DELAY,
|
||||
SAS_READ_RECOVERED_W_RETRY,
|
||||
SAS_READ_RECOVERED,
|
||||
SAS_READ_TOTAL_BYTES,
|
||||
SAS_READ_UNRECOVERED,
|
||||
SAS_WRITE_RECOVERED_WO_DELAY,
|
||||
SAS_WRITE_RECOVERED_W_DELAY,
|
||||
SAS_WRITE_RECOVERED_W_RETRY,
|
||||
SAS_WRITE_RECOVERED,
|
||||
SAS_WRITE_TOTAL_BYTES,
|
||||
SAS_WRITE_UNRECOVERED,
|
||||
SAS_VERIFY_RECOVERED_WO_DELAY,
|
||||
SAS_VERIFY_RECOVERED_W_DELAY,
|
||||
SAS_VERIFY_RECOVERED_W_RETRY,
|
||||
SAS_VERIFY_RECOVERED,
|
||||
SAS_VERIFY_UNRECOVERED,
|
||||
SAS_NON_MEDIUM_ERRORS,
|
||||
TOTAL_SAS_ATTR_ITEMS
|
||||
};
|
||||
|
||||
enum _SMART_ITEMS
|
||||
{
|
||||
SMART_READ_ERROR_RATE_1, // read error rate
|
||||
SMART_SPINUP_TIME_3, // spinup time
|
||||
SMART_REALLOCATION_5, // reallocation
|
||||
SMART_SEEK_ERROR_RATE_7, // seek error rate
|
||||
SMART_SPINUP_RETRY_10, // spinup retry
|
||||
SMART_CALIBRATION_RETRY_11, // calibration retry
|
||||
SMART_TEMPERATURE_194, // temperature
|
||||
TOTAL_SMART_ITEMS,
|
||||
};
|
||||
|
||||
enum _SAS_HW
|
||||
{
|
||||
SAS_HW_DISK, // disks
|
||||
SAS_HW_VOLTAGE, // voltages
|
||||
SAS_HW_FAN, // fans
|
||||
SAS_HW_POWER, // powers
|
||||
SAS_HW_TEMPERATURE, // temperatures
|
||||
TOTAL_SAS_HW
|
||||
};
|
||||
|
||||
typedef struct sSMART_DATA
|
||||
{
|
||||
WORD smIndex;
|
||||
BYTE smStatus;
|
||||
BYTE smThreshold;
|
||||
} sSMART_DATA, *pSMART_DATA;
|
||||
|
||||
// SCSI attribtes
|
||||
typedef struct sSCSI_ATTR
|
||||
{
|
||||
BYTE scsiChannel; // channel for SCSI target (0/1)
|
||||
BYTE scsiId; // SCSI ID for the volume
|
||||
BYTE scsiLun; // LUN (0 if target is IDE)
|
||||
BYTE scsiTaggedQueuing; // 1 --> queue enabled
|
||||
BYTE scsiCacheMode; // 1 --> Cache enabled
|
||||
BYTE scsiSpeed; // IDE(0:ATA33/1:ATA66/2:ATA100/3:ATA133)
|
||||
} sSCSI_ATTR, *pSCSI_ATTR;
|
||||
|
||||
|
||||
typedef struct sGUI_ENC_PROPERTY
|
||||
{
|
||||
BYTE gepVendor[8]; // vendor name
|
||||
BYTE gepProduct[16]; // product name
|
||||
BYTE gepRev[4]; // reversion
|
||||
BYTE gepEncType; // enclosure type
|
||||
BYTE gepEncnumber; // enclosure#
|
||||
BYTE gepEncDisks; // number of disks
|
||||
BYTE gepEncVoltages; // number of voltages
|
||||
BYTE gepEncFans; // number of fans
|
||||
BYTE gepEncPowers; // number of powers
|
||||
BYTE gepEncTemperatures; // number of temperatures
|
||||
BYTE gepRes[0x1D]; // reserved
|
||||
} sGUI_ENC_PROPERTY, *pGUI_ENC_PROPERTY;
|
||||
|
||||
|
||||
#define MAX_ENCLOSURES 8
|
||||
#define MAX_PHY_PER_ENCLOSURE 32
|
||||
#define MAX_DEV_PER_ENCLOSURE 32
|
||||
|
||||
enum
|
||||
{
|
||||
ENC_TYPE_NOT_INSTALLED, // not installed
|
||||
ENC_TYPE_INTERNAL, // built-in enclosure
|
||||
ENC_TYPE_SES2, // ses2
|
||||
ENC_TYPE_SMP, // smp
|
||||
ENC_TYPE_CTRL // controller
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define MAX_ELEMENT_STR_LEN 24
|
||||
#define MAX_SENSORS 32
|
||||
|
||||
|
||||
|
||||
// constant of SES element definitions
|
||||
// common status
|
||||
#define SES_COMMON_STATUS_OK 0x00000001
|
||||
#define SES_COMMON_STATUS_CRITICAL 0x00000002
|
||||
|
||||
// power
|
||||
#define SES_POWER_FAIL 0x40000000
|
||||
|
||||
// fan(cooling)
|
||||
#define SES_FAN_FAIL 0x40000000
|
||||
|
||||
// temperature
|
||||
#define SES_OVER_TEMPERATURE 0x08000000
|
||||
|
||||
// voltage
|
||||
#define SES_OVER_VOLTAGE 0x00000200
|
||||
#define SES_UNDER_VOLTAGE 0x00000100
|
||||
|
||||
#define SES_STATUS_OK(x) (x & SES_COMMON_STATUS_OK)
|
||||
#define SES_STATUS_CRITICAL(x) (x & SES_COMMON_STATUS_CRITICAL)
|
||||
|
||||
|
||||
typedef struct sELEMENT
|
||||
{
|
||||
BYTE snNumberOfSensors; // number of elements
|
||||
BYTE snElementStr[MAX_SENSORS][MAX_ELEMENT_STR_LEN]; // description of elements
|
||||
LONG snValue[MAX_SENSORS]; // the value of sensor
|
||||
DWORD snRawValue[MAX_SENSORS]; // the SES RAW value of sensor
|
||||
}sELEMENT, *pELEMENT;
|
||||
|
||||
typedef struct sDISK_ELEMENT
|
||||
{
|
||||
BYTE snNumberOfElements; // number of elements
|
||||
BYTE snElementStr[MAX_SENSORS][MAX_ELEMENT_STR_LEN]; // description of elements
|
||||
}sDISK_ELEMENT, *pDISK_ELEMENT;
|
||||
|
||||
typedef struct sSENSORS
|
||||
{
|
||||
sDISK_ELEMENT disk;
|
||||
sELEMENT voltage;
|
||||
sELEMENT fan;
|
||||
sELEMENT power;
|
||||
sELEMENT temperature;
|
||||
sELEMENT battery;
|
||||
} sSENSORS, *pSENSORS;
|
||||
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#endif
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
#ifndef _SOLARISCOMM_H_
|
||||
#define _SOLARISCOMM_H_
|
||||
|
||||
#include "commdef.h"
|
||||
#include "interface.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
class SolarisCommInterface : public ArcInterface
|
||||
{
|
||||
public:
|
||||
SolarisCommInterface();
|
||||
~SolarisCommInterface();
|
||||
bool init(const char nPortNum, char nBaudRate = 7, char nStopBit = 0);
|
||||
int send(sIF_CMD_BLOCK *ifData);
|
||||
int recv(sIF_CMD_BLOCK *ifData);
|
||||
int syncSend(sIF_CMD_BLOCK *ifData);
|
||||
void requirelock();
|
||||
void releaselock();
|
||||
int getMTU();
|
||||
void *getDeviceHandle();
|
||||
BOOL ClearReadBuffer();
|
||||
BOOL ClearWriteBuffer();
|
||||
BOOL ClearReadWriteBuffer();
|
||||
|
||||
private:
|
||||
int m_hComm;
|
||||
int fd;
|
||||
pthread_mutex_t mut;
|
||||
};
|
||||
|
||||
#endif
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
#ifndef __SOLARISIOCTL_H__
|
||||
#define __SOLARISIOCTL_H__
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <pthread.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <errno.h> /* Error number definitions */
|
||||
#include <unistd.h> /* fork() */
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <ftw.h>
|
||||
|
||||
#include <sys/mhd.h>
|
||||
#include <sys/scsi/impl/uscsi.h>
|
||||
#include <sys/scsi/generic/commands.h>
|
||||
#include <sys/scsi/generic/inquiry.h>
|
||||
|
||||
|
||||
#include "commdef.h"
|
||||
#include "interface.h"
|
||||
|
||||
typedef struct _SRB_IO_CONTROL sSRB_IO_CONTROL, *pSRB_IO_CONTROL;
|
||||
typedef struct _SRB_BUFFER sSRB_BUFFER, *pSRB_BUFFER;
|
||||
|
||||
|
||||
/*DeviceType*/
|
||||
#define ARECA_SATA_RAID 0x90000000
|
||||
/*FunctionCode*/
|
||||
#define FUNCTION_READ_RQBUFFER 0x0801
|
||||
#define FUNCTION_WRITE_WQBUFFER 0x0802
|
||||
#define FUNCTION_CLEAR_RQBUFFER 0x0803
|
||||
#define FUNCTION_CLEAR_WQBUFFER 0x0804
|
||||
#define FUNCTION_CLEAR_ALLQBUFFER 0x0805
|
||||
#define FUNCTION_RETURN_CODE_3F 0x0806
|
||||
#define FUNCTION_SAY_HELLO 0x0807
|
||||
#define FUNCTION_SAY_GOODBYE 0x0808
|
||||
/* ARECA IO CONTROL CODE*/
|
||||
#define ARCMSR_IOCTL_READ_RQBUFFER ARECA_SATA_RAID | FUNCTION_READ_RQBUFFER
|
||||
#define ARCMSR_IOCTL_WRITE_WQBUFFER ARECA_SATA_RAID | FUNCTION_WRITE_WQBUFFER
|
||||
#define ARCMSR_IOCTL_CLEAR_RQBUFFER ARECA_SATA_RAID | FUNCTION_CLEAR_RQBUFFER
|
||||
#define ARCMSR_IOCTL_CLEAR_WQBUFFER ARECA_SATA_RAID | FUNCTION_CLEAR_WQBUFFER
|
||||
#define ARCMSR_IOCTL_CLEAR_ALLQBUFFER ARECA_SATA_RAID | FUNCTION_CLEAR_ALLQBUFFER
|
||||
#define ARCMSR_IOCTL_RETURN_CODE_3F ARECA_SATA_RAID | FUNCTION_RETURN_CODE_3F
|
||||
#define ARCMSR_IOCTL_SAY_HELLO ARECA_SATA_RAID | FUNCTION_SAY_HELLO
|
||||
#define ARCMSR_IOCTL_SAY_GOODBYE ARECA_SATA_RAID | FUNCTION_SAY_GOODBYE
|
||||
/* ARECA IOCTL ReturnCode */
|
||||
#define ARCMSR_IOCTL_RETURNCODE_OK 0x00000001
|
||||
#define ARCMSR_IOCTL_RETURNCODE_ERROR 0x00000006
|
||||
#define ARCMSR_IOCTL_RETURNCODE_3F 0x0000003F
|
||||
#define SYSERR (-1)
|
||||
|
||||
typedef struct _SRB_IO_CONTROL
|
||||
{
|
||||
unsigned int HeaderLength;
|
||||
UCHAR Signature[8];
|
||||
unsigned int Timeout;
|
||||
unsigned int ControlCode;
|
||||
unsigned int ReturnCode;
|
||||
unsigned int Length;
|
||||
};
|
||||
|
||||
|
||||
typedef struct _SRB_BUFFER
|
||||
{
|
||||
sSRB_IO_CONTROL srbioctl; /*ioctl header*/
|
||||
UCHAR ioctldatabuffer[224];/*areca gui program does not accept more than 1031 byte*/
|
||||
};
|
||||
|
||||
|
||||
class SolarisIoctlInterface : public ArcInterface
|
||||
{
|
||||
public:
|
||||
SolarisIoctlInterface();
|
||||
~SolarisIoctlInterface();
|
||||
bool init(const int nScsiPort);
|
||||
int send(sIF_CMD_BLOCK *ifData);
|
||||
int recv(sIF_CMD_BLOCK *ifData);
|
||||
int syncSend(sIF_CMD_BLOCK *ifData);
|
||||
void requirelock();
|
||||
void releaselock();
|
||||
void *getDeviceHandle();
|
||||
BOOL ClearReadBuffer();
|
||||
BOOL ClearWriteBuffer();
|
||||
BOOL ClearReadWriteBuffer();
|
||||
int getMTU();
|
||||
private:
|
||||
HANDLE m_hScsi;
|
||||
int fd;
|
||||
pthread_mutex_t mut;
|
||||
};
|
||||
|
||||
#endif
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
#ifndef __SOLARISSCSI_H__
|
||||
#define __SOLARISSCSI_H__
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <pthread.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <errno.h> /* Error number definitions */
|
||||
#include <unistd.h> /* fork() */
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef __linux__
|
||||
#include <scsi/sg.h>
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_ioctl.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "commdef.h"
|
||||
#include "interface.h"
|
||||
#include "arclib.h"
|
||||
|
||||
#define SCSI_INQUIRY 0x12
|
||||
#define SCSI_WRITE_BUF 0x3B
|
||||
#define SCSI_READ_BUF 0x3C
|
||||
#define SENSE_LEN 14
|
||||
#define CDB_SIZE 10
|
||||
#define BUF_SIZE 2048
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int inlen; // [i] Length of data written to device
|
||||
int outlen; // [i] Length of data read from device
|
||||
char cdb[CDB_SIZE]; // [i] SCSI command (6 <= x <= 16)
|
||||
// [o] Data read from device starts here
|
||||
// [o] On error, sense buffer starts here
|
||||
char buf[4100]; // [i] Data written to device starts here
|
||||
}sSRB_BUF, *pSRB_BUF;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE ErrorCode; // Error Code (70H or 71H)
|
||||
BYTE SegmentNum; // Number of current segment descriptor
|
||||
BYTE SenseKey; // Sense Key(See bit definitions too)
|
||||
BYTE InfoByte0; // Information MSB
|
||||
BYTE InfoByte1; // Information MID
|
||||
BYTE InfoByte2; // Information MID
|
||||
BYTE InfoByte3; // Information LSB
|
||||
BYTE AddSenLen; // Additional Sense Length
|
||||
BYTE ComSpecInf0; // Command Specific Information MSB
|
||||
BYTE ComSpecInf1; // Command Specific Information MID
|
||||
BYTE ComSpecInf2; // Command Specific Information MID
|
||||
BYTE ComSpecInf3; // Command Specific Information LSB
|
||||
BYTE AddSenseCode; // Additional Sense Code
|
||||
BYTE AddSenQual; // Additional Sense Code Qualifier
|
||||
BYTE FieldRepUCode; // Field Replaceable Unit Code
|
||||
BYTE SenKeySpec15; // Sense Key Specific 15th byte
|
||||
BYTE SenKeySpec16; // Sense Key Specific 16th byte
|
||||
BYTE SenKeySpec17; // Sense Key Specific 17th byte
|
||||
BYTE AddSenseBytes; // Additional Sense Bytes
|
||||
} sSENSE_DATA_FMT, *pSENSE_DATA_FMT;
|
||||
|
||||
class SolarisSCSIInterface : public ArcInterface
|
||||
{
|
||||
public:
|
||||
SolarisSCSIInterface();
|
||||
~SolarisSCSIInterface();
|
||||
bool init(const int nScsiPort);
|
||||
int send(sIF_CMD_BLOCK *ifData);
|
||||
int recv(sIF_CMD_BLOCK *ifData);
|
||||
int syncSend(sIF_CMD_BLOCK *ifData);
|
||||
int getMTU();
|
||||
void *getDeviceHandle();
|
||||
|
||||
private:
|
||||
|
||||
HANDLE m_hScsi;
|
||||
//pthread_mutex_t *m_LOCK;
|
||||
int fd;
|
||||
};
|
||||
|
||||
#endif
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
#ifndef _WINCOMM_H_
|
||||
#define _WINCOMM_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <tchar.h>
|
||||
// TODO: reference additional headers your program requires here
|
||||
#include <wtypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
#include "commdef.h"
|
||||
#include "interface.h"
|
||||
|
||||
|
||||
class ARCLIB_API WinCommInterface : public ArcInterface
|
||||
{
|
||||
friend class CArclib;
|
||||
public:
|
||||
WinCommInterface();
|
||||
~WinCommInterface();
|
||||
bool init(const char nPortNum, char nBaudRate = 7, char nStopBit = 0);
|
||||
int send(sIF_CMD_BLOCK *ifData);
|
||||
int recv(sIF_CMD_BLOCK *ifData);
|
||||
int syncSend(sIF_CMD_BLOCK *ifData);
|
||||
int getMTU();
|
||||
void *getDeviceHandle();
|
||||
void requirelock();
|
||||
void releaselock();
|
||||
|
||||
private:
|
||||
BOOL ClearReadBuffer();
|
||||
BOOL ClearWriteBuffer();
|
||||
BOOL ClearReadWriteBuffer();
|
||||
HANDLE m_hComm;
|
||||
HANDLE m_hSyncComm;
|
||||
PSECURITY_DESCRIPTOR pSD;
|
||||
};
|
||||
|
||||
#endif
|
||||
BIN
Binary file not shown.
+132
@@ -0,0 +1,132 @@
|
||||
#ifndef _WIN_PASS_IOCTL_H_
|
||||
#define _WIN_PASS_IOCTL_H_
|
||||
|
||||
#include "commdef.h"
|
||||
#include "interface.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <tchar.h>
|
||||
#include <wtypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
#include <winioctl.h>
|
||||
|
||||
#define FILE_DEVICE_CONTROLLER 0x00000004
|
||||
|
||||
#define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER
|
||||
#define IOCTL_SCSI_MINIPORT CTL_CODE(IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) //0x0004D008 see NTDDSCSI.H for definition
|
||||
#define IOCTL_SCSI_RESCAN_BUS CTL_CODE(IOCTL_SCSI_BASE, 0x0407, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_SCSI_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
|
||||
#define ARCMSR_IOCTL_READ_RQBUFFER 0x90002004
|
||||
#define ARCMSR_IOCTL_WRITE_WQBUFFER 0x90002008
|
||||
#define ARCMSR_IOCTL_CLEAR_RQBUFFER 0x9000200C
|
||||
#define ARCMSR_IOCTL_CLEAR_WQBUFFER 0x90002010
|
||||
#define ARCMSR_IOCTL_CLEAR_ALLQBUFFER 0x90002014
|
||||
#define ARCMSR_IOCTL_RETURN_CODE_3F 0x90002018
|
||||
#define ARCMSR_IOCTL_SAY_HELLO 0x9000201C
|
||||
|
||||
|
||||
// return code
|
||||
#define SRB_STATUS_SUCCESS 0x01
|
||||
#define SRB_STATUS_INVALID_REQUEST 0x06
|
||||
|
||||
|
||||
class ARCLIB_API WinPassIoctlInterface : public ArcInterface
|
||||
{
|
||||
friend class CArclib;
|
||||
|
||||
public:
|
||||
WinPassIoctlInterface();
|
||||
~WinPassIoctlInterface();
|
||||
bool init(const int nScsiPort);
|
||||
int send(sIF_CMD_BLOCK *ifData);
|
||||
int recv(sIF_CMD_BLOCK *ifData);
|
||||
int syncSend(sIF_CMD_BLOCK *ifData);
|
||||
int getMTU();
|
||||
void *getDeviceHandle();
|
||||
void requirelock();
|
||||
void releaselock();
|
||||
|
||||
private:
|
||||
BOOL ClearReadBuffer();
|
||||
BOOL ClearWriteBuffer();
|
||||
BOOL ClearReadWriteBuffer();
|
||||
HANDLE m_hScsi;
|
||||
HANDLE m_hSyncIm;
|
||||
PSECURITY_DESCRIPTOR pSD;
|
||||
};
|
||||
|
||||
//
|
||||
// SCSI CDB operation codes
|
||||
//
|
||||
|
||||
#define SCSIOP_TEST_UNIT_READY 0x00
|
||||
#define SCSIOP_REZERO_UNIT 0x01
|
||||
#define SCSIOP_REWIND 0x01
|
||||
#define SCSIOP_REQUEST_BLOCK_ADDR 0x02
|
||||
#define SCSIOP_REQUEST_SENSE 0x03
|
||||
#define SCSIOP_FORMAT_UNIT 0x04
|
||||
#define SCSIOP_READ_BLOCK_LIMITS 0x05
|
||||
#define SCSIOP_REASSIGN_BLOCKS 0x07
|
||||
#define SCSIOP_READ6 0x08
|
||||
#define SCSIOP_RECEIVE 0x08
|
||||
#define SCSIOP_WRITE6 0x0A
|
||||
#define SCSIOP_PRINT 0x0A
|
||||
#define SCSIOP_SEND 0x0A
|
||||
#define SCSIOP_SEEK6 0x0B
|
||||
#define SCSIOP_TRACK_SELECT 0x0B
|
||||
#define SCSIOP_SLEW_PRINT 0x0B
|
||||
#define SCSIOP_SEEK_BLOCK 0x0C
|
||||
#define SCSIOP_PARTITION 0x0D
|
||||
#define SCSIOP_READ_REVERSE 0x0F
|
||||
#define SCSIOP_WRITE_FILEMARKS 0x10
|
||||
#define SCSIOP_FLUSH_BUFFER 0x10
|
||||
#define SCSIOP_SPACE 0x11
|
||||
#define SCSIOP_INQUIRY 0x12
|
||||
#define SCSIOP_VERIFY6 0x13
|
||||
#define SCSIOP_RECOVER_BUF_DATA 0x14
|
||||
#define SCSIOP_MODE_SELECT 0x15
|
||||
#define SCSIOP_RESERVE_UNIT 0x16
|
||||
#define SCSIOP_RELEASE_UNIT 0x17
|
||||
#define SCSIOP_COPY 0x18
|
||||
#define SCSIOP_ERASE 0x19
|
||||
#define SCSIOP_MODE_SENSE 0x1A
|
||||
#define SCSIOP_START_STOP_UNIT 0x1B
|
||||
#define SCSIOP_STOP_PRINT 0x1B
|
||||
#define SCSIOP_LOAD_UNLOAD 0x1B
|
||||
#define SCSIOP_RECEIVE_DIAGNOSTIC 0x1C
|
||||
#define SCSIOP_SEND_DIAGNOSTIC 0x1D
|
||||
#define SCSIOP_MEDIUM_REMOVAL 0x1E
|
||||
#define SCSIOP_READ_CAPACITY 0x25
|
||||
#define SCSIOP_READ 0x28
|
||||
#define SCSIOP_WRITE 0x2A
|
||||
#define SCSIOP_SEEK 0x2B
|
||||
#define SCSIOP_LOCATE 0x2B
|
||||
#define SCSIOP_WRITE_VERIFY 0x2E
|
||||
#define SCSIOP_VERIFY 0x2F
|
||||
#define SCSIOP_SEARCH_DATA_HIGH 0x30
|
||||
#define SCSIOP_SEARCH_DATA_EQUAL 0x31
|
||||
#define SCSIOP_SEARCH_DATA_LOW 0x32
|
||||
#define SCSIOP_SET_LIMITS 0x33
|
||||
#define SCSIOP_READ_POSITION 0x34
|
||||
#define SCSIOP_SYNCHRONIZE_CACHE 0x35
|
||||
#define SCSIOP_COMPARE 0x39
|
||||
#define SCSIOP_COPY_COMPARE 0x3A
|
||||
#define SCSIOP_WRITE_DATA_BUFF 0x3B
|
||||
#define SCSIOP_READ_DATA_BUFF 0x3C
|
||||
#define SCSIOP_CHANGE_DEFINITION 0x40
|
||||
#define SCSIOP_READ_SUB_CHANNEL 0x42
|
||||
#define SCSIOP_READ_TOC 0x43
|
||||
#define SCSIOP_READ_HEADER 0x44
|
||||
#define SCSIOP_PLAY_AUDIO 0x45
|
||||
#define SCSIOP_PLAY_AUDIO_MSF 0x47
|
||||
#define SCSIOP_PLAY_TRACK_INDEX 0x48
|
||||
#define SCSIOP_PLAY_TRACK_RELATIVE 0x49
|
||||
#define SCSIOP_PAUSE_RESUME 0x4B
|
||||
#define SCSIOP_LOG_SELECT 0x4C
|
||||
#define SCSIOP_LOG_SENSE 0x4D
|
||||
|
||||
#endif
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
#ifndef _WIN_PASS_IOCTL_ODIN_H_
|
||||
#define _WIN_PASS_IOCTL_ODIN_H_
|
||||
|
||||
#include "commdef.h"
|
||||
#include "if.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <tchar.h>
|
||||
#include <wtypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
#include <winioctl.h>
|
||||
|
||||
#define FILE_DEVICE_CONTROLLER 0x00000004
|
||||
|
||||
#define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER
|
||||
#define IOCTL_SCSI_MINIPORT CTL_CODE(IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) //0x0004D008 see NTDDSCSI.H for definition
|
||||
#define IOCTL_SCSI_RESCAN_BUS CTL_CODE(IOCTL_SCSI_BASE, 0x0407, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_SCSI_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
|
||||
#define ARCMSR_IOCTL_READ_RQBUFFER 0x90002004
|
||||
#define ARCMSR_IOCTL_WRITE_WQBUFFER 0x90002008
|
||||
#define ARCMSR_IOCTL_CLEAR_RQBUFFER 0x9000200C
|
||||
#define ARCMSR_IOCTL_CLEAR_WQBUFFER 0x90002010
|
||||
#define ARCMSR_IOCTL_CLEAR_ALLQBUFFER 0x90002014
|
||||
#define ARCMSR_IOCTL_RETURN_CODE_3F 0x90002018
|
||||
#define ARCMSR_IOCTL_SAY_HELLO 0x9000201C
|
||||
|
||||
|
||||
// return code
|
||||
#define SRB_STATUS_SUCCESS 0x01
|
||||
#define SRB_STATUS_INVALID_REQUEST 0x06
|
||||
|
||||
|
||||
class ARCLIB_API WinPassIoctlOdinInterface : public ArcInterface
|
||||
{
|
||||
friend class CArclibOdin;
|
||||
|
||||
public:
|
||||
WinPassIoctlOdinInterface();
|
||||
~WinPassIoctlOdinInterface();
|
||||
bool init(const int nScsiPort);
|
||||
int send(sIF_CMD_BLOCK *ifData);
|
||||
int recv(sIF_CMD_BLOCK *ifData);
|
||||
int syncSend(sIF_CMD_BLOCK *ifData);
|
||||
int getMTU();
|
||||
void *getDeviceHandle();
|
||||
void requirelock();
|
||||
void releaselock();
|
||||
|
||||
private:
|
||||
BOOL ClearReadBuffer();
|
||||
BOOL ClearWriteBuffer();
|
||||
BOOL ClearReadWriteBuffer();
|
||||
HANDLE m_hScsi;
|
||||
HANDLE m_hSyncIm;
|
||||
PSECURITY_DESCRIPTOR pSD;
|
||||
};
|
||||
|
||||
//
|
||||
// SCSI CDB operation codes
|
||||
//
|
||||
|
||||
#define SCSIOP_TEST_UNIT_READY 0x00
|
||||
#define SCSIOP_REZERO_UNIT 0x01
|
||||
#define SCSIOP_REWIND 0x01
|
||||
#define SCSIOP_REQUEST_BLOCK_ADDR 0x02
|
||||
#define SCSIOP_REQUEST_SENSE 0x03
|
||||
#define SCSIOP_FORMAT_UNIT 0x04
|
||||
#define SCSIOP_READ_BLOCK_LIMITS 0x05
|
||||
#define SCSIOP_REASSIGN_BLOCKS 0x07
|
||||
#define SCSIOP_READ6 0x08
|
||||
#define SCSIOP_RECEIVE 0x08
|
||||
#define SCSIOP_WRITE6 0x0A
|
||||
#define SCSIOP_PRINT 0x0A
|
||||
#define SCSIOP_SEND 0x0A
|
||||
#define SCSIOP_SEEK6 0x0B
|
||||
#define SCSIOP_TRACK_SELECT 0x0B
|
||||
#define SCSIOP_SLEW_PRINT 0x0B
|
||||
#define SCSIOP_SEEK_BLOCK 0x0C
|
||||
#define SCSIOP_PARTITION 0x0D
|
||||
#define SCSIOP_READ_REVERSE 0x0F
|
||||
#define SCSIOP_WRITE_FILEMARKS 0x10
|
||||
#define SCSIOP_FLUSH_BUFFER 0x10
|
||||
#define SCSIOP_SPACE 0x11
|
||||
#define SCSIOP_INQUIRY 0x12
|
||||
#define SCSIOP_VERIFY6 0x13
|
||||
#define SCSIOP_RECOVER_BUF_DATA 0x14
|
||||
#define SCSIOP_MODE_SELECT 0x15
|
||||
#define SCSIOP_RESERVE_UNIT 0x16
|
||||
#define SCSIOP_RELEASE_UNIT 0x17
|
||||
#define SCSIOP_COPY 0x18
|
||||
#define SCSIOP_ERASE 0x19
|
||||
#define SCSIOP_MODE_SENSE 0x1A
|
||||
#define SCSIOP_START_STOP_UNIT 0x1B
|
||||
#define SCSIOP_STOP_PRINT 0x1B
|
||||
#define SCSIOP_LOAD_UNLOAD 0x1B
|
||||
#define SCSIOP_RECEIVE_DIAGNOSTIC 0x1C
|
||||
#define SCSIOP_SEND_DIAGNOSTIC 0x1D
|
||||
#define SCSIOP_MEDIUM_REMOVAL 0x1E
|
||||
#define SCSIOP_READ_CAPACITY 0x25
|
||||
#define SCSIOP_READ 0x28
|
||||
#define SCSIOP_WRITE 0x2A
|
||||
#define SCSIOP_SEEK 0x2B
|
||||
#define SCSIOP_LOCATE 0x2B
|
||||
#define SCSIOP_WRITE_VERIFY 0x2E
|
||||
#define SCSIOP_VERIFY 0x2F
|
||||
#define SCSIOP_SEARCH_DATA_HIGH 0x30
|
||||
#define SCSIOP_SEARCH_DATA_EQUAL 0x31
|
||||
#define SCSIOP_SEARCH_DATA_LOW 0x32
|
||||
#define SCSIOP_SET_LIMITS 0x33
|
||||
#define SCSIOP_READ_POSITION 0x34
|
||||
#define SCSIOP_SYNCHRONIZE_CACHE 0x35
|
||||
#define SCSIOP_COMPARE 0x39
|
||||
#define SCSIOP_COPY_COMPARE 0x3A
|
||||
#define SCSIOP_WRITE_DATA_BUFF 0x3B
|
||||
#define SCSIOP_READ_DATA_BUFF 0x3C
|
||||
#define SCSIOP_CHANGE_DEFINITION 0x40
|
||||
#define SCSIOP_READ_SUB_CHANNEL 0x42
|
||||
#define SCSIOP_READ_TOC 0x43
|
||||
#define SCSIOP_READ_HEADER 0x44
|
||||
#define SCSIOP_PLAY_AUDIO 0x45
|
||||
#define SCSIOP_PLAY_AUDIO_MSF 0x47
|
||||
#define SCSIOP_PLAY_TRACK_INDEX 0x48
|
||||
#define SCSIOP_PLAY_TRACK_RELATIVE 0x49
|
||||
#define SCSIOP_PAUSE_RESUME 0x4B
|
||||
#define SCSIOP_LOG_SELECT 0x4C
|
||||
#define SCSIOP_LOG_SENSE 0x4D
|
||||
|
||||
#endif
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
#ifndef _WINSCSI_H_
|
||||
#define _WINSCSI_H_
|
||||
|
||||
#include "commdef.h"
|
||||
#include "interface.h"
|
||||
#include "arclib.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <tchar.h>
|
||||
#include <wtypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define MAX_SCSI_DEV 10
|
||||
#define MAX_SCSI_CH 2
|
||||
#define MAX_SCSI_TARGETID 127 // older value is 15, modify for SAS, upgrade to 127, 2008/03/11
|
||||
#define MAX_SCSI_LUN 7
|
||||
|
||||
//
|
||||
// SCSI CDB operation codes
|
||||
//
|
||||
|
||||
#define SCSIOP_TEST_UNIT_READY 0x00
|
||||
#define SCSIOP_REZERO_UNIT 0x01
|
||||
#define SCSIOP_REWIND 0x01
|
||||
#define SCSIOP_REQUEST_BLOCK_ADDR 0x02
|
||||
#define SCSIOP_REQUEST_SENSE 0x03
|
||||
#define SCSIOP_FORMAT_UNIT 0x04
|
||||
#define SCSIOP_READ_BLOCK_LIMITS 0x05
|
||||
#define SCSIOP_REASSIGN_BLOCKS 0x07
|
||||
#define SCSIOP_READ6 0x08
|
||||
#define SCSIOP_RECEIVE 0x08
|
||||
#define SCSIOP_WRITE6 0x0A
|
||||
#define SCSIOP_PRINT 0x0A
|
||||
#define SCSIOP_SEND 0x0A
|
||||
#define SCSIOP_SEEK6 0x0B
|
||||
#define SCSIOP_TRACK_SELECT 0x0B
|
||||
#define SCSIOP_SLEW_PRINT 0x0B
|
||||
#define SCSIOP_SEEK_BLOCK 0x0C
|
||||
#define SCSIOP_PARTITION 0x0D
|
||||
#define SCSIOP_READ_REVERSE 0x0F
|
||||
#define SCSIOP_WRITE_FILEMARKS 0x10
|
||||
#define SCSIOP_FLUSH_BUFFER 0x10
|
||||
#define SCSIOP_SPACE 0x11
|
||||
#define SCSIOP_INQUIRY 0x12
|
||||
#define SCSIOP_VERIFY6 0x13
|
||||
#define SCSIOP_RECOVER_BUF_DATA 0x14
|
||||
#define SCSIOP_MODE_SELECT 0x15
|
||||
#define SCSIOP_RESERVE_UNIT 0x16
|
||||
#define SCSIOP_RELEASE_UNIT 0x17
|
||||
#define SCSIOP_COPY 0x18
|
||||
#define SCSIOP_ERASE 0x19
|
||||
#define SCSIOP_MODE_SENSE 0x1A
|
||||
#define SCSIOP_START_STOP_UNIT 0x1B
|
||||
#define SCSIOP_STOP_PRINT 0x1B
|
||||
#define SCSIOP_LOAD_UNLOAD 0x1B
|
||||
#define SCSIOP_RECEIVE_DIAGNOSTIC 0x1C
|
||||
#define SCSIOP_SEND_DIAGNOSTIC 0x1D
|
||||
#define SCSIOP_MEDIUM_REMOVAL 0x1E
|
||||
#define SCSIOP_READ_CAPACITY 0x25
|
||||
#define SCSIOP_READ 0x28
|
||||
#define SCSIOP_WRITE 0x2A
|
||||
#define SCSIOP_SEEK 0x2B
|
||||
#define SCSIOP_LOCATE 0x2B
|
||||
#define SCSIOP_WRITE_VERIFY 0x2E
|
||||
#define SCSIOP_VERIFY 0x2F
|
||||
#define SCSIOP_SEARCH_DATA_HIGH 0x30
|
||||
#define SCSIOP_SEARCH_DATA_EQUAL 0x31
|
||||
#define SCSIOP_SEARCH_DATA_LOW 0x32
|
||||
#define SCSIOP_SET_LIMITS 0x33
|
||||
#define SCSIOP_READ_POSITION 0x34
|
||||
#define SCSIOP_SYNCHRONIZE_CACHE 0x35
|
||||
#define SCSIOP_COMPARE 0x39
|
||||
#define SCSIOP_COPY_COMPARE 0x3A
|
||||
#define SCSIOP_WRITE_DATA_BUFF 0x3B
|
||||
#define SCSIOP_READ_DATA_BUFF 0x3C
|
||||
#define SCSIOP_CHANGE_DEFINITION 0x40
|
||||
#define SCSIOP_READ_SUB_CHANNEL 0x42
|
||||
#define SCSIOP_READ_TOC 0x43
|
||||
#define SCSIOP_READ_HEADER 0x44
|
||||
#define SCSIOP_PLAY_AUDIO 0x45
|
||||
#define SCSIOP_PLAY_AUDIO_MSF 0x47
|
||||
#define SCSIOP_PLAY_TRACK_INDEX 0x48
|
||||
#define SCSIOP_PLAY_TRACK_RELATIVE 0x49
|
||||
#define SCSIOP_PAUSE_RESUME 0x4B
|
||||
#define SCSIOP_LOG_SELECT 0x4C
|
||||
#define SCSIOP_LOG_SENSE 0x4D
|
||||
|
||||
|
||||
class ARCLIB_API WinScsiInterface : public ArcInterface
|
||||
{
|
||||
friend class CArclib;
|
||||
public:
|
||||
WinScsiInterface();
|
||||
~WinScsiInterface();
|
||||
bool init_physical_drive(const int pd);
|
||||
bool init(const int scsi,const int ch = 0, const int id = 0, const int lun = 0);
|
||||
int send(sIF_CMD_BLOCK *ifData);
|
||||
int recv(sIF_CMD_BLOCK *ifData);
|
||||
int syncSend(sIF_CMD_BLOCK *ifData);
|
||||
int getMTU();
|
||||
void *getDeviceHandle();
|
||||
|
||||
private:
|
||||
HANDLE m_hScsi;
|
||||
unsigned int nAddress;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,595 @@
|
||||
#include "BaseSocket.h"
|
||||
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#define SOCKET_NOT_VALID -1
|
||||
#define MAX_SEND_RETRY_COUNT 10 // Socket send 실패시 최대 재전송 시도 횟수.
|
||||
|
||||
|
||||
/// @brief 생성자.
|
||||
/// @param socket [in] 처리할 socket descriptor
|
||||
CBaseSocket::CBaseSocket( const int& socket )
|
||||
: m_sock( socket )
|
||||
{
|
||||
if( m_sock < 0 )
|
||||
{
|
||||
m_sock = SOCKET_NOT_VALID;
|
||||
m_bConnected = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bConnected = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 소멸자
|
||||
CBaseSocket::~CBaseSocket()
|
||||
{
|
||||
// 소멸자 Socket 명시적 Close 처리.
|
||||
Close();
|
||||
}
|
||||
|
||||
/// @brief 소켓의 Close 처리를 수행함.
|
||||
void CBaseSocket::Close()
|
||||
{
|
||||
m_bConnected = false;
|
||||
|
||||
if( m_sock != SOCKET_NOT_VALID )
|
||||
{
|
||||
close( m_sock );
|
||||
m_sock = SOCKET_NOT_VALID;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 전달받은 Target 으로 Socket 접속을 수행
|
||||
/// @param szTarget [in] 접속 대상 Host name 또는 IP
|
||||
/// @param nPort [in] 접속 Port
|
||||
/// @return 접속 성공시 true, 실패시 false 반환. ( 오류 내역은 로깅처리됨.)
|
||||
bool CBaseSocket::Connect( const std::string& szTarget, int nPort )
|
||||
{
|
||||
// 기존 접속을 Close 처리
|
||||
Close();
|
||||
|
||||
unsigned int nHost = ConversionAddr( szTarget.c_str() );
|
||||
if( nHost == INADDR_NONE )
|
||||
{
|
||||
LOG( LERR, "target host name resolve fail. [%s]->INADDR_NONE", szTarget.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sockaddr_in stTargetAddr;
|
||||
|
||||
m_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if( m_sock == -1 )
|
||||
{
|
||||
int errorNum = errno;
|
||||
|
||||
LOG( LERR, "socket create failed.[%d][%s] Target:[%s]", errorNum, strerror(errorNum), szTarget.c_str() );
|
||||
|
||||
m_sock = SOCKET_NOT_VALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
stTargetAddr.sin_family = AF_INET;
|
||||
stTargetAddr.sin_addr.s_addr = nHost;
|
||||
stTargetAddr.sin_port = htons( nPort );
|
||||
|
||||
// NEW 2012-05-18 huibong
|
||||
// Connnection 종료시 많은 TIME_WAIT 상태 발생으로 인해 .. 이를 제거하기 위해 SO_LINGER 옵션을 설정처리한다.
|
||||
struct linger opt_linger;
|
||||
opt_linger.l_onoff = 1; /* LINGER ON */
|
||||
|
||||
// CHG 2014-05-27 huibong
|
||||
// 아래와 같이 No Wait 로 처리할 경우... Server 역활 수행 중 Close 신호를 받지 못하는 경우가 발생 가능함.
|
||||
// 따라서 5 sec 정도 대기하도록 수정 처리한다.
|
||||
//opt_linger.l_linger = 0; /* No Wait => 0 for abortive disconnect */
|
||||
opt_linger.l_linger = 5; // 5 sec 대기
|
||||
|
||||
int result = setsockopt( m_sock, SOL_SOCKET, SO_LINGER, &opt_linger, sizeof(opt_linger));
|
||||
if( result != 0 )
|
||||
{
|
||||
int errorNum = errno;
|
||||
LOG( LERR, "setsockopt func SO_LINGER set fail.[%d][%s]", errorNum, strerror(errorNum));
|
||||
|
||||
}
|
||||
|
||||
/* Send Timeout 설정. */
|
||||
struct timeval tv_timeo = { 5, 0 };
|
||||
|
||||
result = setsockopt( m_sock, SOL_SOCKET, SO_SNDTIMEO, &tv_timeo, sizeof(tv_timeo));
|
||||
if( result != 0 )
|
||||
{
|
||||
int errorNum = errno;
|
||||
LOG( LERR, "setsockopt func SO_SNDTIMEO set fail.[%d][%s]", errorNum, strerror(errorNum));
|
||||
|
||||
}
|
||||
|
||||
if(connect(m_sock, (struct sockaddr *)&stTargetAddr, sizeof(stTargetAddr)) < 0 )
|
||||
{
|
||||
int errorNum = errno;
|
||||
LOG( LERR, "connect fail.[%s][%d] [%d][%s]", szTarget.c_str(), nPort, errorNum, strerror( errorNum ) );
|
||||
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bConnected = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @brief 멤버 변수인 m_sock 이 유효하고 연결된 상태인 경우 true 반환.
|
||||
/// @return socket이 유효하지 않거나 연결이 끊어지 경우 false 반환, 그외에는 true 반환.
|
||||
bool CBaseSocket::IsValidSocket()
|
||||
{
|
||||
if( m_sock != SOCKET_NOT_VALID && m_bConnected == true )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @brief m_sock 으로부터 지정된 size 만큼 데이터 read 를 시도 ( read 함수와 동일 )
|
||||
/// @param vptr [out] Read 된 데이터를 저장하기 위한 변수에 대한 포인터.
|
||||
/// @param size [in] read 하고자 하는 데이터의 크기.
|
||||
/// @return read 된 데이터의 크기. 0: fd closed, -1: 오류
|
||||
ssize_t CBaseSocket::Read( void * vptr, size_t size )
|
||||
{
|
||||
if( IsValidSocket() == false )
|
||||
return 0;
|
||||
|
||||
ssize_t nRead = 0;
|
||||
while( (nRead = read( m_sock, vptr, size )) < 0 )
|
||||
{
|
||||
int errorNum = errno;
|
||||
if( errorNum == EINTR || errorNum == EAGAIN || errorNum == EWOULDBLOCK )
|
||||
{
|
||||
nRead = 0;
|
||||
continue;
|
||||
}
|
||||
else if( errorNum == ECONNRESET || errorNum == EPIPE )
|
||||
{
|
||||
// 2010-07-23 BUG huibong 잘못된 대입연산자를 비교연산자로 수정.
|
||||
// 2015-08-28 CHG huibong EPIPE(32) 오류 발생시.. 연결 종료로 처리되도록 수정
|
||||
m_bConnected = false;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG( LERR, "read func fail.[%d][%s]", errorNum, strerror(errorNum) );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return nRead;
|
||||
}
|
||||
|
||||
/// @brief m_sock 로부터 지정된 size 만큼 read 를 시도, \n
|
||||
///< 만약 지정된 크기만큼 데이터가 존재하지 않을 경우 해당 크기만큼 데이터를 read 할때까지 대기.
|
||||
/// @param vptr [out] Read 된 데이터를 저장하기 위한 변수에 대한 포인터.
|
||||
/// @param size [in] read 하고자 하는 데이터의 크기.
|
||||
/// @return read 된 데이터의 크기. 0: fd closed, -1: 오류
|
||||
ssize_t CBaseSocket::ReadN( void * vptr, size_t size )
|
||||
{
|
||||
if( IsValidSocket() == false )
|
||||
return 0;
|
||||
|
||||
ssize_t nRead = 0;
|
||||
size_t nLeft = size;
|
||||
char * ptr = (char *)vptr;
|
||||
|
||||
while( nLeft > 0 )
|
||||
{
|
||||
if( (nRead = read( m_sock, ptr, nLeft )) < 0 )
|
||||
{
|
||||
int errorNum = errno;
|
||||
if( errorNum == EINTR || errorNum == EAGAIN || errorNum == EWOULDBLOCK )
|
||||
{
|
||||
nRead = 0;
|
||||
continue;
|
||||
}
|
||||
else if( errorNum == ECONNRESET || errorNum == EPIPE )
|
||||
{
|
||||
// 2015-08-28 CHG huibong EPIPE(32) 오류 발생시.. 연결 종료로 처리되도록 수정
|
||||
m_bConnected = false;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG( LERR, "read func fail.[%d][%s]", errorNum, strerror(errorNum) );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if( nRead == 0 )
|
||||
{
|
||||
m_bConnected = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
nLeft -= nRead;
|
||||
ptr += nRead;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/// @brief m_sock 로부터 지정된 size 만큼 read 를 시도, \n
|
||||
///< 만약 지정된 크기만큼 데이터가 존재하지 않을 경우 해당 크기만큼 데이터를 read 할때까지 대기. \n
|
||||
///< 또는 지정된 Timeout 값 동안 read 를 하지 못하는 경우 오류 처리.
|
||||
/// @param vptr [out] Read 된 데이터를 저장하기 위한 변수에 대한 포인터.
|
||||
/// @param size [in] read 하고자 하는 데이터의 크기.
|
||||
/// @param timeout [in] Timeout value (sec)
|
||||
/// @return read 된 데이터의 크기. 0: fd closed, -1: 오류 , -2: Timeout
|
||||
ssize_t CBaseSocket::ReadNTimeout( void * vptr, size_t size, int timeout )
|
||||
{
|
||||
if( IsValidSocket() == false )
|
||||
return 0;
|
||||
|
||||
ssize_t nRead = 0;
|
||||
size_t nLeft = size;
|
||||
char * ptr = (char *)vptr;
|
||||
|
||||
struct timeval timeOver;
|
||||
int result;
|
||||
|
||||
fd_set selectFds;
|
||||
FD_ZERO( &selectFds );
|
||||
|
||||
while( nLeft > 0 )
|
||||
{
|
||||
timeOver.tv_sec = timeout;
|
||||
timeOver.tv_usec = 0;
|
||||
FD_SET( m_sock, &selectFds );
|
||||
|
||||
result = select( m_sock+1, &selectFds, (fd_set *)NULL, (fd_set *)NULL, &timeOver );
|
||||
|
||||
if( result > 0 )
|
||||
{
|
||||
if( FD_ISSET( m_sock, &selectFds ))
|
||||
{
|
||||
if( (nRead = read( m_sock, ptr, nLeft) ) < 0 )
|
||||
{
|
||||
int errorNum = errno;
|
||||
if(errorNum == EINTR || errorNum == EAGAIN || errorNum == EWOULDBLOCK)
|
||||
{
|
||||
nRead = 0;
|
||||
continue;
|
||||
}
|
||||
else if( errorNum == ECONNRESET || errorNum == EPIPE )
|
||||
{
|
||||
// 2015-08-28 CHG huibong EPIPE(32) 오류 발생시.. 연결 종료로 처리되도록 수정
|
||||
m_bConnected = false;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG( LERR, "read func fail.[%d][%s]", errorNum, strerror(errorNum) );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if( nRead == 0 )
|
||||
{
|
||||
m_bConnected = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
nLeft -= nRead;
|
||||
ptr += nRead;
|
||||
}
|
||||
|
||||
}
|
||||
else if( result == 0 ) // Timeout
|
||||
{
|
||||
//LOG( LDBG, "read timeout");
|
||||
return -2;
|
||||
}
|
||||
else
|
||||
{
|
||||
int errorNum = errno;
|
||||
LOG( LERR, "select func error.[%d][%s]", errorNum, strerror(errorNum) );
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/// @brief m_sock 로부터 지정된 size 만큼 read 를 시도, \n
|
||||
///< 만약 지정된 크기만큼 데이터가 존재하지 않을 경우 해당 크기만큼 데이터를 read 할때까지 대기. \n
|
||||
///< 또는 지정된 Timeout 값 동안 read 를 하지 못하는 경우 오류 처리.
|
||||
///< 본 함수는 Socket 상에 이미 Data 가 존재하는 경우에만 사용.
|
||||
/// @param vptr [out] Read 된 데이터를 저장하기 위한 변수에 대한 포인터.
|
||||
/// @param size [in] read 하고자 하는 데이터의 크기.
|
||||
/// @param timeout [in] Timeout value (sec)
|
||||
/// @return read 된 데이터의 크기. 0: fd closed, -1: 오류, -2: Timeout
|
||||
ssize_t CBaseSocket::ReadNTimeout2( void * vptr, size_t size, int timeout )
|
||||
{
|
||||
if( IsValidSocket() == false )
|
||||
return 0;
|
||||
|
||||
ssize_t nRead = 0;
|
||||
size_t nLeft = size;
|
||||
char * ptr = (char *)vptr;
|
||||
int errorNum;
|
||||
|
||||
// 우선은 읽기 시도.
|
||||
if( (nRead = read( m_sock, ptr, nLeft) ) < 0 )
|
||||
{
|
||||
errorNum = errno;
|
||||
if( errorNum == EINTR || errorNum == EAGAIN || errorNum == EWOULDBLOCK )
|
||||
{
|
||||
nRead = 0;
|
||||
}
|
||||
else if( errorNum == ECONNRESET || errorNum == EPIPE )
|
||||
{
|
||||
// 2015-08-28 CHG huibong EPIPE(32) 오류 발생시.. 연결 종료로 처리되도록 수정
|
||||
|
||||
m_bConnected = false;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG( LERR, "read func fail.[%d][%s]", errorNum, strerror(errorNum) );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if( nRead == 0 )
|
||||
{
|
||||
m_bConnected = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
nLeft -= nRead;
|
||||
ptr += nRead;
|
||||
|
||||
// 만약 더 받을 데이터가 존재한다면.
|
||||
if( nLeft > 0 )
|
||||
{
|
||||
struct timeval timeOver;
|
||||
int result;
|
||||
|
||||
fd_set selectFds;
|
||||
FD_ZERO( &selectFds );
|
||||
|
||||
while( nLeft > 0 )
|
||||
{
|
||||
timeOver.tv_sec = timeout;
|
||||
timeOver.tv_usec = 0;
|
||||
FD_SET( m_sock, &selectFds );
|
||||
|
||||
result = select( m_sock+1, &selectFds, (fd_set *)NULL, (fd_set *)NULL, &timeOver );
|
||||
|
||||
if( result > 0 )
|
||||
{
|
||||
if( FD_ISSET( m_sock, &selectFds ))
|
||||
{
|
||||
if( (nRead = read( m_sock, ptr, nLeft) ) < 0 )
|
||||
{
|
||||
errorNum = errno;
|
||||
if(errorNum == EINTR || errorNum == EAGAIN || errorNum == EWOULDBLOCK)
|
||||
{
|
||||
nRead = 0;
|
||||
continue;
|
||||
}
|
||||
else if( errorNum == ECONNRESET || errorNum == EPIPE )
|
||||
{
|
||||
// 2015-08-28 CHG huibong EPIPE(32) 오류 발생시.. 연결 종료로 처리되도록 수정
|
||||
m_bConnected = false;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG( LERR, "read func fail.[%d][%s]", errorNum, strerror(errorNum) );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if( nRead == 0 )
|
||||
{
|
||||
m_bConnected = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
nLeft -= nRead;
|
||||
ptr += nRead;
|
||||
}
|
||||
}
|
||||
else if( result == 0 ) // Timeout
|
||||
{
|
||||
//LOG( LDBG, "read timeout");
|
||||
return -2;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorNum = errno;
|
||||
LOG( LERR, "select func error.[%d][%s]", errorNum, strerror(errorNum) );
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/// @brief m_sock 으로 지정된 크기만큼 vptr 의 데이터를 전송 시도.\n
|
||||
///< Send Timeout 옵션 설정으로 Write Timeout 설정 가능. \n
|
||||
///< 지정된 횟수만큼 재전송 실패시 오류로 처리함.
|
||||
/// @param vptr [in] 전달할 데이터를 저장한 변수에 대한 포인터.
|
||||
/// @param size [in] write 하고자 하는 데이터의 크기.
|
||||
/// @return write 된 데이터의 크기. 0: fd closed, -1: 오류
|
||||
ssize_t CBaseSocket::WriteN( const void * vptr, size_t size )
|
||||
{
|
||||
if( IsValidSocket() == false )
|
||||
return 0;
|
||||
|
||||
size_t nLeft;
|
||||
ssize_t nWrite;
|
||||
|
||||
const char * ptr = (const char *)vptr;
|
||||
nLeft = size;
|
||||
|
||||
int nTryCount = 0;
|
||||
|
||||
while( nLeft > 0 )
|
||||
{
|
||||
if( (nWrite = send( m_sock, ptr, nLeft, 0 )) < 0 )
|
||||
{
|
||||
int errorNum = errno;
|
||||
|
||||
if( errorNum == EINTR || errorNum == EAGAIN || errorNum == EWOULDBLOCK )
|
||||
{
|
||||
nWrite = 0;
|
||||
++nTryCount;
|
||||
}
|
||||
else if( errorNum == ECONNRESET || errorNum == EPIPE )
|
||||
{
|
||||
// 2015-08-28 CHG huibong EPIPE(32) 오류 발생시.. 연결 종료로 처리되도록 수정
|
||||
m_bConnected = false;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG( LERR, "send func fail.[%d][%s]", errorNum, strerror(errorNum));
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if( nWrite == 0 )
|
||||
{
|
||||
m_bConnected = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( nTryCount > MAX_SEND_RETRY_COUNT )
|
||||
{
|
||||
LOG( LERR, "send func failure due to exceeding count of retry[%d/%d]", nTryCount, MAX_SEND_RETRY_COUNT );
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
nLeft -= nWrite;
|
||||
ptr += nWrite;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
// CHG 2011-05-03 huibong
|
||||
// gethostbyname() 함수가 Thread Safe 하지 않기 때문에
|
||||
// DNS resolve 처리시 잘못된 정보를 반환할 가능성이 존재
|
||||
// 이에 따라 본 함수를 수정처리함.
|
||||
/*
|
||||
unsigned int CBaseSocket::ConversionAddr( const char * name )
|
||||
{
|
||||
struct hostent *he;
|
||||
int max;
|
||||
unsigned int retval;
|
||||
|
||||
if ((retval = inet_addr(name)) != INADDR_NONE)
|
||||
return retval;
|
||||
|
||||
he = gethostbyname(name);
|
||||
if (he == NULL)
|
||||
return INADDR_NONE;
|
||||
|
||||
for (max = 0; he->h_addr_list[max]; max++) ;
|
||||
if (max == 1)
|
||||
return *((unsigned int *)(he->h_addr_list[0]));
|
||||
else
|
||||
return *((unsigned int *)(he->h_addr_list[random() % max]));
|
||||
}
|
||||
*/
|
||||
|
||||
unsigned int CBaseSocket::ConversionAddr( const char * name )
|
||||
{
|
||||
unsigned int retval;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result = NULL;
|
||||
int error;
|
||||
|
||||
|
||||
// 전달받은 정보가 IP 주소인 경우...
|
||||
// - DNS resolve 할 필요 없이 변환시킨 값을 그대로 사용한다.
|
||||
if( (retval = inet_addr(name)) != INADDR_NONE )
|
||||
return retval;
|
||||
|
||||
// getaddrinfo() 함수 호출을 위한 Hint 설정
|
||||
memset( &hints, 0x00, sizeof(hints));
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
// Thread Safe 한 DNS Resolve 처리함수 호출
|
||||
// int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res);
|
||||
|
||||
// CHG 2014-11-14 huibong
|
||||
// getaddrinfo 호출시 종종 EAI_NONAME 오류가 반환됨. (#20783)
|
||||
// - 따라서 오류 반환시 재시도하도록 기능 추가
|
||||
// CHG 2015-07-15 huibong
|
||||
// usleep 의 multi thread 상에서 block 발생 가능
|
||||
// - nanosleep 을 사용토록 변경 처리
|
||||
for( int count = 0 ; count < 3; count++ )
|
||||
{
|
||||
error = getaddrinfo( name, NULL, &hints, &result );
|
||||
|
||||
// 오류 발생시
|
||||
if( error != 0 )
|
||||
{
|
||||
if( result != NULL)
|
||||
{
|
||||
freeaddrinfo(result);
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
// 잠시 대기 후 재시도 처리
|
||||
struct timespec sleep;
|
||||
sleep.tv_sec = 0;
|
||||
sleep.tv_nsec = 500000000; // 0.5 sec
|
||||
nanosleep( &sleep, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
// 정상 처리된 경우...
|
||||
// - loop 탈출
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 최종 오류 발생시
|
||||
if( error != 0 )
|
||||
{
|
||||
LOG( LERR, "name[%s] dns resolve fail. getaddrinfo return error [%d][%s]", name, error, gai_strerror(error) );
|
||||
return INADDR_NONE;
|
||||
}
|
||||
|
||||
struct sockaddr_in * addr = (struct sockaddr_in *)result->ai_addr;
|
||||
retval = (unsigned int)(addr->sin_addr.s_addr);
|
||||
|
||||
// DNS Resovle 결과 확인용 코드
|
||||
/*
|
||||
struct addrinfo *temp;
|
||||
for( temp = result; temp; temp = temp->ai_next )
|
||||
{
|
||||
addr = (struct sockaddr_in *)temp->ai_addr;
|
||||
printf ("getaddrinfo result = %s\n",inet_ntoa( addr->sin_addr));
|
||||
}
|
||||
*/
|
||||
|
||||
// getaddrinfo() 함수에서 생성한 메모리 영역 해제 처리.
|
||||
freeaddrinfo(result);
|
||||
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/***************************************************************************
|
||||
BaseSocket ( Base Socket Class )
|
||||
-----------------------------------------
|
||||
begin : 2010/03/02
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __LIBRARY_BASE_SOCKET_H__
|
||||
#define __LIBRARY_BASE_SOCKET_H__
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "Logger.h"
|
||||
|
||||
#define SOCKET_NOT_VALID -1
|
||||
#define DEFAULT_DATA_RECEIVE_TIMEOUT 15 // sec
|
||||
|
||||
|
||||
class CBaseSocket
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief socket descriptor
|
||||
int m_sock;
|
||||
|
||||
/// @brief socket 의 연결상태인지 여부를 저장하기 위한 변수.
|
||||
bool m_bConnected;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/// @brief 생성자.
|
||||
CBaseSocket( const int & socket );
|
||||
|
||||
/// @brief 소멸자.
|
||||
~CBaseSocket();
|
||||
|
||||
/// @brief 소켓의 Close 처리를 수행함.
|
||||
void Close(void);
|
||||
|
||||
/// @brief 전달받은 Target 으로 Socket 접속을 수행
|
||||
/// @param szTarget [in] 접속 대상 Host name 또는 IP
|
||||
/// @param nPort [in] 접속 Port
|
||||
/// @return 접속 성공시 true, 실패시 false 반환. ( 오류 내역은 로깅처리됨.)
|
||||
bool Connect( const std::string& szTarget, int nPort );
|
||||
|
||||
/// @brief 멤버 변수인 m_sock 이 유효하고 연결된 상태인 경우 true 반환.
|
||||
/// @return socket이 유효하지 않거나 연결이 끊어지 경우 false 반환, 그외에는 true 반환.
|
||||
bool IsValidSocket(void);
|
||||
|
||||
/// @brief 멤버변수인 socket 의 접속 상태 여부를 설정하기 위한 함수.
|
||||
void SetConnectionStatus( bool bConnected) { m_bConnected = bConnected; }
|
||||
|
||||
/// @brief 현재 socket 의 접속 상태를 반환.
|
||||
bool GetConnectionStatus( void) { return m_bConnected; }
|
||||
|
||||
//void SetLogger( Logger * pLog ) { m_pLog = pLog; }
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief m_sock 로 부터 지정된 size 만큼 데이터 read 를 시도 ( read 함수와 동일 )
|
||||
/// @param vptr [out] Read 된 데이터를 저장하기 위한 변수에 대한 포인터.
|
||||
/// @param size [in] read 하고자 하는 데이터의 크기.
|
||||
/// @return read 된 데이터의 크기. 0: fd closed, -1: 오류
|
||||
ssize_t Read( void * vptr, size_t size );
|
||||
|
||||
/// @brief m_sock 로부터 지정된 size 만큼 read 를 시도, \n
|
||||
///< 만약 지정된 크기만큼 데이터가 존재하지 않을 경우 해당 크기만큼 데이터를 read 할때까지 대기.
|
||||
/// @param vptr [out] Read 된 데이터를 저장하기 위한 변수에 대한 포인터.
|
||||
/// @param size [in] read 하고자 하는 데이터의 크기.
|
||||
/// @return read 된 데이터의 크기. 0: fd closed, -1: 오류
|
||||
ssize_t ReadN( void * vptr, size_t size );
|
||||
|
||||
/// @brief m_sock 로부터 지정된 size 만큼 read 를 시도, \n
|
||||
///< 만약 지정된 크기만큼 데이터가 존재하지 않을 경우 해당 크기만큼 데이터를 read 할때까지 대기. \n
|
||||
///< 또는 지정된 Timeout 값 동안 read 를 하지 못하는 경우 오류 처리.
|
||||
/// @param vptr [out] Read 된 데이터를 저장하기 위한 변수에 대한 포인터.
|
||||
/// @param size [in] read 하고자 하는 데이터의 크기.
|
||||
/// @param timeout [in] Timeout value (sec)
|
||||
/// @return read 된 데이터의 크기. 0: fd closed, -1: 오류, -2: Timeout
|
||||
ssize_t ReadNTimeout( void * vptr, size_t size, int timeout = DEFAULT_DATA_RECEIVE_TIMEOUT );
|
||||
|
||||
/// @brief m_sock 로부터 지정된 size 만큼 read 를 시도, \n
|
||||
///< 만약 지정된 크기만큼 데이터가 존재하지 않을 경우 해당 크기만큼 데이터를 read 할때까지 대기. \n
|
||||
///< 또는 지정된 Timeout 값 동안 read 를 하지 못하는 경우 오류 처리.
|
||||
///< 본 함수는 Socket 상에 이미 Data 가 존재하는 경우에만 사용.
|
||||
/// @param vptr [out] Read 된 데이터를 저장하기 위한 변수에 대한 포인터.
|
||||
/// @param size [in] read 하고자 하는 데이터의 크기.
|
||||
/// @param timeout [in] Timeout value (sec)
|
||||
/// @return read 된 데이터의 크기. 0: fd closed, -1: 오류, -2: Timeout
|
||||
ssize_t ReadNTimeout2( void * vptr, size_t size, int timeout = DEFAULT_DATA_RECEIVE_TIMEOUT );
|
||||
|
||||
public:
|
||||
/// @brief m_sock 으로 지정된 크기만큼 vptr 의 데이터를 전송 시도.\n
|
||||
///< Send Timeout 옵션 설정으로 Write Timeout 설정 가능. \n
|
||||
///< 지정된 횟수만큼 재전송 실패시 오류로 처리함.
|
||||
/// @param vptr [in] 전달할 데이터를 저장한 변수에 대한 포인터.
|
||||
/// @param size [in] write 하고자 하는 데이터의 크기.
|
||||
/// @return write 된 데이터의 크기. 0: fd closed, -1: 오류
|
||||
ssize_t WriteN( const void * vptr, size_t size );
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief 문자열로 전달받은 정보를 검사하여 IP 접속 정보를 생성한다.
|
||||
unsigned int ConversionAddr( const char * name );
|
||||
|
||||
};
|
||||
|
||||
#endif /* __LIBRARY_BASE_SOCKET_H__ */
|
||||
@@ -0,0 +1,238 @@
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <boost/algorithm/string.hpp> // use boost
|
||||
|
||||
|
||||
Config::Config()
|
||||
: m_keyDelimiter( CONFIG_DEFAULT_KEY_DELIMITER )
|
||||
, m_valueDelimiter( CONFIG_DEFAULT_VALUE_DELIMITER )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// @brief destructor
|
||||
Config::~Config()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
/// @brief 지정된 Config 파일의 모든 정보를 읽어 내부 변수에 저장처리
|
||||
/// @param path [in] Config file 의 전체 경로정보( C 배열 지원을 위해 & 사용안함)
|
||||
/// @return On success return true, otherwise return false
|
||||
bool Config::Open( const string path )
|
||||
{
|
||||
ifstream file;
|
||||
|
||||
// Config file open
|
||||
file.open( path.c_str());
|
||||
if( file.is_open() == false )
|
||||
{
|
||||
cerr << "[error] " << __FILE__<< ":" << __func__ << ": config file open failed.[" << path << "][" << strerror( errno ) << "]" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 기존 데이터가 존재하면 삭제 처리.
|
||||
if( m_configData.empty() == false )
|
||||
m_configData.clear();
|
||||
|
||||
// config file parsing
|
||||
string line;
|
||||
string section;
|
||||
vector< string > configs;
|
||||
|
||||
// 루프를 돌면서 Config 파일을 line 단위로 읽어들인당....
|
||||
while( std::getline( file, line ) )
|
||||
{
|
||||
// 앞뒤 공백 제거 처리
|
||||
boost::trim( line );
|
||||
|
||||
// 공백 or 주석처리 라인 검사
|
||||
if( line.empty() == true || boost::starts_with( line, string("#") ) == true || line == "\r" )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Section 여부 검사
|
||||
if( boost::starts_with( line, string("[") ) == true && boost::ends_with( line, string("]") ) == true )
|
||||
{
|
||||
// [] 로 정의된 section 의 문자열 값 추출
|
||||
line.erase( line.begin() );
|
||||
line.erase( line.end() -1 );
|
||||
boost::trim( line );
|
||||
|
||||
if( section.empty() == false && section != line )
|
||||
{
|
||||
// 이전 세션과 다른 신규 세션인 경우
|
||||
// 기존까지 저장했던 데이터를 멤버 변수에 입력 처리 후 내부변수 초기화 처리.
|
||||
|
||||
m_configData.insert( make_pair( section, configs ) );
|
||||
section.clear();
|
||||
configs.clear();
|
||||
}
|
||||
|
||||
// 신규 section 정보 저장처리.
|
||||
section = line;
|
||||
line.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Section 정보가 아닌 경우 => 실제 설정값 .. ^^
|
||||
configs.push_back( line );
|
||||
}
|
||||
}
|
||||
|
||||
// 마지막 세션 처리된 정보가 존재하는 경우 멤버 변수에 저장 처리.
|
||||
if( section.empty() == false )
|
||||
{
|
||||
m_configData.insert( make_pair( section, configs ) );
|
||||
}
|
||||
|
||||
// 종료 처리.
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Config 멤버 변수에 저장된 데이터 삭제처리.
|
||||
/// @return void
|
||||
void Config::Clear()
|
||||
{
|
||||
m_configData.clear();
|
||||
}
|
||||
|
||||
/// @brief 해당 Section, Key 에 해당하는 value 값을 찾아 반환
|
||||
/// @param section [in] 찾고자 하는 Section 값
|
||||
/// @param key [in] 찾고자 하는 key 값
|
||||
/// @param value [out] 해당 Section, Key 에 해당하는 value 값을 저장하기 위한 변수
|
||||
/// @return On success return true, otherwise return false
|
||||
bool Config::GetConfig( const string& section, const string& key, string& value )
|
||||
{
|
||||
// Section 에 대한 임시 데이터 저장객체 생성
|
||||
vector< string > configs;
|
||||
|
||||
// 해당 Section 이 존재하지 않는 경우
|
||||
if( Find( section, configs ) == false )
|
||||
return false;
|
||||
|
||||
string line;
|
||||
string result;
|
||||
vector< string >::const_iterator it;
|
||||
|
||||
// 해당 Key 이 존재하는지 검사
|
||||
for( it = configs.begin(); it != configs.end(); it++)
|
||||
{
|
||||
line = *it;
|
||||
|
||||
// Line 상의 주석 제거
|
||||
string::size_type pos = line.find( '#' );
|
||||
if( pos != string::npos)
|
||||
{
|
||||
line = line.substr(0, pos);
|
||||
boost::trim( line );
|
||||
}
|
||||
|
||||
// key = value 에서 key 부분 추출
|
||||
pos = line.find( m_keyDelimiter );
|
||||
if( pos == string::npos )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = line.substr(0, pos);
|
||||
boost::trim( result );
|
||||
}
|
||||
|
||||
if( key == result )
|
||||
{
|
||||
// Key 값이 동일한 경우
|
||||
value = line.substr( pos+1 );
|
||||
boost::trim( value );
|
||||
// ${value} : 참조 값 찾기
|
||||
pos = value.find( "${" );
|
||||
if( pos != string::npos )
|
||||
{
|
||||
value = value.substr(pos+2);
|
||||
pos = value.rfind("}");
|
||||
if( pos != string::npos )
|
||||
{
|
||||
value = value.substr(0,pos);
|
||||
pos = value.find( '.' );
|
||||
if( pos != string::npos )
|
||||
{
|
||||
string ss = value.substr(0,pos);
|
||||
string kk = value.substr(pos+1);
|
||||
return GetConfig( ss, kk,value );
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @brief 해당 Section, Key 에 해당하는 value Array 값을 찾아 반환
|
||||
/// @param section [in] 찾고자 하는 Section 값
|
||||
/// @param key [in] 찾고자 하는 key 값
|
||||
/// @param value [out] 해당 Section, Key 에 해당하는 value 값을 저장하기 위한 배열
|
||||
/// @return On success return true, otherwise return false
|
||||
bool Config::GetConfig( const string& section, const string& key, vector< string >& value )
|
||||
{
|
||||
string result;
|
||||
vector< string > vec;
|
||||
|
||||
if( GetConfig( section, key, result ) == false )
|
||||
return false;
|
||||
|
||||
// 전달받은 result 값을 value delimiter 를 이용하여 parsing 처리
|
||||
boost::split( vec, result, boost::is_any_of( m_valueDelimiter ));
|
||||
if( vec.empty() == true )
|
||||
return false;
|
||||
|
||||
// 루프를 돌면서 trim 처리 후 결과값 저장처리.
|
||||
vector< string >::const_iterator it;
|
||||
for( it = vec.begin(); it != vec.end(); it++)
|
||||
{
|
||||
result = boost::trim_copy( *it );
|
||||
|
||||
if( result.empty() == false )
|
||||
value.push_back( result );
|
||||
}
|
||||
|
||||
if( value.empty() == true )
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Config 멤버 변수에 저장된 데이터 중 해당 Section 에 해당하는 데이터 반환.
|
||||
/// @param section [in] section 명
|
||||
/// @param configData [out] 해당 Section 에서 읽은 Cofig 정보를 저장할 string 배열
|
||||
/// @return On success return true, otherwise return false
|
||||
bool Config::Find( const string& section, vector<string>& configData )
|
||||
{
|
||||
map< string, vector< string > >::iterator it = m_configData.find( section );
|
||||
if( it != m_configData.end() )
|
||||
{
|
||||
// 해당 section 을 찾은 경우
|
||||
configData = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 해당 section 을 찾지 못한 경우
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/***************************************************************************
|
||||
Config File Parser Class
|
||||
-----------------------------------------
|
||||
begin : 2010/02/27
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __LIBRARY_CONFIG_H__
|
||||
#define __LIBRARY_CONFIG_H__
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
#define CONFIG_DEFAULT_KEY_DELIMITER "="
|
||||
#define CONFIG_DEFAULT_VALUE_DELIMITER ","
|
||||
|
||||
|
||||
/// @brief Config class
|
||||
/// 1. config 파일의 내용을 파싱처리하여 각 Section, Key 에 해당하는 값을 반환처리
|
||||
/// 2. config 파일은 [section] 단위로 구분된다.
|
||||
/// 3. config 파일은 key=value 로 구분가능하며 이는 Delimiter 설정을 통해 변경가능하다.
|
||||
/// 4. value 값이 다중으로 존재하는 경우 "," 값을 통해 구분가능, Delimiter 변경시 다른 값도 사용가능함.
|
||||
/// 5. config 파일상에서 "#" 로 시작하는 문자열은 라인 끝까지 주석으로 처리된다.
|
||||
/// 6. 특정 Key 값에 대한 다중 value 값 조회는 vector<string> 을 통해 수행한다.
|
||||
/// 7. 만약 다중 value 값이 존재시 string 으로 반환받을 경우 해당 Row 가 통째로 반환된다.
|
||||
/// 8. 본 객체는 Open , Clear 함수가 호출되기전까지 이전 Config 정보가 저장된다.
|
||||
class Config
|
||||
{
|
||||
private:
|
||||
/// @brief config information saved variable
|
||||
// string : section data
|
||||
// vector<string> : key=value data
|
||||
map< string, vector< string> > m_configData;
|
||||
|
||||
/// @brief Key, Value 구분자 저장 변수
|
||||
string m_keyDelimiter;
|
||||
string m_valueDelimiter;
|
||||
|
||||
public:
|
||||
/// @brief constructor
|
||||
Config();
|
||||
|
||||
/// @brief destructor
|
||||
~Config();
|
||||
|
||||
/// @brief 지정된 Config 파일의 모든 정보를 읽어 내부 변수에 저장처리
|
||||
/// @param path [in] Config file 의 전체 경로정보( C 배열 지원을 위해 & 사용안함)
|
||||
/// @return On success return true, otherwise return false
|
||||
bool Open( const string path );
|
||||
|
||||
/// @brief Config 멤버 변수에 저장된 데이터 삭제처리.
|
||||
/// @return void
|
||||
void Clear();
|
||||
|
||||
/// @brief 해당 Section, Key 에 해당하는 value 값을 찾아 반환
|
||||
/// @param section [in] 찾고자 하는 Section 값
|
||||
/// @param key [in] 찾고자 하는 key 값
|
||||
/// @param value [out] 해당 Section, Key 에 해당하는 value 값을 저장하기 위한 변수
|
||||
/// @return On success return true, otherwise return false
|
||||
bool GetConfig( const string& section, const string& key, string& value );
|
||||
|
||||
/// @brief 해당 Section, Key 에 해당하는 value Array 값을 찾아 반환
|
||||
/// @param section [in] 찾고자 하는 Section 값
|
||||
/// @param key [in] 찾고자 하는 key 값
|
||||
/// @param value [out] 해당 Section, Key 에 해당하는 value 값을 저장하기 위한 배열
|
||||
/// @return On success return true, otherwise return false
|
||||
bool GetConfig( const string& section, const string& key, vector< string >& value );
|
||||
|
||||
/// @brief Key, Value Delimiter Get 함수
|
||||
/// @param key [out] key delimiter 값
|
||||
/// @param value [out] value delimiter 값
|
||||
void GetDelimiter( string& key, string& value )
|
||||
{
|
||||
key = m_keyDelimiter;
|
||||
value = m_valueDelimiter;
|
||||
}
|
||||
|
||||
/// @brief Key, Value Delimiter Set 함수
|
||||
/// @param key [out] key delimiter 값
|
||||
/// @param value [out] value delimiter 값, 지정하지 않을 경우 Default 값이 사용됨.
|
||||
void SetDelimiter( string& key, string value = CONFIG_DEFAULT_VALUE_DELIMITER )
|
||||
{
|
||||
m_keyDelimiter = key;
|
||||
m_valueDelimiter = value;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
/// @brief Config 멤버 변수에 저장된 데이터 중 해당 Section 에 해당하는 데이터 반환.
|
||||
/// @param section [in] section 명
|
||||
/// @param configData [out] 해당 Section 에서 읽은 Cofig 정보를 저장할 string 배열
|
||||
/// @return On success return true, otherwise return false
|
||||
bool Find( const string& section, vector<string>& configData );
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* __LIBRARY_CONFIG_H__ */
|
||||
@@ -0,0 +1,487 @@
|
||||
/***************************************************************************
|
||||
Logger.cpp
|
||||
-----------------------------------------
|
||||
begin : 2011/10/26
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
#include "Logger.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <iostream>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_BUFFER_SIZE 2048 // 임시 버퍼 최대 크기
|
||||
#define DEFAULT_LOG_LEVEL LINF
|
||||
|
||||
using namespace std;
|
||||
|
||||
CLogger* CLogger::m_pInstance = NULL;
|
||||
bool CLogger::m_bIsInitialized = false;
|
||||
pthread_mutex_t CLogger::m_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
|
||||
CLogger::CLogger( string programName, string logDir, int logLevel )
|
||||
{
|
||||
m_szProgramName = programName;
|
||||
m_szLogDir = logDir;
|
||||
|
||||
if( IsValidLogLevel( logLevel ) == true )
|
||||
{
|
||||
m_nLogLevel = logLevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nLogLevel = DEFAULT_LOG_LEVEL;
|
||||
}
|
||||
|
||||
MakeLogLevelString();
|
||||
}
|
||||
|
||||
void CLogger::MakeLogLevelString()
|
||||
{
|
||||
m_vectorLogLevelString.push_back( "EMR" );
|
||||
m_vectorLogLevelString.push_back( "ALT" );
|
||||
m_vectorLogLevelString.push_back( "CRT" );
|
||||
m_vectorLogLevelString.push_back( "ERR" );
|
||||
m_vectorLogLevelString.push_back( "WAR" );
|
||||
m_vectorLogLevelString.push_back( "NOT" );
|
||||
m_vectorLogLevelString.push_back( "INF" );
|
||||
m_vectorLogLevelString.push_back( "DBG" );
|
||||
m_vectorLogLevelString.push_back( "DEV" );
|
||||
m_vectorLogLevelString.push_back( "DEV1" );
|
||||
m_vectorLogLevelString.push_back( "DEV2" );
|
||||
}
|
||||
|
||||
CLogger::~CLogger()
|
||||
{
|
||||
m_vectorLogLevelString.clear();
|
||||
}
|
||||
|
||||
bool CLogger::Init( string programName, string logDir, int logLevel )
|
||||
{
|
||||
if( m_bIsInitialized == true )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
pthread_mutex_lock( &m_mutex );
|
||||
|
||||
// 변수 유효성 검사.
|
||||
if( programName.empty() == true || logDir.empty() == true )
|
||||
{
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( IsValidLogLevel( logLevel ) == false )
|
||||
{
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( MakeLogDir( programName, logDir ) == false )
|
||||
{
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( CLogger::m_pInstance != NULL )
|
||||
{
|
||||
delete CLogger::m_pInstance;
|
||||
CLogger::m_pInstance = NULL;
|
||||
}
|
||||
|
||||
CLogger::m_pInstance = new CLogger( programName, logDir, logLevel );
|
||||
m_bIsInitialized = true;
|
||||
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CLogger::IsValidLogLevel( int logLevel )
|
||||
{
|
||||
return ( ( logLevel < 0 || logLevel > MAX_LOG_LEVEL ) ? false : true );
|
||||
}
|
||||
|
||||
bool CLogger::SetLogLevel( int logLevel )
|
||||
{
|
||||
if( IsValidLogLevel( logLevel ) == false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_nLogLevel = logLevel;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CLogger::MakeLogDir( string programName, string logDir )
|
||||
{
|
||||
string path = logDir + "/" + programName;
|
||||
|
||||
struct stat dirStat;
|
||||
|
||||
// 해당 이름을 가진 파일 또는 디렉토리가 존재하고
|
||||
if( lstat( path.c_str(), &dirStat ) == 0 )
|
||||
{
|
||||
// 해당 이름이 디렉토리인 경우
|
||||
if( S_ISDIR( dirStat.st_mode ) == true )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "exist file with the same name as log path(" << path << ")." << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 디렉토리 가 존재하지 않는 경우 디렉토리 생성 시도
|
||||
string cmd = "mkdir -p " + path;
|
||||
system( cmd.c_str() );
|
||||
|
||||
if( IsDirectory( path ) == false )
|
||||
{
|
||||
cerr << "can't make log directory. path=" << path << "." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CLogger::IsDirectory( string path )
|
||||
{
|
||||
struct stat dirStat;
|
||||
|
||||
if( lstat ( path.c_str(), &dirStat ) != 0 )
|
||||
{
|
||||
cerr << "Log path not valid. Check path [" << path << "][" << errno << "][" << strerror(errno) << "]" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 해당 정보가 Directory 가 아닌 경우
|
||||
if( S_ISDIR( dirStat.st_mode ) == false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CLogger::Exit()
|
||||
{
|
||||
if( m_bIsInitialized == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock( &m_mutex );
|
||||
|
||||
if( CLogger::m_pInstance != NULL )
|
||||
{
|
||||
delete CLogger::m_pInstance;
|
||||
CLogger::m_pInstance = NULL;
|
||||
m_bIsInitialized = false;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
}
|
||||
|
||||
CLogger* CLogger::GetInstance()
|
||||
{
|
||||
return CLogger::m_pInstance;
|
||||
}
|
||||
|
||||
string CLogger::GetLogFilename( struct tm &timeNow )
|
||||
{
|
||||
char timeStr[256];
|
||||
snprintf( timeStr, (size_t)256, "%04d%02d%02d.log", timeNow.tm_year+1900, timeNow.tm_mon+1, timeNow.tm_mday);
|
||||
|
||||
// Make File Name
|
||||
string filename = m_szLogDir + "/" + m_szProgramName + "/" + m_szProgramName + "_" + string( timeStr );
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
bool CLogger::Write( int logLevel, const char * fmt, ...)
|
||||
{
|
||||
// 가변 인자 처리
|
||||
va_list args;
|
||||
char buffer[MAX_BUFFER_SIZE];
|
||||
va_start( args, fmt );
|
||||
if( vsnprintf( buffer, MAX_BUFFER_SIZE, fmt, args) < 0 )
|
||||
{
|
||||
va_end( args );
|
||||
return false;
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
return Write( logLevel, PREFIX_DATE, NULL, 0, buffer );
|
||||
}
|
||||
|
||||
bool CLogger::WriteNoPrefix( int logLevel, const char * fmt, ...)
|
||||
{
|
||||
// 가변 인자 처리
|
||||
va_list args;
|
||||
char buffer[MAX_BUFFER_SIZE];
|
||||
va_start( args, fmt );
|
||||
if( vsnprintf( buffer, MAX_BUFFER_SIZE, fmt, args) < 0 )
|
||||
{
|
||||
va_end( args );
|
||||
return false;
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
return Write( logLevel, PREFIX_NONE, NULL, 0, buffer );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// CHG 2012-08-16 huibong
|
||||
// 가변인자를 사용하는 Write 함수 다중 정의로 인해...
|
||||
// Complier 에서 인수 갯수 및 Type 이 동일할 경우 다른 함수를 가르키는 현상이 발견됨.
|
||||
// 이를 해결하기 위해 Write 함수에 대한 다중 정의를 제거토록 함수명을 명확하게 변경처리함.
|
||||
// 함수명 : Write -> WriteWithFunc 으로 변경 처리
|
||||
bool CLogger::WriteWithFunc( int logLevel, const char* filename, const char* funcname, int lineNum, const char * fmt, ...)
|
||||
{
|
||||
if( filename == NULL || funcname == NULL || lineNum < 0 || fmt == NULL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 가변 인자 처리
|
||||
va_list args;
|
||||
char buffer[MAX_BUFFER_SIZE];
|
||||
va_start( args, fmt );
|
||||
if( vsnprintf( buffer, MAX_BUFFER_SIZE, fmt, args) < 0 )
|
||||
{
|
||||
va_end( args );
|
||||
return false;
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
|
||||
char className[255];
|
||||
string funcPrefix = GetClassName( className, filename );
|
||||
funcPrefix += "::" + string( funcname ) + "()";
|
||||
|
||||
return Write( logLevel, PREFIX_FUNCTION, funcPrefix.c_str(), lineNum, buffer );
|
||||
}
|
||||
|
||||
const char* CLogger::GetClassName( char* className, const char* filename )
|
||||
{
|
||||
if( className == NULL )
|
||||
{
|
||||
cout << "[ERROR] The input argument 'className' is NULL." << endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( filename == NULL )
|
||||
{
|
||||
cout << "[ERROR] The input argument 'filename' is NULL." << endl;
|
||||
strcpy( className, "NULL" );
|
||||
return className;
|
||||
}
|
||||
|
||||
int filenameSize = strlen( filename );
|
||||
memcpy( className, filename, filenameSize );
|
||||
|
||||
// find end position
|
||||
char endCharacter = '.';
|
||||
int endPos = filenameSize - 1;
|
||||
for( ; endPos > 0; --endPos )
|
||||
{
|
||||
if( className[endPos] == endCharacter )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( endPos == 0 )
|
||||
{
|
||||
cout << "[ERROR] endPos=0" << endl;
|
||||
strcpy( className, "NULL" );
|
||||
return className;
|
||||
}
|
||||
|
||||
className[endPos] = '\0';
|
||||
|
||||
// find start position
|
||||
char startCharacter = '/';
|
||||
int startPos = endPos - 1;
|
||||
for( ; startPos > 0; --startPos )
|
||||
{
|
||||
if( className[startPos] == startCharacter )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( startPos != 0 )
|
||||
{
|
||||
startPos += 1;
|
||||
}
|
||||
|
||||
return (className + startPos );
|
||||
}
|
||||
|
||||
bool CLogger::Write( int logLevel, int logPrefix, const char* functionName, int lineNum, const char* log )
|
||||
{
|
||||
/// 유효한 로그 레벨이 아니면 로깅하지 않음.
|
||||
if( IsValidLogLevel( logLevel ) == false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Log Level 검사 : 지정된 Level 이상인 경우 로깅하지 않음.
|
||||
if( logLevel > m_nLogLevel )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( log == NULL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get Current Data & Time
|
||||
time_t now = time( NULL );
|
||||
struct tm timeNow;
|
||||
localtime_r( &now, &timeNow );
|
||||
|
||||
string filename = GetLogFilename( timeNow );
|
||||
|
||||
// Log file open
|
||||
FILE* pFile = NULL;
|
||||
pFile = fopen( filename.c_str(), "a+" );
|
||||
|
||||
if( pFile == NULL )
|
||||
{
|
||||
cerr << "Log file open fail.[" << filename.c_str() << "][" << errno << "][" << strerror(errno) << "]" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 시간 정보처리
|
||||
char timeStr[256];
|
||||
snprintf( timeStr, (size_t)256, "[%02d:%02d:%02d]"
|
||||
, timeNow.tm_hour, timeNow.tm_min, timeNow.tm_sec );
|
||||
|
||||
// Log Level 문자열 검색
|
||||
string szLevel = m_vectorLogLevelString[ logLevel ];
|
||||
|
||||
switch( logPrefix )
|
||||
{
|
||||
case PREFIX_DATE:
|
||||
/// 형식 예: [15:47:41] [DBG] sample log message.
|
||||
fprintf( pFile, "%s [%-4s] %s\n", timeStr, szLevel.c_str(), log );
|
||||
break;
|
||||
|
||||
case PREFIX_FUNCTION:
|
||||
if( functionName == NULL )
|
||||
{
|
||||
fclose( pFile );
|
||||
return false;
|
||||
}
|
||||
/// 형식 예: [15:47:41] [DBG] sample log message. [SomeClass::SomeFunction():12]
|
||||
fprintf( pFile, "%s [%-4s] %s [%s:%d]\n", timeStr, szLevel.c_str(), log, functionName, lineNum );
|
||||
break;
|
||||
|
||||
case PREFIX_NONE:
|
||||
/// 형식 예: sample log message.
|
||||
fprintf( pFile, "%s\n", log );
|
||||
break;
|
||||
}
|
||||
// Write to log file
|
||||
fflush( pFile );
|
||||
|
||||
// 종료 처리.
|
||||
fclose( pFile );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CLogger::WriteHex( int logLevel, const unsigned char* data, const int size )
|
||||
{
|
||||
/// 유효한 로그 레벨이 아니면 로깅하지 않음.
|
||||
if( IsValidLogLevel( logLevel ) == false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Log Level 검사 : 지정된 Level 이상인 경우 로깅하지 않음.
|
||||
if( logLevel > m_nLogLevel )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( data == NULL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( size <= 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get Current Data & Time
|
||||
time_t now = time( NULL );
|
||||
struct tm timeNow;
|
||||
localtime_r( &now, &timeNow );
|
||||
|
||||
string filename = GetLogFilename( timeNow );
|
||||
|
||||
// Log file open
|
||||
FILE* pFile = NULL;
|
||||
pFile = fopen( filename.c_str(), "a+" );
|
||||
|
||||
if( pFile == NULL )
|
||||
{
|
||||
cerr << "Log file open fail.[" << filename.c_str() << "][" << errno << "][" << strerror(errno) << "]" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
for( int i = 0; i < size; ++i )
|
||||
{
|
||||
fprintf( pFile, "%02X", data[i] );
|
||||
|
||||
if( i == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( ( (i+1) % 8 ) == 0 )
|
||||
{
|
||||
fprintf( pFile, " " );
|
||||
}
|
||||
|
||||
if( ( (i+1) % 16 ) == 0 )
|
||||
{
|
||||
fprintf( pFile, " " );
|
||||
}
|
||||
|
||||
if( ( (i+1) % 32 ) == 0 )
|
||||
{
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
}
|
||||
fprintf( pFile, "\n" );
|
||||
fflush( pFile );
|
||||
|
||||
// 종료 처리.
|
||||
fclose( pFile );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
/***************************************************************************
|
||||
Logger.h
|
||||
-----------------------------------------
|
||||
begin : 2011/10/26
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 3.2.0.805
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
#ifndef __LOGGER_H__
|
||||
#define __LOGGER_H__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <pthread.h>
|
||||
|
||||
///@brief 로그 레벨 정의
|
||||
#define LEMR 0 /* system is or will be unusable if situation is not resolved */
|
||||
#define LALT 1 /* immediate action required */
|
||||
#define LCRT 2 /* critical situations */
|
||||
#define LERR 3 /* error conditions */
|
||||
#define LWAR 4 /* recoverable errors */
|
||||
#define LNOT 5 /* unusual situation that merits investigation */
|
||||
#define LINF 6 /* information messages */
|
||||
#define LDBG 7 /* verbose data for debugging */
|
||||
#define LDEV 8 /* verbose data for developer */
|
||||
#define LDEV1 9 /* start or end the function of application level */
|
||||
#define LDEV2 10 /* start or end the function of application level */
|
||||
|
||||
#define MAX_LOG_LEVEL LDEV2
|
||||
|
||||
|
||||
///@brief Log 정보를 파일로 저장하기 위한 Class.
|
||||
///1. 가변 format 으로 전달된 로그 관련 정보를 Log Level 에 따라 로그 파일에 아래의 4가지 형식으로 저장한다.
|
||||
///
|
||||
/// 1.1 Prefix로 [hh:mm:ss]와 [ClassName::FunctionName]이 추가된 로그
|
||||
/// LOG( level, format, ... ) 매크로 사용.
|
||||
/// 예) [17:43:40] [DBG] log level debug [LoggerTestTestLogger]
|
||||
///
|
||||
/// 1.2 Prefix로 [hh:mm:ss]이 추가된 로그
|
||||
/// _LOG( level, format, ... ) 매크로 사용
|
||||
/// 예) [17:43:40] [EMR] log level emergency
|
||||
///
|
||||
/// 1.3 Prefix가 없는 로그
|
||||
/// _LOG_( level, format, ... ) 매크로 사용
|
||||
/// 예) log level emergency
|
||||
///
|
||||
/// 1.4 Hex 로그.
|
||||
/// LOG_HEX( level, data, size ) 매크로 사용
|
||||
/// 예) 00010203 04050607 08090A0B 0C0D0E0F
|
||||
///
|
||||
///2. Logger 객체 초기화시 전달된 Log Level 정보보다 전달받은 Log Level 정보가 큰 경우 해당 로그는 파일로 저장되지 않는다.
|
||||
///
|
||||
///3. 로그 파일은 매 일단위로 저장파일이 변경된다.
|
||||
///
|
||||
///4. 로그 저장을 위한 program 경로가 존재하지 않는 경우 자동 생성 처리된다.
|
||||
///
|
||||
///5. 로그 저장방식은 매 저장로그마다 open-close 로 처리된다.
|
||||
///
|
||||
///6. 파일로 기록시 Log Level 에 대한 정보도 함께 기록된다.
|
||||
///
|
||||
///7. 싱글톤으로 작성되었고, CLogger::Init(...)시에 쓰레드 안정성을 제공한다.
|
||||
///
|
||||
///8. 동적으로 로그 레벨을 변경할 수 있는 인터페이스를 제공한다.
|
||||
///
|
||||
class CLogger
|
||||
{
|
||||
// Attributes
|
||||
private:
|
||||
///@brief 싱글톤 객체 인트턴스.
|
||||
static CLogger* m_pInstance;
|
||||
|
||||
///@brief 싱글톤 객체 초기화 여부.
|
||||
static bool m_bIsInitialized;
|
||||
|
||||
///@brief 싱글톤 객체 초기화시 스레드 안정성을 위한 뮤텍스.
|
||||
static pthread_mutex_t m_mutex;
|
||||
|
||||
///@brief 프로그램 이름. 로그 파일 경로를 만들 때 사용.
|
||||
std::string m_szProgramName;
|
||||
|
||||
///@brief 공통 로그 디렉토리 이름. 로그 파일 경로를 만들 때 사용.
|
||||
std::string m_szLogDir;
|
||||
|
||||
///@brief 로그 레벨.
|
||||
int m_nLogLevel;
|
||||
|
||||
///@brief 로그 레벨에 대응되는 문자열 정보를 저장.
|
||||
std::vector<std::string> m_vectorLogLevelString;
|
||||
|
||||
protected:
|
||||
|
||||
public:
|
||||
///@brief 로그 형식을 지정.
|
||||
typedef enum
|
||||
{
|
||||
PREFIX_NONE = 0, /// 클래스 설명의 1.3에 해당
|
||||
PREFIX_DATE, /// 클래스 설명의 1.2에 해당
|
||||
PREFIX_FUNCTION, /// 클래스 설명의 1.1에 해당
|
||||
} LOG_PREFIX;
|
||||
|
||||
// Operations
|
||||
private:
|
||||
///@brief 생성자.
|
||||
/// 프로그램 이름, 공통 로그 디렉토리, 로그 레벨을 저장하고
|
||||
/// 로그 레벨에 대응되는 문자열 정보를 만든다.
|
||||
///@param programName [in] 프로그램 이름
|
||||
///@param logDir [in] 공통 로그 디렉토리 경로
|
||||
///@param logLevel [in] 로그 레벨
|
||||
CLogger( std::string programName, std::string logDir, int logLevel );
|
||||
|
||||
///@brief 소멸자.
|
||||
/// 로그 레벨에 대응되는 문자열 정보를 저장하고 있는
|
||||
/// 벡터 m_vectorLogLevelString을 clear 시킴.
|
||||
virtual ~CLogger();
|
||||
|
||||
///@brief 로그 레벨에 대응되는 문자열을 만든다.
|
||||
///@param none.
|
||||
///@return none.
|
||||
void MakeLogLevelString();
|
||||
|
||||
///@brief 로그 파일이 위치할 실제 로그 디렉토리를 생성한다.
|
||||
/// 생성할 디렉토리 경로는 'logDir/programName'이 된다.
|
||||
///@param programName [in] 프로그램 이름
|
||||
///@param logDir [in] 공통 로그 디렉토리 경로
|
||||
///@return 디렉토리가 이미 존재하거나 생성 성공하면 true,
|
||||
/// 해당 경로가 존재하지만 디렉토리가 아니거나, 디렉토리 생성 실패하면 false 반환.
|
||||
static bool MakeLogDir( std::string programName, std::string logDir );
|
||||
|
||||
///@brief 해당 경로가 디렉토리 인지 아닌지 판단.
|
||||
///@param path [in] 디렉토리 인지 아닌지 판단할 경로.
|
||||
///@return 해당 경로가 디렉토이면 true,
|
||||
/// 경로가 존재하지 않거나 디렉토리가 아니면 false 반환.
|
||||
static bool IsDirectory( std::string path );
|
||||
|
||||
///@brief 로그 레벨이 올바른지 판별.
|
||||
///@param logLevel [in]
|
||||
///@return 올바른 로그 레벨이면 true, 그렇지 않으면 false 반환.
|
||||
static bool IsValidLogLevel( int logLevel );
|
||||
|
||||
///@brief 시간 정보를 입력 받아 로그 파일 이름을 만든다.
|
||||
/// 로그 파일 이름 형식 : 프로그램명_YYYYMMDD.log
|
||||
///param timeNow [in] 현재 시간 정보.
|
||||
///return 로그 파일 이름.
|
||||
std::string GetLogFilename( struct tm &timeNow );
|
||||
|
||||
///@brief 로그를 남기는는 클래스가 정의된 파일의 이름에서 클래스명을 추출한다.
|
||||
/// 쓰레드 안정성을 보장한다.
|
||||
///@param className [out] 파일 이름에서 추출된 클래스명
|
||||
///@param filename [in] 파일 이름.
|
||||
///@return 클래스명 추출이 성공하면 클래스명 문자열의 포인터, 추출 실패하면 NULL.
|
||||
const char* GetClassName( char* className, const char* filename );
|
||||
|
||||
///@brief 인자 logPrefix에 따라 적절한 형식으로 로그 파일에 로그를 저장한다.
|
||||
/// 인자 logLevel이 설정된 로그 레벨보다 높으면 로그를 출력하지 않는다.
|
||||
///@param logLevel [in] 로그 레벨
|
||||
///@param logPrefix [in] 로그 프리픽스 종류.
|
||||
///@functionName [in] ClassName::FunctionNmae() 형식의 문자열.
|
||||
///@lineNum [in] 라인 번호.
|
||||
///@log [in] 출력하고자 하는 로그 내용.
|
||||
bool Write( int logLevel, int logPrefix, const char* functionName, int lineNum, const char* log );
|
||||
|
||||
protected:
|
||||
|
||||
public:
|
||||
///@brief 싱글톤 객체 m_pInstance를 생성하고 인자 정보로 로그 디렉토리를 만든다.
|
||||
///@param programName [in] 프로그램 이름
|
||||
///@param logDir [in] 공통 로그 디렉토리 경로
|
||||
///@param logLevel [in] 로그 레벨
|
||||
///@return 로그 디렉토리를 만들고 싱글톤 객체를 생성했으면 true,
|
||||
/// 로그 디렉토리를 만들지 못 했거나 인자 값이 올바르지 않으면 false 반환.
|
||||
static bool Init( std::string programName, std::string logDir, int logLevel );
|
||||
|
||||
///@brief 싱글톤 객체 m_pInstance를 delete 한다.
|
||||
///@param none.
|
||||
///@return none.
|
||||
static void Exit();
|
||||
|
||||
///@brief 싱글톤 객체 m_pInstance를 반환한다.
|
||||
///@param none.
|
||||
///@return CLogger 객체의 인스턴스.
|
||||
static CLogger* GetInstance();
|
||||
|
||||
///@brief Prefix로 [hh:mm:ss]이 추가된 형식으로 로그 저장.
|
||||
///@param logLevel [in] 로그 레벨
|
||||
///@param fmt [in] 로그 내용 포맷.
|
||||
///@param __VAR_ARGS__ [in] 가변 인자.
|
||||
///@return 로그 파일에 로그를 저장했으면 true, 그렇지 않으면 false 반환
|
||||
bool Write( int logLevel, const char * fmt, ...)
|
||||
__attribute__((format(printf, 3, 4)));
|
||||
|
||||
///@brief Prefix가 없는 로그 저장.
|
||||
///@param logLevel [in] 로그 레벨
|
||||
///@param fmt [in] 로그 내용 포맷.
|
||||
///@param __VAR_ARGS__ [in] 가변 인자.
|
||||
///@return 로그 파일에 로그를 저장했으면 true, 그렇지 않으면 false 반환
|
||||
bool WriteNoPrefix( int logLevel, const char * fmt, ...)
|
||||
__attribute__((format(printf, 3, 4)));
|
||||
|
||||
|
||||
// CHG 2012-08-16 huibong
|
||||
// 가변인자를 사용하는 Write 함수 다중 정의로 인해...
|
||||
// Complier 에서 인수 갯수 및 Type 이 동일할 경우 다른 함수를 가르키는 현상이 발견됨.
|
||||
// 이를 해결하기 위해 Write 함수에 대한 다중 정의를 제거토록 함수명을 명확하게 변경처리함.
|
||||
|
||||
///@brief Prefix로 [hh:mm:ss]와 [ClassName::FunctionName:line]이 추가된 형식으로 로그 저장.
|
||||
///@param logLevel [in] 로그 레벨
|
||||
///@param filename [in] 파일 이름
|
||||
///@param funcname [in] 함수 이름
|
||||
///@param lineNum [in] 라인 번호
|
||||
///@param fmt [in] 로그 내용 포맷.
|
||||
///@param __VAR_ARGS__ [in] 가변 인자.
|
||||
///@return 로그 파일에 로그를 저장했으면 true, 그렇지 않으면 false 반환
|
||||
bool WriteWithFunc( int logLevel, const char* filename, const char* funcname, int lineNum, const char * fmt, ...)
|
||||
__attribute__((format(printf, 6, 7)));
|
||||
|
||||
///@brief 로그를 hex 형식으로 저장.
|
||||
///@param logLevel [in] 로그 레벨
|
||||
///@param data [in] hex 형식으로 출력할 데이터.
|
||||
///@pram size [in] data의 크기.
|
||||
///@return 로그 파일에 로그를 저장했으면 true, 그렇지 않으면 false 반환
|
||||
bool WriteHex( int logLevel, const unsigned char* data, const int size );
|
||||
|
||||
///@brief 로그을 설정한다. 인자 logLevel이 적절한 값이면 새로운 값으로 변경하고
|
||||
/// 적절한 값이 아니면 로그 레벨을 변경하지 않는다.
|
||||
///@param logLevel [in] 설정할 로그 레벨
|
||||
///@return none.
|
||||
bool SetLogLevel( int logLevel );
|
||||
|
||||
inline int GetLogLevel() { return m_nLogLevel; };
|
||||
inline std::string GetLogDir() { return m_szLogDir + "/" + m_szProgramName; };
|
||||
};
|
||||
|
||||
#define LOG( level, format, ... ) \
|
||||
if( CLogger::GetInstance() != NULL ) \
|
||||
{ \
|
||||
CLogger::GetInstance()->WriteWithFunc( level, __FILE__, __FUNCTION__, __LINE__, format, ##__VA_ARGS__ ); \
|
||||
}
|
||||
|
||||
|
||||
#define _LOG( level, format, ... ) \
|
||||
if( CLogger::GetInstance() != NULL ) \
|
||||
{ \
|
||||
CLogger::GetInstance()->Write( level, format, ##__VA_ARGS__ ); \
|
||||
}
|
||||
|
||||
|
||||
#define _LOG_( level, format, ... ) \
|
||||
if( CLogger::GetInstance() != NULL ) \
|
||||
{ \
|
||||
CLogger::GetInstance()->WriteNoPrefix( level, format, ##__VA_ARGS__ ); \
|
||||
}
|
||||
|
||||
|
||||
#define _LOG_HEX_( level, data, size ) \
|
||||
if( CLogger::GetInstance() != NULL ) \
|
||||
{ \
|
||||
CLogger::GetInstance()->WriteHex( level, (const unsigned char*)data, size ); \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define FUNC_BEGIN() LOG( LDEV1, "begin" )
|
||||
#define FUNC_END() LOG( LDEV1, "end" )
|
||||
|
||||
#define FRM_BEGIN() LOG( LDEV2, "begin" )
|
||||
#define FRM_END() LOG( LDEV2, "end" )
|
||||
|
||||
#endif // __LOGGER_H__
|
||||
@@ -0,0 +1,62 @@
|
||||
#****************************************************************************
|
||||
# Makefile for INTERACTIVE Common Libaray
|
||||
# -----------------------------------------
|
||||
#
|
||||
# begin : 2010/02/27
|
||||
# copyright : (C) 2005 SolutionBox Inc.
|
||||
# author : Service 1 Team
|
||||
# email : svc1@solbox.com
|
||||
# version : 1.0
|
||||
#
|
||||
# CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
# Redistribution and use in source and binary forms, with or with out
|
||||
# modification, are not permitted in outside of SolutionBox Inc.
|
||||
#*****************************************************************************
|
||||
|
||||
# Library info
|
||||
|
||||
LIB_NAME = InterCommon
|
||||
|
||||
LIB = lib$(LIB_NAME).a
|
||||
|
||||
OBJS = Config.o Logger.o BaseSocket.o
|
||||
|
||||
# Compiler info
|
||||
CC = /usr/bin/g++
|
||||
AR = /usr/bin/ar
|
||||
|
||||
DIR_INCLUDE = -I/usr/local/include
|
||||
|
||||
CFLAGS = -Wall -O3 -g -Wreturn-type -Wunused -Wuninitialized\
|
||||
-Wparentheses -Wshadow -Wpointer-arith -Woverloaded-virtual\
|
||||
-D_REENTRANT
|
||||
LFLAGS =
|
||||
DFLAGS =
|
||||
|
||||
############################
|
||||
|
||||
all:$(LIB)
|
||||
sync
|
||||
|
||||
%.o: %.cpp
|
||||
$(CC) $(CFLAGS) -o $@ -c $^ $(DFLAGS) $(DIR_INCLUDE)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -o $@ -c $^ $(DFLAGS) $(DIR_INCLUDE)
|
||||
|
||||
|
||||
$(LIB): $(OBJS)
|
||||
$(AR) crsv $@ $^
|
||||
|
||||
|
||||
clean:
|
||||
-rm -f *.o core *.out *.log
|
||||
-rm -f $(LIB)
|
||||
sync
|
||||
|
||||
|
||||
install :
|
||||
sync
|
||||
|
||||
|
||||
# End of Makefile
|
||||
@@ -0,0 +1,415 @@
|
||||
#include "ArecaWrapper.h"
|
||||
#include <vector>
|
||||
#include <time.h>
|
||||
|
||||
#define MAX_EVENT_BUFF_SIZE 512
|
||||
|
||||
#define UNKNOWN_EVT_STR "Unknown Event"
|
||||
|
||||
|
||||
CArecaWrapper::CArecaWrapper(int nEventLevel)
|
||||
: m_nEventLevel( nEventLevel )
|
||||
{
|
||||
pthread_mutex_init(&mutex_lock, NULL);
|
||||
}
|
||||
|
||||
CArecaWrapper::~CArecaWrapper()
|
||||
{
|
||||
pthread_mutex_destroy(&mutex_lock);
|
||||
int nInterfaceIndex;
|
||||
CArclib *ctrl;
|
||||
for (nInterfaceIndex =0; nInterfaceIndex < m_nTotalCtrl; nInterfaceIndex++)
|
||||
{
|
||||
ctrl = &m_Arc[nInterfaceIndex];
|
||||
LinuxIoctlInterface *out = (LinuxIoctlInterface*)ctrl->ArcGetInterface();
|
||||
delete out;
|
||||
}
|
||||
}
|
||||
|
||||
// libacrlib에서 사용하는 pSYS_TIME 타입의 값을 time_t로 변환한다.
|
||||
time_t CArecaWrapper::GetTime_t(pSYS_TIME evtTime)
|
||||
{
|
||||
/*
|
||||
tm tmpTime;
|
||||
|
||||
tmpTime.tm_year = evtTime->u.tmYear+100;
|
||||
tmpTime.tm_mon = evtTime->u.tmMonth-1;
|
||||
tmpTime.tm_mday = evtTime->u.tmDate;
|
||||
tmpTime.tm_hour = evtTime->u.tmHour;
|
||||
tmpTime.tm_min = evtTime->u.tmMinute;
|
||||
tmpTime.tm_sec = evtTime->u.tmSecond;
|
||||
|
||||
return mktime(&tmpTime);
|
||||
*/
|
||||
|
||||
time_t rawtime;
|
||||
struct tm * timeinfo;
|
||||
time ( &rawtime );
|
||||
timeinfo = gmtime ( &rawtime );
|
||||
|
||||
timeinfo->tm_year = evtTime->u.tmYear+100;
|
||||
timeinfo->tm_mon = evtTime->u.tmMonth-1;
|
||||
timeinfo->tm_mday = evtTime->u.tmDate;
|
||||
timeinfo->tm_hour = evtTime->u.tmHour;
|
||||
timeinfo->tm_min = evtTime->u.tmMinute;
|
||||
timeinfo->tm_sec = evtTime->u.tmSecond;
|
||||
timeinfo->tm_isdst = 0; // disable daylight saving time
|
||||
|
||||
time_t ret = mktime ( timeinfo );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
bool CArecaWrapper::DisableUpload()
|
||||
{
|
||||
system( "touch /user/service/vmasd.disable" );
|
||||
|
||||
struct stat st;
|
||||
|
||||
if( lstat( "/user/service/vmasd.disable", &st ) != 0 )
|
||||
{
|
||||
ERROR_LOG( "can't touch vmasd.disable" );
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
INFO_LOG( "disable upload." );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CArecaWrapper::IsDisableUpload( int eventCategory, int eventId )
|
||||
{
|
||||
switch( eventCategory )
|
||||
{
|
||||
case EVENT_DEVICE: // device event
|
||||
/// The meaning of eventId
|
||||
/// 0 : Device Inserted
|
||||
/// 1 : Device Removed
|
||||
/// 2 : Reading Error
|
||||
/// 3 : Writing Error
|
||||
/// 4 : ATA Ecc Error
|
||||
/// 5 : Change ATA Mode
|
||||
/// 6 : Time Out Error
|
||||
/// 7 : Device Failed
|
||||
/// 8 : PCI Parity Error
|
||||
/// 9 : Dev Fail (SMART)
|
||||
/// 10 : Pass
|
||||
|
||||
|
||||
case EVENT_VOLUMESET: // volumeset event
|
||||
case EVENT_RAIDSET: // raidset event
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//int CArecaWrapper::GetEvent(int nEventFlag, char *pszResult)
|
||||
bool CArecaWrapper::GetEvent(int nEventFlag, list<CEventData>& listRet)
|
||||
{
|
||||
CArclib *ctrl;
|
||||
ARC_STATUS stat = ARC_SUCCESS;
|
||||
bool gotEvent = false;
|
||||
int nCount = 0; // total number of event objects we got
|
||||
int i;
|
||||
int nCurEvtLevel = EVT_SERIOUS;
|
||||
sSYSTEM_INFO sysInfo;
|
||||
BYTE ptr1[64];
|
||||
char tmpStr[64];
|
||||
char eventStrBuf[MAX_EVENT_BUFF_SIZE];
|
||||
int eventCategory = 0;
|
||||
int eventId = 0;
|
||||
|
||||
//the time event occurred, defined in arclib.h
|
||||
pSYS_TIME evtTime = (pSYS_TIME)new sSYS_TIME;
|
||||
|
||||
pthread_mutex_lock(&mutex_lock);
|
||||
if (m_nTotalCtrl == 0) {
|
||||
LOG(LERR, "No Raild controller was found.");
|
||||
pthread_mutex_unlock(&mutex_lock);
|
||||
if( evtTime )
|
||||
{
|
||||
delete evtTime;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ctrl = &m_Arc[0];
|
||||
|
||||
memset(ptr1, 0, sizeof(ptr1));
|
||||
memset(tmpStr, 0, sizeof(tmpStr));
|
||||
memset(eventStrBuf, 0, sizeof(eventStrBuf));
|
||||
|
||||
// event object defined in arclib.h
|
||||
pEVENT_DATA pEventObject = (pEVENT_DATA)new sEVENT_DATA;
|
||||
stat = ctrl->ArcGetSysInfo(&sysInfo);
|
||||
if( stat != ARC_SUCCESS )
|
||||
{
|
||||
LOG(LERR, "ArcGetSysInfo Failed: %d",stat);
|
||||
pthread_mutex_unlock(&mutex_lock);
|
||||
if( pEventObject )
|
||||
{
|
||||
delete pEventObject;
|
||||
}
|
||||
if( evtTime )
|
||||
{
|
||||
delete evtTime;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/* We should call ArcSetTime() to correct the raid-subsystem time
|
||||
Call ArcGetReqEventPage() to get the required event page from raid subsystem.
|
||||
There are 4 event pages reside in the raid subsystem and each contains 16 event objects.
|
||||
*/
|
||||
memset(pEventObject, 0, sizeof(sEVENT_DATA));
|
||||
stat = ctrl->ArcGetReqEventPage(nEventFlag, &nCount);
|
||||
if (stat == ARC_SUCCESS)
|
||||
{
|
||||
if (nCount != 0)
|
||||
{
|
||||
for ( i = nCount - 1; i >= 0; i--)
|
||||
{
|
||||
// Call ArcGetEventObject function to extract the individual event object from event page
|
||||
if (ctrl->ArcGetEventObject( i, pEventObject ))
|
||||
{
|
||||
::memset(eventStrBuf, 0, MAX_EVENT_BUFF_SIZE);
|
||||
eventCategory = (int)pEventObject->evtCategory;
|
||||
eventId = pEventObject->evtType;
|
||||
|
||||
*((LONG *)evtTime) = pEventObject->evtTime;
|
||||
// Parse the event object we got
|
||||
switch ((int)pEventObject->evtCategory)
|
||||
{
|
||||
/*
|
||||
The member "evtStr" of event object structure contains the string to indicate
|
||||
which raidset owns this event object
|
||||
*/
|
||||
case EVENT_RAIDSET: // raidset event
|
||||
nCurEvtLevel = pEventObject->evtType;
|
||||
memcpy(tmpStr, pEventObject->evtStr, 16);
|
||||
if ( nCurEvtLevel > RS_EVT_NO_EVENT )
|
||||
{
|
||||
strcpy( (char *)ptr1, UNKNOWN_EVT_STR);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( (char *)ptr1, htmRaidEvent[pEventObject->evtType]);
|
||||
}
|
||||
sprintf((char *)eventStrBuf, "Controller#%d: %s %s",1, tmpStr, ptr1);
|
||||
gotEvent = true;
|
||||
break;
|
||||
/*
|
||||
The member "evtStr" of event object structure contains the string to indicate
|
||||
which volumeset owns this event object
|
||||
*/
|
||||
case EVENT_VOLUMESET: // volumeset event
|
||||
nCurEvtLevel = pEventObject->evtType;
|
||||
memcpy(tmpStr, pEventObject->evtStr, 16);
|
||||
if ( nCurEvtLevel >= VS_EVT_TOTALS)
|
||||
{
|
||||
strcpy( (char *)ptr1, UNKNOWN_EVT_STR);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( (char *)ptr1, htmVolEvent[pEventObject->evtType]);
|
||||
}
|
||||
sprintf((char *)eventStrBuf, "Controller#%d: %s %s", 1, tmpStr, ptr1);
|
||||
gotEvent = true;
|
||||
break;
|
||||
|
||||
case EVENT_DEVICE: // device event
|
||||
nCurEvtLevel = pEventObject->evtType;
|
||||
if( sysInfo.gsiTargetType == TARGET_SAS )
|
||||
{
|
||||
memcpy(tmpStr, pEventObject->evtStr, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(tmpStr, "IDE Channel #%2d", pEventObject->evtChannel + 1);
|
||||
}
|
||||
|
||||
if ( nCurEvtLevel >= DEV_EVT_TOTALS)
|
||||
{
|
||||
strcpy( (char *)ptr1, UNKNOWN_EVT_STR);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( (char *)ptr1, htmDevEvent[pEventObject->evtType]);
|
||||
}
|
||||
sprintf((char *)eventStrBuf, "Controller#%d: %s %s", 1
|
||||
, tmpStr, ptr1 );
|
||||
gotEvent = true;
|
||||
break;
|
||||
|
||||
case EVENT_HOST: // host event
|
||||
//this is Host SCSI events
|
||||
nCurEvtLevel = pEventObject->evtType;
|
||||
if ( sysInfo.gsiScsiHostChannels)
|
||||
{
|
||||
if ( nCurEvtLevel >= SCSI_EVT_TOTALS )
|
||||
{
|
||||
strcpy( (char *)ptr1, UNKNOWN_EVT_STR);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( (char *)ptr1, htmScsiHostEvent[pEventObject->evtType]);
|
||||
}
|
||||
} else {
|
||||
if ( nCurEvtLevel >= SCSI_EVT_TOTALS )
|
||||
{
|
||||
strcpy( (char *)ptr1, UNKNOWN_EVT_STR);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( (char *)ptr1, htmIdeHostEvent[pEventObject->evtType]);
|
||||
}
|
||||
}
|
||||
|
||||
// CHG 2020-10-05 huibong FreeBSD 12.x 컴파일시 발생하는 warning 코드 수정 (#33225)
|
||||
// - FreeBSD 12.x 의 gcc 9.3 컴파일시 sprintf 사용 관련 buffer size 문제로 warning 발생
|
||||
// - flow 상으로는 buffer overflow 발생 가능성 없음
|
||||
// - 하지만.. 컴파일시마다 warning 발생하므로.. 수정 결정
|
||||
sprintf((char *)eventStrBuf, "Controller#%d: %s %s", 1, eventCat[pEventObject->evtCategory], ptr1 );
|
||||
|
||||
gotEvent = true;
|
||||
break;
|
||||
|
||||
case EVENT_HW_MONITOR: // hardware monitor event
|
||||
nCurEvtLevel = pEventObject->evtType;
|
||||
memcpy(tmpStr, eventCat[pEventObject->evtCategory], 16);
|
||||
if ( nCurEvtLevel >= HW_EVT_TOTALS )
|
||||
{
|
||||
strcpy( (char *)ptr1, UNKNOWN_EVT_STR);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( (char *)ptr1, htmHwMonEvent[pEventObject->evtType]);
|
||||
}
|
||||
sprintf((char *)eventStrBuf, "Controller#%d: %s %s", 1
|
||||
, tmpStr, ptr1 );
|
||||
gotEvent = true;
|
||||
break;
|
||||
|
||||
case EVENT_NEW_83782D:
|
||||
memcpy(tmpStr, pEventObject->evtStr, 16);
|
||||
if ( pEventObject->evtType >= GHM_TOTALS )
|
||||
{
|
||||
strcpy( (char *)ptr1, UNKNOWN_EVT_STR);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( (char *)ptr1, htmNewEventStr[pEventObject->evtType]);
|
||||
}
|
||||
sprintf((char *)eventStrBuf, "Controller#%d: %s %s",1
|
||||
, tmpStr, ptr1 );
|
||||
gotEvent = true;
|
||||
break;
|
||||
case EVENT_NO_EVENT:
|
||||
// 이벤트가 없는 경우
|
||||
gotEvent = true;
|
||||
default:
|
||||
continue;
|
||||
}// end switch
|
||||
|
||||
}// end if
|
||||
|
||||
// 모든 이벤트를 결과 list에 추가필요 수정 2015-06-26
|
||||
CEventData objEvent;
|
||||
|
||||
objEvent.m_evtTime = GetTime_t(evtTime);
|
||||
objEvent.m_szEventData = eventStrBuf;
|
||||
objEvent.SetEventType( eventCategory, eventId );
|
||||
|
||||
listRet.push_back(objEvent);
|
||||
|
||||
|
||||
}// end for
|
||||
} else {
|
||||
_LOG(LWAR, "Event empty.");
|
||||
gotEvent = true;
|
||||
}
|
||||
}// end if
|
||||
|
||||
|
||||
if (pEventObject) {
|
||||
delete pEventObject;
|
||||
}
|
||||
|
||||
if (evtTime) {
|
||||
delete evtTime;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_lock);
|
||||
return gotEvent;
|
||||
}
|
||||
|
||||
int CArecaWrapper::DiscoveryDevice(void)
|
||||
{
|
||||
dev_t dev;
|
||||
char buf[64];
|
||||
mode_t mode = 0666;
|
||||
unsigned int nTotalCtrl = 0;
|
||||
ARC_STATUS stat = ARC_SUCCESS;
|
||||
sSYSTEM_INFO sysInfo;
|
||||
|
||||
mode |= S_IFCHR;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
sprintf(buf,"/dev/arcmsr%d", i);
|
||||
unlink(buf);
|
||||
}
|
||||
|
||||
for (int mymajor = 255; mymajor > 161; mymajor--)
|
||||
{
|
||||
for (int myminor = 0; myminor < 4; myminor++)
|
||||
{
|
||||
LinuxIoctlInterface *out = new LinuxIoctlInterface();
|
||||
memset(buf, 0, sizeof(buf));
|
||||
sprintf(buf,"/dev/arcmsr%d", nTotalCtrl);
|
||||
dev = makedev(mymajor, myminor);
|
||||
mknod(buf, mode, dev);
|
||||
if (out->init(nTotalCtrl)) {
|
||||
stat = m_Arc[nTotalCtrl++].ArcInitSession(out);
|
||||
if (stat != ARC_SUCCESS) {
|
||||
_LOG(LERR, "ArcInitSession Failed : %d",stat);
|
||||
if( out )
|
||||
{
|
||||
delete out;
|
||||
out = NULL;
|
||||
}
|
||||
unlink(buf);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
delete out;
|
||||
out = NULL;
|
||||
unlink(buf);
|
||||
}
|
||||
}
|
||||
if (nTotalCtrl) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nTotalCtrl;
|
||||
}
|
||||
|
||||
int CArecaWrapper::InitArecaControllers(void)
|
||||
{
|
||||
int nCount = 0;
|
||||
int nInterfaceIndex = 0;
|
||||
m_nTotalCtrl = DiscoveryDevice();
|
||||
_LOG(LDBG, "Total Count: %d", m_nTotalCtrl);
|
||||
|
||||
if(m_nTotalCtrl == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (nInterfaceIndex =0; nInterfaceIndex < m_nTotalCtrl; nInterfaceIndex++)
|
||||
{
|
||||
m_Arc[nInterfaceIndex].ArcGetReqEventPage(FLAG_ALL, &nCount);
|
||||
}
|
||||
|
||||
return m_nTotalCtrl;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/***************************************************************************
|
||||
Areca Wrapper Class
|
||||
-----------------------------------------
|
||||
begin : 2010/05/19
|
||||
copyright : (C) 2010 SolutionBox Inc.
|
||||
author : svc1
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2010 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __ARECA_WRAPPER__
|
||||
#define __ARECA_WRAPPER__
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
// 가장 중요하고 핵심적인 헤더 파일
|
||||
#include "arclib.h"
|
||||
#include "ethernet.h"
|
||||
#include "EventData.h"
|
||||
#include <list>
|
||||
#include "Logger.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// 필요한 인터페이스에 대한 헤더파일
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
#include "linux_comm.h"
|
||||
#include "linux_ioctl.h"
|
||||
#if defined(__linux__)
|
||||
#include "linux_scsi.h"
|
||||
#include "linux_pass_ioctl.h"
|
||||
#else
|
||||
#include "freebsd_scsi.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// 정보를 조회할 최대 컨트롤 수.
|
||||
#define MAX_CONTROLLER_SUPPORTED 64
|
||||
|
||||
// for GetEvent()'s first param
|
||||
#define GET_EVENT_ALL 0
|
||||
#define GET_EVENT_ONE 1
|
||||
|
||||
class CArecaWrapper
|
||||
{
|
||||
public:
|
||||
|
||||
/// @brief 생성자.
|
||||
/// @param nEventLevel [in] 필터 할 이벤트 레벨을 지정한다. conf를 통해 받아오게 되며, 레벨은 아래와 같다.
|
||||
///< -------- EVENT LEVEL ---------
|
||||
///< 0: Not to report
|
||||
///< 1: Serious Error Notification
|
||||
///< 2: Error Notification
|
||||
///< 3: Warning Notification
|
||||
///< 4: Information Notification
|
||||
///< ------------------------------
|
||||
CArecaWrapper(int nEventLevel);
|
||||
|
||||
/// @brief 소멸자.
|
||||
~CArecaWrapper();
|
||||
|
||||
/// @brief Areca Controller의 정보를 얻을 준비를 한다.
|
||||
// @return Areca Controller의 개수를 리턴한다. 없을 경우 -1을 리턴한다.
|
||||
int InitArecaControllers(void);
|
||||
|
||||
|
||||
/// @brief Areca Controller의 정보를 얻을 준비를 한다.
|
||||
/// @param nFlag [in] 이벤트 받을 형태를 지정한다.
|
||||
//< GET_EVENT_ALL : 저장된 모든 이벤트 데이터를 수신한다.
|
||||
//< GET_EVENT_ONE : 최근 1개의 이벤트 데이터를 수신한다.
|
||||
/// @param listRet [out] Areca Library를 통해 얻은 데이터를 저장한다. 데이터의 타입은 CEventData 형태이다.
|
||||
/// @return 성공시 true, 실패시 false 를 리턴한다.
|
||||
bool GetEvent(int nFlag, list<CEventData>& listRet);
|
||||
|
||||
private:
|
||||
CArclib m_Arc[MAX_CONTROLLER_SUPPORTED];
|
||||
|
||||
pthread_mutex_t mutex_lock;
|
||||
|
||||
int DiscoveryDevice(void);
|
||||
time_t GetTime_t(pSYS_TIME evtTime);
|
||||
int m_nEventLevel;
|
||||
int m_nTotalCtrl;
|
||||
|
||||
//bool IsDisableUpload( int eventCategory, int eventId );
|
||||
//bool DisableUpload();
|
||||
};
|
||||
#endif // __ARECA_WRAPPER__
|
||||
@@ -0,0 +1,127 @@
|
||||
/***************************************************************************
|
||||
AutoDisableUpload.cpp
|
||||
-----------------------------------------
|
||||
begin : 2011/07/26
|
||||
copyright : (C) 2010 SolutionBox Inc.
|
||||
author : svc1
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2010 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
#include "AutoDisableUpload.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
CAutoDisableUpload::CAutoDisableUpload()
|
||||
{
|
||||
}
|
||||
|
||||
CAutoDisableUpload::~CAutoDisableUpload()
|
||||
{
|
||||
}
|
||||
|
||||
void CAutoDisableUpload::DoProcess( int eventCategory, int eventId )
|
||||
{
|
||||
if( IsDisableUpload( eventCategory, eventId ) == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
system( "touch /user/service/vmasd.disable" );
|
||||
|
||||
struct stat st;
|
||||
|
||||
if( lstat( "/user/service/vmasd.disable", &st ) != 0 )
|
||||
{
|
||||
LOG(LERR, "can't touch vmasd.disable. event category = %s, event name = %s",
|
||||
m_szEventCategory.c_str(), m_szEventName.c_str() );
|
||||
return;
|
||||
}
|
||||
|
||||
_LOG(LINF, "disable upload. event category = %s, event name = %s",
|
||||
m_szEventCategory.c_str(), m_szEventName.c_str() );
|
||||
}
|
||||
|
||||
bool CAutoDisableUpload::IsDisableUpload( int eventCategory, int eventId )
|
||||
{
|
||||
switch( eventCategory )
|
||||
{
|
||||
case EVENT_DEVICE:
|
||||
/// The meaning of eventId.
|
||||
/// 0(DEV_EVT_ADDED) - Device Inserted
|
||||
/// 1(DEV_EVT_REMOVED) - Device Removed
|
||||
/// 2(DEV_EVT_READ_ERROR) - Reading Error
|
||||
/// 3(DEV_EVT_WRITE_ERROR) - Writing Error
|
||||
/// 4(DEV_EVT_ATA_ECC_ERROR) - ATA Ecc Error
|
||||
/// 5(DEV_EVT_ATA_CHANGE_MODE) - Change ATA Mode
|
||||
/// 6(DEV_EVT_TIMEOUT) - Time Out Error
|
||||
/// 7(DEV_EVT_MARK_FAILED) - Device Failed
|
||||
/// 8(DEV_EVT_PCI_ERROR) - PCI Parity Error
|
||||
/// 9(DEV_EVT_SMART_FAILED) - Dev Fail (SMART)
|
||||
/// 10(DEV_EVT_CREATE_PASS) - Pass Through Disk Created
|
||||
/// 11(DEV_EVT_MODIFY_PASS) - Pass Through Disk Modified
|
||||
/// 12(DEV_EVT_DELETE_PASS) - Pass Through Disk Deleted
|
||||
|
||||
m_szEventCategory = "Device Event";
|
||||
m_szEventName = htmDevEvent[ eventId ];
|
||||
return ( eventId == DEV_EVT_MARK_FAILED ? true : false );
|
||||
|
||||
case EVENT_VOLUMESET:
|
||||
/// The meaning of eventId.
|
||||
/// 0(VS_EVT_INITIALIZING) - Start Initialize
|
||||
/// 1(VS_EVT_REBUILDING) - Start Rebuilding
|
||||
/// 2(VS_EVT_MIGRATING) - Start Migrating
|
||||
/// 3(VS_EVT_CHECKING) - Start Checking
|
||||
/// 4(VS_EVT_COMPLETE_INIT) - Complete Init
|
||||
/// 5(VS_EVT_COMPLETE_REBUILD) - Complete Rebuild
|
||||
/// 6(VS_EVT_COMPLETE_MIGRATING) - Complete Migrate
|
||||
/// 7(VS_EVT_COMPLETE_CHECKING) - Complete Check
|
||||
/// 8(VS_EVT_CREATE) - Create Volume
|
||||
/// 9(VS_EVT_DELETE) - Delete Volume
|
||||
/// 10(VS_EVT_MODIFY) - Modify Volume
|
||||
/// 11(VS_EVT_DEGRADED) - Volume Degraded
|
||||
/// 12(VS_EVT_FAILED) - Volume Failed
|
||||
/// 13(VS_EVT_REVIVED) - Failed Volume Revived
|
||||
/// 14(VS_EVT_ABORT_INIT) - Abort Initialization
|
||||
/// 15(VS_EVT_ABORT_REBUILD) - Abort Rebuilding
|
||||
/// 16(VS_EVT_ABORT_MIGRATING) - Abort Migration
|
||||
/// 17(VS_EVT_ABORT_CHECKING) - Abort Checking
|
||||
/// 18(VS_EVT_STOP_INIT) - Stop Initialization
|
||||
/// 19(VS_EVT_STOP_REBUILD) - Stop Rebuilding
|
||||
/// 20(VS_EVT_STOP_MIGRATING) - Stop Migration
|
||||
/// 21(VS_EVT_STOP_CHECKING) - Stop Checking
|
||||
|
||||
m_szEventCategory = "VolumeSet Event";
|
||||
m_szEventName = htmVolEvent[ eventId ];
|
||||
return ( ( eventId == VS_EVT_REBUILDING ) || ( eventId == VS_EVT_DEGRADED ) ? true : false );
|
||||
|
||||
case EVENT_RAIDSET:
|
||||
/// The meaning of eventId
|
||||
/// 0(RS_EVT_CREATE) - Create RaidSet
|
||||
/// 1(RS_EVT_DELETE) - Delete RaidSet
|
||||
/// 2(RS_EVT_EXPAND) - Expand RaidSet
|
||||
/// 3(RS_EVT_REBUILD) - Rebuild RaidSet
|
||||
/// 4(RS_EVT_DEGRADED) - RaidSet Degraded
|
||||
|
||||
m_szEventCategory = "RaidSet Event";
|
||||
m_szEventName = htmRaidEvent[ eventId ];
|
||||
return ( ( eventId == RS_EVT_REBUILD ) || ( eventId == RS_EVT_DEGRADED ) ? true : false );
|
||||
|
||||
/// for test code
|
||||
///case EVENT_NEW_83782D:
|
||||
/// m_szEventCategory = "New Events";
|
||||
/// m_szEventName = htmNewEventStr[ eventId ];
|
||||
/// return ( eventId == GHM_GUI_LOGIN ? true : false );
|
||||
|
||||
default:
|
||||
m_szEventCategory = "";
|
||||
m_szEventName = "";
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/***************************************************************************
|
||||
AutoDisableUpload.h
|
||||
-----------------------------------------
|
||||
begin : 2011/07/26
|
||||
copyright : (C) 2010 SolutionBox Inc.
|
||||
author : svc1
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2010 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
#ifndef __AUTODISABLEUPLOAD_H__
|
||||
#define __AUTODISABLEUPLOAD_H__
|
||||
|
||||
#include "arclib.h"
|
||||
#include "Logger.h"
|
||||
#include <string>
|
||||
|
||||
class CAutoDisableUpload
|
||||
{
|
||||
// Attributes
|
||||
private:
|
||||
std::string m_szEventCategory;
|
||||
std::string m_szEventName;
|
||||
|
||||
protected:
|
||||
|
||||
public:
|
||||
|
||||
|
||||
// Operations
|
||||
private:
|
||||
/// @brief 업로드 방지 이벤트 발생 여부 확인.
|
||||
/// @param eventCategory [in] 이벤트 카테고리
|
||||
/// @param eventId [in] 이벤트 카테고리별 이벤트 아이디
|
||||
/// @return 업로드 방지 이벤트면 true, 그렇지 않으면 false.
|
||||
bool IsDisableUpload( int eventCategory, int eventId );
|
||||
|
||||
protected:
|
||||
|
||||
public:
|
||||
CAutoDisableUpload();
|
||||
virtual ~CAutoDisableUpload();
|
||||
|
||||
/// @brief 업로드 방지 이벤트가 발생했으면 /user/service/vmasd.disable 파일을 생성해서
|
||||
/// 업로드가 방지 되도록 한다.
|
||||
/// @param eventCategory [in] 이벤트 카테고리
|
||||
/// @param eventId [in] 이벤트 카테고리별 이벤트 아이디
|
||||
/// @return 없음.
|
||||
void DoProcess( int eventCategory, int eventId );
|
||||
};
|
||||
|
||||
#endif // __AUTODISABLEUPLOAD_H__
|
||||
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
#include "fhs_raidmond.h"
|
||||
#include "Child.h"
|
||||
#include "SmsSender.h"
|
||||
#include "ArecaWrapper.h"
|
||||
#include "UdpListener.h"
|
||||
#include "EventDataManager.h"
|
||||
#include "AutoDisableUpload.h"
|
||||
|
||||
|
||||
#define MAXSIZEOFSTR 128
|
||||
|
||||
/// @brief child Process 종료 Signal 을 전달받은 경우 이를 처리하기 위한 함수.
|
||||
/// @param nSignalNumber [in] 발생한 시그널 Number
|
||||
/// @return void
|
||||
static void SigTermChild( int nSignalNumber )
|
||||
{
|
||||
// Signal Number 에 따른 로깅처리.
|
||||
if( nSignalNumber == SIGTERM )
|
||||
{
|
||||
_LOG( LWAR, "Child Process[%d] exit job start by user signal [SIGTERM]", getpid() );
|
||||
}
|
||||
else
|
||||
{
|
||||
_LOG(LWAR, "Child Process[%d] exit job start by abnormal signal [%d]", getpid(), nSignalNumber );
|
||||
}
|
||||
_LOG(LWAR, "Child Process[%d] exit job end. Good Bye..", getpid());
|
||||
|
||||
usleep(500000);
|
||||
exit( EXIT_SUCCESS );
|
||||
}
|
||||
/// @brief child Process 에서 Core 생성 관련 Signal 을 받은 경우 이를 처리하기 위한 함수.
|
||||
/// @param nSignalNumber [in] 발생한 시그널 Number
|
||||
/// @return void
|
||||
static void SigCoreChild( int nSignalNumber )
|
||||
{
|
||||
_LOG(LERR, "Child Process[%d] abnoraml exit. Check Core file. Receive signal [%d]", getpid(), nSignalNumber );
|
||||
//ERROR_LOG( "Core file path : [%s/%s.core]", g_envConfig.szLogDir.c_str(), PROG_NAME );
|
||||
// Process 종료관련 작업 추가
|
||||
|
||||
// Log Directory 상에 Core 파일 생성처리.
|
||||
chdir( g_envConfig.szLogDir.c_str() );
|
||||
signal( nSignalNumber, SIG_DFL );
|
||||
// Core dump 생성을 위한 신호 발생처리.=> ?
|
||||
raise( nSignalNumber );
|
||||
}
|
||||
|
||||
|
||||
/// @brief child process signal 처리 설정을 위한 함수
|
||||
/// @return void
|
||||
static void SetSignalChild( void )
|
||||
{
|
||||
sigset_t set;
|
||||
struct sigaction act;
|
||||
sigfillset( &set );
|
||||
sigprocmask( SIG_SETMASK, &set, NULL );
|
||||
memset( &act, 0x00, sizeof(act) );
|
||||
sigfillset( &act.sa_mask );
|
||||
/* 무시할 신호 목록 */
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigaction( SIGPIPE, &act, NULL); /* 파이프 디스크립터 오류 발생시 Process가 죽는 것은 방지하기 위하여 설정 */
|
||||
sigaction( SIGHUP , &act, NULL); /* Process를 기동시킨 관리자의 로그아웃시 발생 시그널 */
|
||||
sigaction( SIGINT , &act, NULL); /* ^C 키를 누른 경우 받는 신호 => demon 으로 기동되기 땜시 이 신호 못받음 */
|
||||
sigaction( SIGQUIT, &act, NULL); /* 키보드에 의한 Abort 신호 처리 => ? */
|
||||
// Child 프로세스는 자식 프로세스가 존재하지 않으므로 그냥 무시처리함.
|
||||
sigaction( SIGCHLD, &act, NULL);
|
||||
/* 각종 에러나 사용자의 종료 신호 처리 */
|
||||
act.sa_handler = SigTermChild;
|
||||
sigaction( SIGTERM, &act, NULL); /* kill -TERM 에 의한 프로세스 종료시 */
|
||||
/* Core 관련 signal 처리 : 오류 처리 및 Debug(core dump) 목적 */
|
||||
// dadamin : 팀 기준 적용
|
||||
//act.sa_handler = SigCoreChild;
|
||||
//sigaction( SIGILL , &act, NULL); /* Illegal instruction */
|
||||
//sigaction( SIGFPE , &act, NULL); /* Erroneout arithmetic operation */
|
||||
//sigaction( SIGBUS , &act, NULL); /* Access to undefined portion of a memory object */
|
||||
//sigaction( SIGSEGV, &act, NULL); /* Invalid memory reference */
|
||||
//sigaction( SIGSYS , &act, NULL); /* Bad System Call */
|
||||
//sigaction( SIGXCPU, &act, NULL); /* CPU-time limit exceeded */
|
||||
//sigaction( SIGXFSZ, &act, NULL); /* File-size limit exceeded */
|
||||
|
||||
|
||||
sigemptyset(&set); /* 신호 처리기 처리 설정 위한 블록 해제 */
|
||||
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||
}
|
||||
|
||||
/// @brief Child Process 의 main 함수
|
||||
int ChildMain(void)
|
||||
{
|
||||
bool bRet = false;
|
||||
int nFailCnt = 0;
|
||||
// set child signal
|
||||
SetSignalChild();
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
setproctitle( "Child [initialize process]");
|
||||
#endif
|
||||
|
||||
|
||||
char szTime[MAXSIZEOFSTR];
|
||||
time_t ltime;
|
||||
struct tm *pTm = NULL;
|
||||
char szHostname[MAXSIZEOFSTR];
|
||||
|
||||
// ** SMS Sender 객체 생성 및 초기화
|
||||
CSmsSender objSmsSender(g_envConfig.szSMSHost, g_envConfig.nSMSPort, g_envConfig.szSMSSendfile);
|
||||
bRet = objSmsSender.Init();
|
||||
if( bRet == false )
|
||||
{
|
||||
LOG(LERR, "Initializing SmsSender Object has failed.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// ** SMS Sender 객체 생성 및 초기화
|
||||
// 2015-06-26 두 번째 파라메터는 더이상 의미가 없다.
|
||||
CArecaWrapper objAreca(g_envConfig.nEventLevel);
|
||||
if( objAreca.InitArecaControllers() < 0 )
|
||||
{
|
||||
LOG(LERR, "Initializing Areca RAID Controller has failed.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// ** EventDataManager 객체 생성 및 초기화
|
||||
CEventDataManager objDataManager;
|
||||
bRet = objDataManager.Init();
|
||||
if( bRet == false )
|
||||
{
|
||||
LOG(LERR, "Initializing SmsSender Object has failed.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// ** Raid Event Monitor 객체 생성 및 초기화
|
||||
|
||||
// ** UDP Listener 객체 생성 및 초기화
|
||||
CUdpListener udpObj(&objDataManager);
|
||||
// report thread port :
|
||||
bRet = udpObj.Init(g_envConfig.nReportPort);
|
||||
|
||||
if( bRet == false )
|
||||
{
|
||||
LOG(LERR, "Initializing UdpListener Object has failed.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
udpObj.Start();
|
||||
|
||||
// 현재 hostname
|
||||
// hostname이 변경되면 반영되지 않는다. 반영이 꼭필요하다면 while구문 안으로 넣으면 된다.
|
||||
if( ::gethostname(szHostname, MAXSIZEOFSTR) < 0 )
|
||||
{
|
||||
_LOG(LWAR, "gethostname failed. : %s", szHostname);
|
||||
::snprintf(szHostname, MAXSIZEOFSTR, "%s", "error.hostname.com");
|
||||
}
|
||||
nFailCnt = 0;
|
||||
while( 1 )
|
||||
{
|
||||
list<CEventData> listRet;
|
||||
|
||||
if( objAreca.GetEvent(GET_EVENT_ALL, listRet) == false )
|
||||
{
|
||||
if( nFailCnt < 3 )
|
||||
{
|
||||
nFailCnt++;
|
||||
_LOG(LWAR, "Get RAID Event Data Failed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LERR, "Get RAID Event Data Failed. %d(th). Send SMS.",nFailCnt);
|
||||
nFailCnt = 0;
|
||||
|
||||
// 현재 시각 설정
|
||||
time((time_t *)<ime);
|
||||
pTm = ::localtime((time_t *)<ime);
|
||||
::memset(szTime, 0, sizeof(szTime));
|
||||
::snprintf(szTime, MAXSIZEOFSTR, "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d",
|
||||
pTm->tm_year+1900, pTm->tm_mon +1, pTm->tm_mday,
|
||||
pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
|
||||
|
||||
objSmsSender.SendToWebServ(szHostname, szTime ,"Can NOT Receive Data From RAID Controller!");
|
||||
}
|
||||
sleep(g_envConfig.nCheckTerm);
|
||||
continue;
|
||||
}
|
||||
nFailCnt = 0; // 성공하면 실패 카운트를 리셋한다.
|
||||
|
||||
// 받아온 Raid Event 저장
|
||||
bRet = objDataManager.SetCurrentData(listRet);
|
||||
if( bRet == false )
|
||||
{
|
||||
LOG(LERR, "SetCurrentData Failed. but it's Impossible. Check ArecaWrapper::GetEvent().");
|
||||
sleep(g_envConfig.nCheckTerm);
|
||||
continue;
|
||||
}
|
||||
// SMS 전송 목록
|
||||
listRet.clear();
|
||||
bRet = objDataManager.GetSmsEvent(listRet);
|
||||
if( bRet == false )
|
||||
{
|
||||
LOG(LERR, "GetSmsEvent() failed.");
|
||||
sleep(g_envConfig.nCheckTerm);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
for (list<CEventData>::iterator it=listRet.begin(); it!=listRet.end(); it++)
|
||||
{
|
||||
// NEW 2019-09-16 huibong 불필요 "Battery Module Failed" event 는 전송하지 않는다. (#32795)
|
||||
// - "Battery Module Failed" event 는 운영자가 수신해도 할 작업이 없음
|
||||
// - 하지만 일 10~20 건 정도가 발생하여 운영자에게 불필요 event 가 전달됨
|
||||
// - 이와 관련 KT 운영팀 윤철희 실장이 해당 event 는 무시하도록 처리해 달라고 해서...
|
||||
// - 해당 메시지 발생시 운영자에게 event 전송하지 않도록 한다.
|
||||
// - 실제로 CEventDataManager 모듈에서도 처리가능하지만...
|
||||
// - 본 모듈에서 실제 event 전송을 담당하므로.. 본 모듈에서 무시 처리하도록 수정함.
|
||||
// BUG 2020-01-10 huibong 불필요 "Battery Module Failed" event 미전송 관련 버그 수정 (#32911)
|
||||
// - 실제로 Module 단어와 Failed 단어 사이에 공백이 3개 존재
|
||||
// - 이로 인해 해당 event 가 계속 전송되는 상황 발견됨
|
||||
// - 이에 Battery Module" check 후 Failed 문자열 check 하도록 수정
|
||||
std::string::size_type find_result;
|
||||
find_result = it->m_szEventData.find( "Battery Module" );
|
||||
if( find_result != std::string::npos )
|
||||
{
|
||||
find_result = it->m_szEventData.find( "Fail" );
|
||||
if( find_result != std::string::npos )
|
||||
{
|
||||
_LOG( LDBG, "Do not send event with operator requests [%s]", it->m_szEventData.c_str() );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pTm = ::localtime(&(it->m_evtTime));
|
||||
::memset(szTime, 0, sizeof(szTime));
|
||||
::snprintf(szTime, MAXSIZEOFSTR, "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d",
|
||||
pTm->tm_year+1900, pTm->tm_mon +1, pTm->tm_mday,
|
||||
pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
|
||||
_LOG(LWAR, "SMS Sent.[%s::%s:%s]",szHostname, szTime, it->m_szEventData.c_str());
|
||||
//FIXME:호출하면 SMS가 발송된다... :많은사람에게 문자가 수신되므로 디버깅 때는 가급적 자제할것. please........
|
||||
objSmsSender.SendToWebServ(szHostname, szTime ,it->m_szEventData.c_str());
|
||||
|
||||
/// 2011.07.26, 수정자 : 장희준
|
||||
/// 업로드 자동 방지
|
||||
CAutoDisableUpload autoDisableUpload;
|
||||
autoDisableUpload.DoProcess( it->GetEventCategory(), it->GetEventId() );
|
||||
}
|
||||
sleep(g_envConfig.nCheckTerm);
|
||||
}
|
||||
|
||||
|
||||
// wait
|
||||
while(1)
|
||||
{
|
||||
// 그냥 시그널 대기
|
||||
pause();
|
||||
}
|
||||
|
||||
//잠시 대기 후 종료처리.
|
||||
usleep(500000);
|
||||
// exit( EXIT_SUCCESS );
|
||||
return EXIT_SUCCESS; // fork 를 수행한 함수에서 exit 함수 호출을 통한 종료처리
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/***************************************************************************
|
||||
fhs_raidmond Header ( Child.h )
|
||||
-----------------------------------------
|
||||
begin : 2010/03/09
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __CHILD_PROCESS_H__
|
||||
#define __CHILD_PROCESS_H__
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// @brief Child Process ÀÇ main ÇÔ¼ö
|
||||
/// @return
|
||||
int ChildMain( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CHILD_PROCESS_H__ */
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#define MaxRTTime 5
|
||||
#define MaxRecvBuffSize (20 * 1024)
|
||||
|
||||
void handleAlarm(int signal)
|
||||
{
|
||||
return; // just return and interupt.
|
||||
}
|
||||
|
||||
|
||||
// main function
|
||||
int main( int argc, char * argv[] )
|
||||
{
|
||||
if(argc != 4)
|
||||
{
|
||||
cerr << PROG_NAME << " Version :" << PROG_VERSION << endl;
|
||||
cerr << "Usage: " << PROG_NAME << " server-ip port mode" << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
static bool success = false;
|
||||
// parse command line arguments
|
||||
string host = argv[1];
|
||||
int port = atoi(argv[2]);
|
||||
string mode = argv[3];
|
||||
|
||||
//cout << "arguments : " << host << "," << port << "," << mode << endl;
|
||||
|
||||
int r = -1;
|
||||
struct sockaddr_in cliaddr;
|
||||
int addr_len = sizeof(cliaddr);
|
||||
char recvbuf[MaxRecvBuffSize];
|
||||
string result;
|
||||
|
||||
// socket initialize
|
||||
int s = -1;
|
||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if(s < 0)
|
||||
{
|
||||
cerr << "Socket Create: errno:" << errno << " errmsg:" << strerror(errno) << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = MaxRTTime;
|
||||
timeout.tv_usec = 0;
|
||||
int optlen = sizeof(timeout);
|
||||
|
||||
int errtimeout = -1;
|
||||
if( setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (void*)&timeout, (socklen_t)optlen) < 0)
|
||||
{
|
||||
struct sigaction sigact, oldact;
|
||||
sigact.sa_handler = handleAlarm;
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigact.sa_flags = 0;
|
||||
#ifdef SA_INTERRUPT
|
||||
sigact.sa_flags |= SA_INTERRUPT;
|
||||
#endif // SA_INTERRUPT
|
||||
if(sigaction(SIGALRM, &sigact, &oldact) < 0)
|
||||
{
|
||||
cerr << "sigaction error: errno:" << errno << " errmsg:" << strerror(errno) << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
errtimeout = EINTR;
|
||||
}
|
||||
else
|
||||
errtimeout = EAGAIN;
|
||||
|
||||
struct sockaddr_in SocAddr;
|
||||
|
||||
SocAddr.sin_family = AF_INET;
|
||||
SocAddr.sin_port = htons(port);
|
||||
//SocAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
if (inet_aton(host.c_str(), &SocAddr.sin_addr)==0)
|
||||
{
|
||||
cerr << "inet_aton() failed: errno:" << errno << " errmsg:" << strerror(errno) << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// send
|
||||
int len = mode.length();
|
||||
if( sendto( s, mode.c_str(), mode.length(), 0, (struct sockaddr *)&SocAddr, sizeof(SocAddr) ) != len)
|
||||
{
|
||||
cerr << "sendto error : errno :"<< errno << " errmg:" << strerror(errno) << endl;
|
||||
goto GOTO_END;
|
||||
}
|
||||
|
||||
if( errtimeout == EINTR )
|
||||
{
|
||||
alarm(MaxRTTime);
|
||||
}
|
||||
|
||||
// receive
|
||||
do
|
||||
{
|
||||
memset(recvbuf, 0, MaxRecvBuffSize);
|
||||
r = recvfrom( s, (char *)&recvbuf, (unsigned int)MaxRecvBuffSize, 0, (struct sockaddr *)&cliaddr, (socklen_t *)&addr_len );
|
||||
//cerr << "nREAD = " << r << "," << errno << endl;
|
||||
|
||||
if(r >= 0)
|
||||
result += recvbuf;
|
||||
else
|
||||
{
|
||||
if( errno == errtimeout ) // timeout
|
||||
{
|
||||
cerr << "3:" << (long)time(NULL) << ":Disabled" << endl;
|
||||
goto GOTO_END;
|
||||
}
|
||||
}
|
||||
|
||||
} while (r <= 0);
|
||||
|
||||
cout << result << endl;
|
||||
|
||||
if (result.size())
|
||||
success = true;
|
||||
|
||||
GOTO_END:
|
||||
close(s);
|
||||
|
||||
return success ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/***************************************************************************
|
||||
Areca Library Event Data Class
|
||||
-----------------------------------------
|
||||
begin : 2010/05/21
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __EVENT_DATA__
|
||||
#define __EVENT_DATA__
|
||||
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
|
||||
/// @brief CEventData
|
||||
/// EventData 는 Areca library로부터 받아오는 raid event 정보를 저장한다.
|
||||
/// 내부적으로 Thread를 사용하고있다.
|
||||
class CEventData
|
||||
{
|
||||
private:
|
||||
int m_nEventCategory;
|
||||
int m_nEventId;
|
||||
|
||||
public:
|
||||
/// @brief Areca Library에서 얻어온 데이터의 시간값을 저장한다.
|
||||
time_t m_evtTime;
|
||||
std::string m_szEventData;
|
||||
|
||||
public:
|
||||
/// @brief 생성자
|
||||
CEventData(){};
|
||||
|
||||
/// @brief 소멸자
|
||||
~CEventData(){};
|
||||
|
||||
inline void SetEventType( int eventCategory, int evnetId )
|
||||
{
|
||||
m_nEventCategory = eventCategory;
|
||||
m_nEventId = evnetId;
|
||||
}
|
||||
|
||||
inline int GetEventCategory() { return m_nEventCategory; };
|
||||
inline int GetEventId() { return m_nEventId; };
|
||||
|
||||
/// @brief Areca Library에서 얻어온 이벤트 데이터를 저장한다.
|
||||
///< 데이터의 형태로 반복여부를 확인하여 중복 반복시 최초 1개의 데이터만을 알림하도록 설계되었다.
|
||||
|
||||
inline bool operator==(const CEventData& t)
|
||||
{
|
||||
return ( (t.m_evtTime == m_evtTime) && (t.m_szEventData == m_szEventData) );
|
||||
}
|
||||
};
|
||||
#endif // __EVENT_DATA__
|
||||
@@ -0,0 +1,163 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "EventDataManager.h"
|
||||
#include <stdlib.h>
|
||||
#include <algorithm>
|
||||
|
||||
#define REPEAT_ALLOW_TIME 60*60
|
||||
|
||||
|
||||
// 생성자
|
||||
CEventDataManager::CEventDataManager()
|
||||
{
|
||||
pthread_mutex_init(&m_mutex, NULL);
|
||||
}
|
||||
|
||||
// 소멸자
|
||||
CEventDataManager::~CEventDataManager()
|
||||
{
|
||||
pthread_mutex_destroy(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
bool CEventDataManager::Init(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CEventDataManager::GetAllData(list<CEventData>& listRet)
|
||||
{
|
||||
pthread_mutex_lock( &m_mutex );
|
||||
// SetCurrentData가 정상적으로 동작하였다면, m_Old.size()의 조건에 걸릴 수 없다.
|
||||
if ( m_Current.size() < 1 || m_Old.size() < 1 )
|
||||
{
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
_LOG(LINF, "Data have Nothing.");
|
||||
return false;
|
||||
}
|
||||
|
||||
listRet = m_Current;
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
return true;
|
||||
}
|
||||
|
||||
int CEventDataManager::GetLatestData( CEventData& resData )
|
||||
{
|
||||
pthread_mutex_lock( &m_mutex );
|
||||
// SetCurrentData가 정상적으로 동작하였다면, m_Old.size()의 조건에 걸릴 수 없다.
|
||||
if ( m_Current.size() < 1 || m_Old.size() < 1 )
|
||||
{
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
_LOG(LINF, "Data have Nothing.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if( m_Old.back().m_evtTime == m_Current.back().m_evtTime )
|
||||
{ // ( 과거와 현재 최종 이벤트 시각이 동일하면 변화가 없는 것이다. )
|
||||
resData = m_Current.back();
|
||||
resData.m_szEventData = "NO EVENT";
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 과거와 현재 최종 이벤트 시각이 다르면 이벤트가 추가된 것이다.
|
||||
resData = m_Current.back();
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool CEventDataManager::SetCurrentData(list<CEventData>& listRet)
|
||||
{
|
||||
pthread_mutex_lock( &m_mutex );
|
||||
if( listRet.empty() )
|
||||
{
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
_LOG(LINF, "EventData is empty.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 들어온 데이터는 모두 시간순으로 정렬한다. (오름차순)
|
||||
// Old 데이터를 지운다.
|
||||
m_Old.clear();
|
||||
//현재 값이 비어있을 경우 (최초 실행으로 간주함)
|
||||
if( m_Current.empty() == true)
|
||||
{
|
||||
m_Old = listRet;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Old = m_Current;
|
||||
}
|
||||
m_Current = listRet;
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEventDataManager::GetSmsEvent(list<CEventData>& listRet)
|
||||
{
|
||||
CEventData fetchedData;
|
||||
CEventData lastDataOfOld;
|
||||
list<CEventData> eventData = m_Current;
|
||||
list<CEventData> listFindTemp;
|
||||
|
||||
pthread_mutex_lock( &m_mutex );
|
||||
|
||||
if( m_Current.size() == 0 )
|
||||
{
|
||||
LOG(LERR, "List have No Data");
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
return false;
|
||||
}
|
||||
// 과거의 최신 데이터를 저장한다.
|
||||
m_SentOld = m_Old.back();
|
||||
// 현재 리스트의 뒤쪽(최신)부터 동일 데이터를 찾는다.
|
||||
// (데이터에 시간 값이 포함되어 있기 때문에 완전히 동일한 데이터는 없는 것으로 간주한다.)
|
||||
// (있을 경우 무시해도 되지 않을까?)
|
||||
|
||||
listFindTemp.push_back(m_SentOld);
|
||||
// find_end를 사용하기 위해서 원소가 1개인 리스트를 생성한다.
|
||||
list<CEventData>::iterator it = find_end(m_Current.begin(), m_Current.end(), listFindTemp.begin(), listFindTemp.end());
|
||||
// 뒤쪽부터 원소가 1개인 리스트(listFindTemp)를 찾는다.
|
||||
// find_end()는 집합에 속하는 부분집합을 찾는다.
|
||||
|
||||
|
||||
// 찾아낸 데이터의 뒤쪽 부분은 신규 데이터이다.
|
||||
if( it == m_Current.end() )
|
||||
{ // end()와 같다면, 끝까지 찾지 못한 것을 의미한다. (NOT FOUND)
|
||||
// 찾지 못한 것은 전체가 다 새로운 것이다.
|
||||
_LOG(LINF, "List has NEW Event perfectly.");
|
||||
it = m_Current.begin();
|
||||
}
|
||||
else
|
||||
{ // 찾아낸 데이터의 다음 데이터를 가리키도록 한다.
|
||||
++it;
|
||||
}
|
||||
|
||||
// 신규 데이터 목록 중 앞쪽(오래된)부터 중복된 데이터인지를 검사한다.
|
||||
for( ; it != m_Current.end(); it++)
|
||||
{
|
||||
if( it->m_szEventData == m_SentOld.m_szEventData
|
||||
&& it->m_evtTime - m_SentOld.m_evtTime < REPEAT_ALLOW_TIME
|
||||
&& it->m_evtTime - m_SentOld.m_evtTime >= 0 )
|
||||
{ // 내용이 중복되고 마지막 이벤트로부터 1시간 미만 차이나면?
|
||||
// BUG: Areca bug로 시간이 역순할 수 있다. REPEAT_ALLOW_TIME보다 작은 음수 값이 나오게 되면 무시하면 안된다.
|
||||
_LOG(LINF, "There is Repeted Event.[%s]",it->m_szEventData.c_str());
|
||||
// 중복 되면 버린다.(과거 데이터를 우선한다)
|
||||
continue;
|
||||
}
|
||||
|
||||
// 중복 데이터가 아니면 결과에 추가 한다.(SMS발송 대상)
|
||||
listRet.push_back(*it);
|
||||
m_SentOld = *it;
|
||||
_LOG(LDBG, "ADD : [%lu::%s]", it->m_evtTime, it->m_szEventData.c_str());
|
||||
}
|
||||
// SMS발송 대상이 없을 경우 디버깅 로그만 남긴다.
|
||||
if( listRet.size() == 0 )
|
||||
{
|
||||
LOG(LDBG, "There is No New Event.");
|
||||
}
|
||||
pthread_mutex_unlock( &m_mutex );
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/***************************************************************************
|
||||
SMS Raid Event Data Manager Class
|
||||
-----------------------------------------
|
||||
begin : 2010/05/24
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __EVENT_DATA_MANAGER__
|
||||
#define __EVENT_DATA_MANAGER__
|
||||
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
#include "Logger.h"
|
||||
#include "EventData.h"
|
||||
#include <list>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/// @brief CEventDataManager
|
||||
/// EventDataManager 는 Areca library로부터 받아오는 raid event 정보를 저장한다.
|
||||
class CEventDataManager
|
||||
{
|
||||
public:
|
||||
/// @brief 생성자
|
||||
CEventDataManager();
|
||||
|
||||
/// @brief 소멸자
|
||||
~CEventDataManager();
|
||||
|
||||
//TODO:
|
||||
bool Init();
|
||||
bool SetCurrentData(list<CEventData>& listRet);
|
||||
bool GetSmsEvent(list<CEventData>& listRet);
|
||||
int GetLatestData( CEventData& resData );
|
||||
bool GetAllData(list<CEventData>& listRet);
|
||||
private:
|
||||
// TODO:
|
||||
list<CEventData> m_Current;
|
||||
list<CEventData> m_Old;
|
||||
CEventData m_SentOld;
|
||||
|
||||
pthread_mutex_t m_mutex;
|
||||
|
||||
};
|
||||
#endif // __EVENT_DATA_MANAGER__
|
||||
@@ -0,0 +1,189 @@
|
||||
#include "fhs_raidmond.h"
|
||||
#include "Config.h"
|
||||
#include "GetConfig.h"
|
||||
|
||||
/// @brief config value chech
|
||||
/// @param szValue [in] value
|
||||
/// @param conf [in] Config 객체
|
||||
/// @param defsection [in] default section
|
||||
/// @param defkey [in] default key
|
||||
/// @return 성공시 true, 오류 발생시 false 를 반환.
|
||||
static bool CheckValue(std::string& szValue, Config& conf, const std::string& defsection, const std::string& defkey)
|
||||
{
|
||||
if( szValue.size() > 0 )
|
||||
return true;
|
||||
|
||||
if( defsection.size() <= 0 || defkey.size() <= 0 )
|
||||
return false;
|
||||
|
||||
conf.GetConfig( defsection, defkey, szValue );
|
||||
|
||||
if( szValue.size() > 0 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool GetConfig( const std::string& szConfFile, struct st_config& stConfig, std::string& errorMessage )
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
// Config 처리를 위한 객체 생성
|
||||
Config conf;
|
||||
|
||||
// Config File open
|
||||
if( conf.Open( szConfFile) == false )
|
||||
{
|
||||
errorMessage = "Config file open failed.[" + szConfFile + "]";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string szValue;
|
||||
szValue.clear();
|
||||
|
||||
// log path
|
||||
if( conf.GetConfig( PROG_NAME, "DEFAULT_LOG_DIR", szValue ) == false )
|
||||
{
|
||||
if( !CheckValue(szValue, conf, "COMMON", "DEFAULT_LOG_DIR") )
|
||||
{
|
||||
errorMessage = "Config info get failed. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->LOG_DIR";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
stConfig.szLogDir = szValue;
|
||||
|
||||
szValue.clear();
|
||||
// log level
|
||||
if( conf.GetConfig( PROG_NAME, "LOG_LEVEL", szValue ) == false )
|
||||
{
|
||||
if( !CheckValue(szValue, conf, "COMMON", "LOG_LEVEL") )
|
||||
{
|
||||
errorMessage = "Config info get failed. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->LOG_LEVEL";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
stConfig.nLogLevel = atoi(szValue.c_str());
|
||||
|
||||
szValue.clear();
|
||||
// check term
|
||||
if( conf.GetConfig( PROG_NAME, "HEALTH_CHECK_TERM", szValue ) == false )
|
||||
{
|
||||
errorMessage = "Config info get failed. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->HEALTH_CHECK_TERM";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !CheckValue(szValue, conf, "", "") )
|
||||
{
|
||||
errorMessage = "Config info get empty. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->HEALTH_CHECK_TERM";
|
||||
return false;
|
||||
}
|
||||
stConfig.nCheckTerm = atoi(szValue.c_str());
|
||||
|
||||
szValue.clear();
|
||||
// report port
|
||||
if( conf.GetConfig( PROG_NAME, "REPORT_THREAD_PORT", szValue ) == false )
|
||||
{
|
||||
errorMessage = "Config info get failed. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->REPORT_THREAD_PORT";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !CheckValue(szValue, conf, "", "") )
|
||||
{
|
||||
errorMessage = "Config info get empty. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->REPORT_THREAD_PORT";
|
||||
return false;
|
||||
}
|
||||
stConfig.nReportPort = atoi(szValue.c_str());
|
||||
|
||||
szValue.clear();
|
||||
//event level
|
||||
if( conf.GetConfig( PROG_NAME, "EVENT_LEVEL", szValue ) == false )
|
||||
{
|
||||
errorMessage = "Config info get failed. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->EVENT_LEVEL";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !CheckValue(szValue, conf, "", "") )
|
||||
{
|
||||
errorMessage = "Config info get empty. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->EVENT_LEVEL";
|
||||
return false;
|
||||
}
|
||||
stConfig.nEventLevel = atoi(szValue.c_str());
|
||||
szValue.clear();
|
||||
//sms send host
|
||||
if( conf.GetConfig( PROG_NAME, "SMS_SEND_HOST", szValue ) == false )
|
||||
{
|
||||
errorMessage = "Config info get failed. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->SMS_SEND_HOST";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !CheckValue(szValue, conf, "", "") )
|
||||
{
|
||||
errorMessage = "Config info get empty. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->SMS_SEND_HOST";
|
||||
return false;
|
||||
}
|
||||
stConfig.szSMSHost = szValue;
|
||||
|
||||
szValue.clear();
|
||||
//sms send port
|
||||
if( conf.GetConfig( PROG_NAME, "SMS_SEND_PORT", szValue ) == false )
|
||||
{
|
||||
errorMessage = "Config info get failed. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->SMS_SEND_HOST";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !CheckValue(szValue, conf, "", "") )
|
||||
{
|
||||
errorMessage = "Config info get empty. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->SMS_SEND_PORT";
|
||||
return false;
|
||||
}
|
||||
stConfig.nSMSPort = atoi(szValue.c_str());
|
||||
|
||||
szValue.clear();
|
||||
//sms send file
|
||||
if( conf.GetConfig( PROG_NAME, "SMS_SEND_URI", szValue ) == false )
|
||||
{
|
||||
errorMessage = "Config info get failed. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->SMS_SEND_FILE";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !CheckValue(szValue, conf, "", "") )
|
||||
{
|
||||
errorMessage = "Config info get empty. [";
|
||||
errorMessage += PROG_NAME;
|
||||
errorMessage += "]->SMS_SEND_FILE";
|
||||
return false;
|
||||
}
|
||||
stConfig.szSMSSendfile = szValue;
|
||||
szValue.clear();
|
||||
ret = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/***************************************************************************
|
||||
rc_rmcd ( File Replication & Cache Control Daemon ) Header ( GetConfig.h )
|
||||
-----------------------------------------
|
||||
begin : 2010/03/03
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __GET_CONFIG_H__
|
||||
#define __GET_CONFIG_H__
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// @brief config file parsing and save to stConfig function
|
||||
/// @param szConfFile [in] Conf 파일에 대한 경로 및 파일 정보
|
||||
/// @param stConfig [out] Conf 파일의 정보를 저장하기 위한 st_config 참조변수
|
||||
/// @param errorMessage [out] 오류발생시 해당 오류 정보를 저장하여 반환하기 위한 참조변수
|
||||
/// @return 성공시 true, 오류 발생시 false 를 반환. 상세한 오류 정보는 errorMessage 변수에 저장됨.
|
||||
bool GetConfig( const std::string& szConfFile, struct st_config& stConfig, std::string& errorMessage);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __GET_CONFIG_H__ */
|
||||
@@ -0,0 +1,87 @@
|
||||
#****************************************************************************
|
||||
# Makefile for Arcmond
|
||||
# -----------------------------------------
|
||||
#
|
||||
# begin : 2010/05/17
|
||||
# copyright : (C) 2005 SolutionBox Inc.
|
||||
# author : Service 1 Team
|
||||
# email : svc1@solbox.com
|
||||
# version : 3.0.0
|
||||
#
|
||||
# CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
# Redistribution and use in source and binary forms, with or with out
|
||||
# modification, are not permitted in outside of SolutionBox Inc.
|
||||
#*****************************************************************************
|
||||
|
||||
# Program info
|
||||
PROG_NAME = arcmond
|
||||
PROG_NAME_C = arcmond_client
|
||||
#REVISION = `svnversion -n .`
|
||||
REVISION = 1507
|
||||
BUILD_DATE = `date +%Y%m%d%H%M%S`
|
||||
PROG_VERSION = 3.5.0.$(REVISION)-$(BUILD_DATE)
|
||||
DEFAULT_CONFIG_FILE = /user/service/etc/util.conf
|
||||
INSTALL_BIN = /user/service/bin
|
||||
OSBITS := $(shell getconf LONG_BIT)
|
||||
|
||||
# Compiler info
|
||||
CC = /usr/bin/g++
|
||||
|
||||
CFLAGS = -Wall -O3 -g -Wreturn-type -Wunused -Wuninitialized \
|
||||
-Wparentheses -Wshadow -Wpointer-arith -Woverloaded-virtual\
|
||||
-fno-rtti -D_REENTRANT -Wno-unused -Wno-non-virtual-dtor
|
||||
|
||||
LFLAGS = -lpthread
|
||||
|
||||
# DEBUG or RELEASE Mode select
|
||||
#DFLAGS = -D_DEBUG_ -DPROG_NAME=\"$(PROG_NAME)\" -DPROG_VERSION=\"$(PROG_VERSION)\" -DDEFAULT_CONFIG_FILE=\"$(DEFAULT_CONFIG_FILE)\"
|
||||
DFLAGS = -DPROG_NAME=\"$(PROG_NAME)\" -DPROG_VERSION=\"$(PROG_VERSION)\" -DDEFAULT_CONFIG_FILE=\"$(DEFAULT_CONFIG_FILE)\"
|
||||
|
||||
|
||||
# Application Enviroment
|
||||
APP = $(PROG_NAME)
|
||||
|
||||
DIR_INCLUDE = -I./. -I../lib -I ../external/include #-I /user/db/pgsql/include -I../
|
||||
DIR_LIB = -L../lib -L../external/bin/
|
||||
|
||||
OBJ = GetConfig.o Child.o main.o ArecaWrapper.o UdpListener.o SmsSender.o EventDataManager.o AutoDisableUpload.o
|
||||
|
||||
LIBS = ../lib/libInterCommon.a ../external/bin/libarclib${OSBITS}.a
|
||||
|
||||
ifeq ($(CLIENT), yes)
|
||||
PROG_NAME = $(PROG_NAME_C)
|
||||
OBJ = Client.o
|
||||
LIBS =
|
||||
endif
|
||||
|
||||
############################
|
||||
|
||||
all:$(APP)
|
||||
#rm -f main.o
|
||||
sync
|
||||
|
||||
%.o: %.cpp
|
||||
$(CC) $(CFLAGS) -o $@ -c $^ $(DFLAGS) $(DIR_INCLUDE)
|
||||
|
||||
test: $(OBJ)
|
||||
$(CC) $(LFLAGS) -o $@ -c $^ $(DFLAGS) $(DIR_INCLUDE)
|
||||
|
||||
$(PROG_NAME): $(OBJ)
|
||||
$(CC) $(LFLAGS) -o $@ $^ $(DFLAGS) $(DIR_LIB) $(LIBS)
|
||||
|
||||
tael: $(OBJ) SmsSender.o
|
||||
$(CC) $(LFLAGS) -o $@ $^ $(DFLAGS) $(DIR_LIB) $(LIBS)
|
||||
client:
|
||||
$(MAKE) CLIENT="yes"
|
||||
|
||||
clean:
|
||||
-rm -f *.o core *.out *.log
|
||||
-rm -f $(APP)
|
||||
sync
|
||||
|
||||
|
||||
install : $(APP)
|
||||
-cp $(APP) $(INSTALL_BIN)/$(APP)
|
||||
sync
|
||||
|
||||
# End of Makefile
|
||||
@@ -0,0 +1,256 @@
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "SmsSender.h"
|
||||
#include <iterator>
|
||||
|
||||
#define DEFAULT_BUFFER_SIZE 9216
|
||||
#define MaxSizeOfTRxBuffer 1024
|
||||
|
||||
|
||||
string CSmsSender::RemoveBlankSpace(const char* pszData, size_t nLength)
|
||||
{
|
||||
char * szTemp = NULL;
|
||||
string strReturn;
|
||||
const char * src;
|
||||
char * dest;
|
||||
|
||||
|
||||
szTemp = (char*) ::malloc(sizeof(char) * nLength +1);
|
||||
::memset(szTemp, 0 , sizeof(char)*nLength +1);
|
||||
|
||||
src = pszData;
|
||||
dest = szTemp;
|
||||
|
||||
if( pszData == NULL )
|
||||
{
|
||||
strReturn.clear();
|
||||
return strReturn;
|
||||
}
|
||||
|
||||
if( *src == '\0' )
|
||||
{
|
||||
strReturn = src;
|
||||
return strReturn;
|
||||
}
|
||||
// start with 2nd position
|
||||
src++;
|
||||
while ( src <= (pszData + nLength) && *(src-1) != '\0' )
|
||||
{
|
||||
if( *(src-1) == ' ' && *(src) == ' ' )
|
||||
{ // 연속된 공백이 발견되면, 스킵한다.
|
||||
src++;
|
||||
continue;
|
||||
}
|
||||
*dest = *(src-1);
|
||||
src++;
|
||||
dest++;
|
||||
}
|
||||
// 종료표기
|
||||
dest++;
|
||||
*(dest) = '\0';
|
||||
|
||||
strReturn = szTemp;
|
||||
if (szTemp != NULL)
|
||||
{
|
||||
free(szTemp);
|
||||
szTemp = NULL;
|
||||
}
|
||||
return strReturn;
|
||||
}
|
||||
char hexchars[] = "0123456789ABCDEF";
|
||||
string CSmsSender::PostDataEncode(const char *pszCommand, size_t length)
|
||||
{
|
||||
int i;
|
||||
char tmpBuffer[MaxSizeOfTRxBuffer];
|
||||
string strReturn;
|
||||
|
||||
if( pszCommand == NULL )
|
||||
{
|
||||
strReturn.clear();
|
||||
return strReturn;
|
||||
}
|
||||
|
||||
::memset(tmpBuffer, 0 , MaxSizeOfTRxBuffer);
|
||||
i = 0;
|
||||
while( *pszCommand != '\0' )
|
||||
{
|
||||
if( *pszCommand == ' ' )
|
||||
{ // ' ' => '+'
|
||||
tmpBuffer[i++] = '+';
|
||||
pszCommand++;
|
||||
}
|
||||
else if(*pszCommand == '%')
|
||||
{ // % => %%
|
||||
tmpBuffer[i++] = '%';
|
||||
tmpBuffer[i++] = '%';
|
||||
pszCommand++;
|
||||
}
|
||||
else if( (*pszCommand < '0' && *pszCommand != '-' && *pszCommand != '.' )
|
||||
|| (*pszCommand < 'A' && *pszCommand > '9' )
|
||||
|| (*pszCommand > 'Z' && *pszCommand < 'a' && *pszCommand != '_' )
|
||||
|| (*pszCommand > 'z' ) )
|
||||
{
|
||||
tmpBuffer[i++] = '%';
|
||||
tmpBuffer[i++] = hexchars[(unsigned char)*pszCommand >> 4];
|
||||
tmpBuffer[i++] = hexchars[(unsigned char)*pszCommand & 15];
|
||||
pszCommand++;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpBuffer[i++] = *pszCommand++;
|
||||
}
|
||||
}
|
||||
tmpBuffer[i] = '\0';
|
||||
|
||||
strReturn = tmpBuffer;
|
||||
return strReturn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CSmsSender::CSmsSender(const std::string& szHost, const int nPort, const std::string& szPath)
|
||||
: CBaseSocket( SOCKET_NOT_VALID), m_szHost(szHost), m_nPort(nPort), m_szPath(szPath)
|
||||
{
|
||||
// 생성자
|
||||
}
|
||||
|
||||
CSmsSender::~CSmsSender()
|
||||
{
|
||||
// 소멸자에 BaseSocket의 명시적 Close 처리를 한다.
|
||||
Close();
|
||||
}
|
||||
|
||||
bool CSmsSender::Init(void)
|
||||
{
|
||||
bool bRet = false;
|
||||
|
||||
// 데이터 체크
|
||||
if( m_szHost.empty() || m_nPort < 0 || m_szPath.empty() )
|
||||
{
|
||||
LOG(LERR, "Invalid Parameter.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSmsSender::SendToWebServ(const string& pszHost, const string& pszTime, const string& pszMsg)
|
||||
{
|
||||
string szHost;
|
||||
string szTime;
|
||||
string szMsg;
|
||||
char szSndBuffer[DEFAULT_BUFFER_SIZE];
|
||||
char szRcvBuffer[DEFAULT_BUFFER_SIZE];
|
||||
bool bRet = false;
|
||||
int nRet = 0;
|
||||
|
||||
|
||||
if( pszHost.empty() || pszMsg.empty() || pszTime.empty() )
|
||||
{
|
||||
LOG(LERR, "Invalid Parameter.");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Connect
|
||||
bRet = Connect(m_szHost, m_nPort);
|
||||
if( bRet == false )
|
||||
{
|
||||
LOG(LERR, "Socket Connect Error.[%s:%d]", m_szHost.c_str(), m_nPort);
|
||||
return false;
|
||||
}
|
||||
if( IsValidSocket() == false )
|
||||
{
|
||||
LOG(LERR, "Invalid Socket.");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
::bzero(szSndBuffer, DEFAULT_BUFFER_SIZE);
|
||||
::bzero(szRcvBuffer, DEFAULT_BUFFER_SIZE);
|
||||
|
||||
szHost = PostDataEncode(pszHost.c_str(), pszHost.size());
|
||||
szTime = PostDataEncode(pszTime.c_str(), pszTime.size());
|
||||
szMsg = RemoveBlankSpace(pszMsg.c_str(), pszMsg.size());
|
||||
LOG(LDBG, "SMSMsg = [%s]", szMsg.c_str());
|
||||
szMsg = PostDataEncode(szMsg.c_str(), szMsg.size());
|
||||
|
||||
|
||||
// CHG 2019-09-16 huibong HTTP 관련 줄바꿈문자 LF->CR+LF 변경 (#32794)
|
||||
// - CVE-2016-8743 이슈에 따라 Apache 2.2.32 버전부터 HTTP header 상에서
|
||||
// - 줄바꿈문자가 CR+LF 가 아닌 경우 HTTP 400 응답 발생
|
||||
// - 이를 해결하기 위해 기존 줄바꿈 문자 \n -> \r\n 으로 변경처리한다.
|
||||
::snprintf(szSndBuffer, DEFAULT_BUFFER_SIZE, "GET %s?host=%s&time=%s&msg=%s HTTP/1.0\r\n"\
|
||||
"Content-Type: text/plain\r\n"\
|
||||
"User-Agent: Arcmond\r\n"\
|
||||
"Host: %s\r\n"\
|
||||
"Connection: close\r\n"\
|
||||
"Cache-Control: no-cache\r\n\r\n"
|
||||
,m_szPath.c_str(), szHost.c_str(), szTime.c_str(), szMsg.c_str() ,m_szHost.c_str());
|
||||
|
||||
//DEBUG_LOG("%s", szSndBuffer);
|
||||
//요청 전송 시작
|
||||
nRet = WriteN(&szSndBuffer, ::strlen(szSndBuffer)+1);
|
||||
// MAX_SEND_RETRY_COUNT 회수만큼 재시도 후 실패처리된다.
|
||||
if( nRet == 0 )
|
||||
{
|
||||
LOG(LERR, "write socket closed.");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
else if( nRet == -1 )
|
||||
{
|
||||
LOG(LERR, "write socket error.(%s)",strerror(errno));
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 응답 결과 받기.
|
||||
nRet = ReadNTimeout(szRcvBuffer, DEFAULT_BUFFER_SIZE);
|
||||
if( nRet == 0 )
|
||||
{
|
||||
// Remain이 0일 경우가 모두 받은 상황인데, 그것을 알 수 없다면,
|
||||
// Ret==0일 때가 다 준 상황으로 판단해야 하지 않을까? 그렇다면 에러가 아니다.
|
||||
LOG(LDBG, "read socket closed.");
|
||||
}
|
||||
else if( nRet == -1 )
|
||||
{ // 단순 소켓 에러.
|
||||
LOG(LERR, "read socket error.(%s)",strerror(errno));
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
else if( nRet == -2 )
|
||||
{ // 타임아웃.
|
||||
LOG(LERR, "read socket timed out.");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
// 정상 결과는 아래와 같은 형태이다.
|
||||
//----------------------------------------------------------------
|
||||
// HTTP/1.1 200 OK
|
||||
// Date: Thu, 10 Jun 2010 03:59:23 GMT
|
||||
// Server: Apache/2.0.55 (Unix) DAV/2 PHP/5.2.1
|
||||
// X-Powered-By: PHP/5.2.1
|
||||
// Content-Length: 87
|
||||
// Connection: close
|
||||
// Content-Type: text/html; charset=EUC-KR
|
||||
//
|
||||
// [RAID:qcrts4.ktsh.co.kr]::2010-07-09 12:59:19:Controller#1: SW API Interface API Log In
|
||||
//----------------------------------------------------------------
|
||||
|
||||
// 첫번째 라인만 출력하기 위해서 \n을 \0으로 바꾸고 출력한다.
|
||||
char* pEnd = strchr(szRcvBuffer, '\n');
|
||||
*pEnd = '\0';
|
||||
|
||||
LOG(LINF, "Result:%s", szRcvBuffer);
|
||||
|
||||
// Close()는 return값이 없음.
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/***************************************************************************
|
||||
SMS Sender Class
|
||||
-----------------------------------------
|
||||
begin : 2010/05/19
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __SMS_SENDER__
|
||||
#define __SMS_SENDER__
|
||||
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
#include "Logger.h"
|
||||
#include "BaseSocket.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/// @brief CSmsSender
|
||||
/// SmsSender는 지정된 포멧에 따라 php 웹 페이지를 호출한다.
|
||||
///
|
||||
class CSmsSender : public CBaseSocket
|
||||
{
|
||||
public:
|
||||
/// @brief 생성자
|
||||
/// @param [in] szHost SMS 전송 장비 호스트
|
||||
/// @param [in] nPort SMS 전송 장비 접근 Port
|
||||
/// @param [in] szPath SMS 전송 기능이 구현된 PHP 파일명.
|
||||
CSmsSender(const string& szHost, const int nPort, const string& szPath);
|
||||
|
||||
~CSmsSender();
|
||||
|
||||
/// @brief Init 함수 클래스 환경이 정상적인지를 검사한다.
|
||||
/// @return 성공: true, 실패: false
|
||||
bool Init();
|
||||
|
||||
/// @brief PHP Web페이지를 통해 SMS발송 요청을 수행한다.
|
||||
/// @return 성공: true, 실패: false
|
||||
bool CallWebPage();
|
||||
bool SendToWebServ(const string& pszHost, const string& pszTime, const string& pszMsg);
|
||||
|
||||
private:
|
||||
// 로깅 파일
|
||||
string PostDataEncode(const char *pszCommand, size_t length);
|
||||
string RemoveBlankSpace(const char* pszData, size_t nLength);
|
||||
|
||||
string m_szHost;
|
||||
int m_nPort;
|
||||
string m_szPath;
|
||||
string m_szMessage;
|
||||
string m_szGroupId;
|
||||
};
|
||||
#endif // __SMS_SENDER__
|
||||
@@ -0,0 +1,321 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "UdpListener.h"
|
||||
|
||||
#define DEFAULT_BUFFER_SIZE 9216
|
||||
|
||||
#define MaxSizeOfTID 52
|
||||
#define MaxSizeOfIssuer 128
|
||||
#define MaxSizeOfSID 128
|
||||
#define MaxSizeOfRCID 32
|
||||
|
||||
|
||||
int CUdpListener::SendMsg(char * szSndBuffer,int size, struct sockaddr_in * cliaddr, socklen_t nAddrSize)
|
||||
{
|
||||
int SndBlockSize = 8196;
|
||||
char szLineBuffer[SndBlockSize];
|
||||
int nLeft = size;
|
||||
char * pTmp = szSndBuffer;
|
||||
int nWrite = 0;
|
||||
do
|
||||
{
|
||||
int offset = 0;
|
||||
::memset(szLineBuffer, 0, SndBlockSize);
|
||||
if( nLeft < SndBlockSize )
|
||||
SndBlockSize = nLeft;
|
||||
while( offset < SndBlockSize )
|
||||
szLineBuffer[offset++] = *pTmp++;
|
||||
szLineBuffer[offset] = '\0';
|
||||
|
||||
//DEBUG_LOG("LINE : [%s]", szLineBuffer);
|
||||
nWrite = ::sendto(m_nSocket, szLineBuffer, offset + 1, 0, (struct sockaddr *)cliaddr, nAddrSize);
|
||||
if(nWrite < 0)
|
||||
{ // error
|
||||
LOG(LERR, "sendto socket(%d) error (%s)", m_nSocket, strerror(errno));
|
||||
break;
|
||||
}
|
||||
else if(nWrite == 0)
|
||||
{ // socket closed
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LDBG, "SEND MESSAGE %d, %d, %s", nWrite, offset+1, szLineBuffer);
|
||||
}
|
||||
nLeft -= nWrite;
|
||||
} while ( nLeft > 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// @brief 클라이언트로 부터 받아온 스트링 프로토콜을 정수 프로토콜로 변환한다.
|
||||
/// @param [in] szProtocol 클라이언트로부터 전송받은 스트링 프로토콜.
|
||||
/// @return 성공: 양의 정수의 프로토콜 값. 실패: -1
|
||||
int CUdpListener::ParsingPacket(const char * szProtocol)
|
||||
{
|
||||
int nRet = -1;
|
||||
|
||||
if( szProtocol == NULL )
|
||||
{
|
||||
LOG(LERR, "Invalid Parameter");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 구버전 프로토콜을 유지한다.
|
||||
if(strcmp(szProtocol, "I'M YOUR FATHER. BASTARD !") == 0)
|
||||
{
|
||||
LOG(LDBG, "-------- (OLD)CMD_EVENT_INFO_ONE Called!-----------");
|
||||
nRet = CMD_EVENT_INFO_ONE;
|
||||
}
|
||||
else if(strcmp(szProtocol, "I'M YOUR GOD. BASTARD !") == 0)
|
||||
{
|
||||
LOG(LDBG, "-------- (OLD)CMD_EVENT_INFO_ALL Called! ---------");
|
||||
nRet = CMD_EVENT_INFO_ALL;
|
||||
}
|
||||
else if(strcmp(szProtocol, "EVENT:INFO:ONE") == 0)
|
||||
{
|
||||
LOG(LDBG, "-------- CMD_EVENT_INFO_ONE Called!-----------");
|
||||
nRet = CMD_EVENT_INFO_ONE;
|
||||
}
|
||||
else if(strcmp(szProtocol, "EVENT:INFO:ALL") == 0)
|
||||
{
|
||||
LOG(LDBG, "-------- CMD_EVENT_INFO_ALL Called! ---------");
|
||||
nRet = CMD_EVENT_INFO_ALL;
|
||||
}
|
||||
// 프로토콜을 추가하려면 여기에 아래의 형태로 추가한다.
|
||||
// else if(strcmp(szProtocol, "String...........") == 0)
|
||||
// {
|
||||
// nRet = CMD_XXXXXXXXX;
|
||||
// }
|
||||
else // Invalid Protocol
|
||||
{
|
||||
nRet = CMD_UDP_ERROR;
|
||||
}
|
||||
|
||||
return nRet;
|
||||
}
|
||||
|
||||
|
||||
CUdpListener::CUdpListener(CEventDataManager* pEventDataManager)
|
||||
: m_pEventDataManager( pEventDataManager )
|
||||
{
|
||||
m_nSocket = -1;
|
||||
LOG(LDBG, "Constructor has been called.");
|
||||
}
|
||||
|
||||
CUdpListener::~CUdpListener()
|
||||
{
|
||||
if ( m_nSocket != -1)
|
||||
{
|
||||
::close(m_nSocket);
|
||||
m_nSocket = -1;
|
||||
}
|
||||
pthread_cancel(m_threadHandle);
|
||||
}
|
||||
|
||||
bool CUdpListener::Init(int nPort)
|
||||
{
|
||||
LOG(LDBG, "Initializer has been called.");
|
||||
int fRet = 0;
|
||||
struct sockaddr_in SocAddr;
|
||||
int nVal=1;
|
||||
|
||||
if(m_pEventDataManager == NULL )
|
||||
{
|
||||
LOG(LERR, "Invalid Object.");
|
||||
return false;
|
||||
}
|
||||
if( nPort <= 0 )
|
||||
{
|
||||
LOG(LERR, "Invalid Parameter. Port=%d", nPort);
|
||||
return false;
|
||||
}
|
||||
SocAddr.sin_family = AF_INET;
|
||||
SocAddr.sin_port = htons(nPort);
|
||||
SocAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
// UDP 소켓 생성.
|
||||
m_nSocket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (m_nSocket < 0)
|
||||
{
|
||||
LOG(LERR, "Socket Create: errno:%d errmsg:%s", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (setsockopt(m_nSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&nVal, sizeof(int)) < 0)
|
||||
{
|
||||
LOG(LERR, "setsockopt(SO_REUSEADDR) failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// UDP 소켓 바인드.
|
||||
fRet = ::bind(m_nSocket, (struct sockaddr *)&SocAddr, sizeof(SocAddr));
|
||||
if (fRet != 0)
|
||||
{
|
||||
LOG(LERR, "Socket Bind: errno:%d errmsg:%s", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG(LDBG, "Initializer has been succeed.");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///@brief 이 함수에서 UDP 통신을 receive 한다.
|
||||
void CUdpListener::Execute()
|
||||
{
|
||||
char szRcvBuffer[DEFAULT_BUFFER_SIZE];
|
||||
char szSndBuffer[DEFAULT_BUFFER_SIZE];
|
||||
int nRead = 0;
|
||||
struct sockaddr_in cliaddr;
|
||||
int addr_len = sizeof(cliaddr);
|
||||
int bMode = 0;
|
||||
int nRet = -1;
|
||||
bool bRet = false;
|
||||
string szTmp;
|
||||
|
||||
::memset(szRcvBuffer, 0, DEFAULT_BUFFER_SIZE);
|
||||
::memset(szSndBuffer, 0, DEFAULT_BUFFER_SIZE);
|
||||
//DEBUG_LOG("DEBUG: %d , %lu %lu, %lu", m_nSocket, szRcvBuffer, &cliaddr, &addr_len);
|
||||
nRead = ::recvfrom(m_nSocket, (char *)&szRcvBuffer, (unsigned int)DEFAULT_BUFFER_SIZE, 0, (struct sockaddr *)&cliaddr, (socklen_t *)&addr_len);
|
||||
if ( nRead <= 0 )
|
||||
{
|
||||
LOG(LERR, "recvfrom() error. %s.",strerror(errno));
|
||||
return;
|
||||
}
|
||||
LOG(LDBG, "Request Buffer = %s", szRcvBuffer);
|
||||
LOG(LDBG, "From = %s", inet_ntoa(cliaddr.sin_addr));
|
||||
|
||||
|
||||
bMode = ParsingPacket(szRcvBuffer);
|
||||
|
||||
switch (bMode)
|
||||
{
|
||||
case CMD_EVENT_INFO_ONE:
|
||||
{
|
||||
CEventData resData;
|
||||
|
||||
nRet = m_pEventDataManager->GetLatestData(resData);
|
||||
if ( nRet == -1 )
|
||||
{
|
||||
LOG(LERR, "GeLatestData() failed.");
|
||||
::snprintf(szSndBuffer, DEFAULT_BUFFER_SIZE, "1:%ld:Initializing Now.", ::time(NULL));
|
||||
} else
|
||||
{
|
||||
if( nRet == 0 )
|
||||
::snprintf(szSndBuffer, DEFAULT_BUFFER_SIZE, "%d:%ld:%s", nRet,::time(NULL), resData.m_szEventData.c_str());
|
||||
else
|
||||
::snprintf(szSndBuffer, DEFAULT_BUFFER_SIZE, "%d:%ld:%s", nRet,::time(NULL), resData.m_szEventData.c_str());
|
||||
}
|
||||
// 클라이언트 메시지 송신
|
||||
SendMsg((char*)szSndBuffer, strlen(szSndBuffer),&cliaddr, (socklen_t) sizeof(cliaddr));
|
||||
LOG(LDBG, "SEND MESSAGE %s.", szSndBuffer);
|
||||
}
|
||||
break;
|
||||
case CMD_EVENT_INFO_ALL:
|
||||
{
|
||||
list<CEventData> listRet;
|
||||
listRet.clear();
|
||||
|
||||
bRet = m_pEventDataManager->GetAllData(listRet);
|
||||
if( nRet == false || listRet.empty() )
|
||||
{
|
||||
LOG(LERR, "GetAllData() failed.");
|
||||
::snprintf(szSndBuffer, DEFAULT_BUFFER_SIZE, "%d:%ld:No EVENT IS FOUND.", 1,(long)::time(NULL));
|
||||
} else
|
||||
{
|
||||
// 2013-10-17
|
||||
// 기존에는 모든 메세지를 보냈으나, sms메세지를 만들어주는 web page에서 처리가안되는것을 확인했다.
|
||||
// 이에 따라 최근 100개 메세지를 전송하는 것으로 처리한다.
|
||||
//for (list<CEventData>::iterator it = listRet.begin(); it != listRet.end(); it++)
|
||||
int nCount = 0;
|
||||
|
||||
for (list<CEventData>::reverse_iterator it = listRet.rbegin(); it != listRet.rend(); it++)
|
||||
{
|
||||
// 2016.01.22 dadamin
|
||||
// 96 => 1024 : buffer overflow 발생하여 메세지 전송 실패 발생하여 변경함
|
||||
char timeBuf[1024] = {0};
|
||||
tm* ptm = localtime(&it->m_evtTime);
|
||||
::sprintf(timeBuf, "[%04d-%02d-%02d %02d:%02d:%02d] %s\n",
|
||||
ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec,
|
||||
it->m_szEventData.c_str());
|
||||
szTmp += timeBuf;
|
||||
nCount++;
|
||||
|
||||
if( nCount >= 100 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// upd send size limit
|
||||
if(szTmp.length() > 1100 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// upd send size limit
|
||||
::snprintf(szSndBuffer, 1400, "%d:%ld:%s", 1,(long)::time(NULL) , szTmp.c_str());
|
||||
}
|
||||
SendMsg((char*)szSndBuffer, strlen(szSndBuffer),&cliaddr, (socklen_t) sizeof(cliaddr));
|
||||
LOG(LDBG, "SEND MESSAGE %s.", szSndBuffer);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG(LDBG, "----------------- INVALID COMMAND REQUEST!!! ----------------------------------");
|
||||
LOG(LERR, "Invalid Protocol.");
|
||||
::memset(szSndBuffer, 0, DEFAULT_BUFFER_SIZE);
|
||||
::snprintf(szSndBuffer, DEFAULT_BUFFER_SIZE, "1:%ld:Invalid Arguments!", (long)::time(NULL));
|
||||
|
||||
LOG(LDBG, "SENDING Buffer = [%s]", szSndBuffer);
|
||||
|
||||
//::sendto(m_nSocket, szSndBuffer, strlen(szSndBuffer), 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
|
||||
SendMsg((char*)szSndBuffer, strlen(szSndBuffer),&cliaddr, (socklen_t) sizeof(cliaddr));
|
||||
// TODO: error check
|
||||
return;
|
||||
break;
|
||||
}//~switch (bMode)
|
||||
}
|
||||
|
||||
|
||||
void* CUdpListener::EntryPoint(void* arg)
|
||||
{
|
||||
CUdpListener* pObject = reinterpret_cast<CUdpListener *>(arg);
|
||||
if( pObject == NULL )
|
||||
{
|
||||
// static Function이기 때문에 로깅할 수 없다...
|
||||
//ERROR_LOG("Critical Memory Error, Invalid Object.");
|
||||
//exit(EXIT_FAILURE);
|
||||
}
|
||||
pthread_detach( pthread_self() );
|
||||
|
||||
while(1)
|
||||
{
|
||||
pthread_testcancel();
|
||||
pObject->Execute();
|
||||
pthread_testcancel();
|
||||
}
|
||||
|
||||
// pthread_exit();
|
||||
return (void *)NULL;
|
||||
}
|
||||
|
||||
bool CUdpListener::Start()
|
||||
{
|
||||
int nRet = ::pthread_create(&m_threadHandle, 0, CUdpListener::EntryPoint, this);
|
||||
|
||||
if( nRet != 0 )
|
||||
{
|
||||
LOG(LERR, "Thread create failed: errno:%d errmsg:%s", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
LOG(LDBG, "Thread create succeed.");
|
||||
sleep(0);
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/***************************************************************************
|
||||
UDP Listener Class
|
||||
-----------------------------------------
|
||||
begin : 2010/05/17
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __UDP_LISTENER__
|
||||
#define __UDP_LISTENER__
|
||||
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
#include "Logger.h"
|
||||
#include "EventDataManager.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/// @brief Protocols
|
||||
#define CMD_UDP_BASE 1000
|
||||
#define CMD_UDP_ERROR CMD_UDP_BASE
|
||||
#define CMD_EVENT_INFO_ONE ( CMD_UDP_BASE + 101 )
|
||||
#define CMD_EVENT_INFO_ALL ( CMD_UDP_BASE + 102 )
|
||||
|
||||
/// @brief CUdpListener
|
||||
/// UdpListener 는 client에서 udp 요청되는 패킷을 수신해서 관리하게 되며,
|
||||
/// raid 정보 조회 후, 결과를 전송한다.
|
||||
/// 내부적으로 Thread를 사용하고있다.
|
||||
class CUdpListener
|
||||
{
|
||||
public:
|
||||
/// @brief 생성자
|
||||
/// @param [in] pEventManager CEventManager 객체
|
||||
CUdpListener(CEventDataManager* pEventDataManager);
|
||||
~CUdpListener();
|
||||
|
||||
/// @brief Init 함수 클래스 환경이 정상적인지를 검사한다.
|
||||
/// @param [in] nPort UDP listen port 번호.
|
||||
/// @return 성공: true, 실패: false
|
||||
bool Init(int nPort);
|
||||
|
||||
/// @brief Thread를 생성하고, 이를 시작한다.
|
||||
/// @param none
|
||||
/// @return 성공: true, 실패: false
|
||||
bool Start();
|
||||
|
||||
private:
|
||||
// 이벤트 저장 객체
|
||||
CEventDataManager* m_pEventDataManager;
|
||||
|
||||
// 쓰레드 핸들
|
||||
pthread_t m_threadHandle;
|
||||
|
||||
// 쓰레드 시작 루틴이다.
|
||||
static void* EntryPoint(void* arg);
|
||||
|
||||
int m_nSocket;
|
||||
|
||||
// 해당 함수의 내용은 수정하지 말것.
|
||||
void Execute();
|
||||
|
||||
|
||||
/// @brief 클라이언트로 부터 받아온 스트링 프로토콜을 정수 프로토콜로 변환한다.
|
||||
/// @param [in] szProtocol 클라이언트로부터 전송받은 스트링 프로토콜.
|
||||
/// @return 성공: 양의 정수의 프로토콜 값. 실패: -1
|
||||
int ParsingPacket(const char * szProtocol);
|
||||
int SendMsg(char * szSndBuffer,int size, struct sockaddr_in * cliaddr, socklen_t nAddrSize);
|
||||
CEventData m_evtData;
|
||||
};
|
||||
#endif // __UDP_LISTENER__
|
||||
@@ -0,0 +1,70 @@
|
||||
/***************************************************************************
|
||||
fhs_raidmond Header ( fhs_raidmond.h )
|
||||
-----------------------------------------
|
||||
begin : 2010/03/09
|
||||
copyright : (C) 2005 SolutionBox Inc.
|
||||
author : Service 1 Team
|
||||
email : svc1@solbox.com
|
||||
version : 1.0
|
||||
|
||||
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
||||
Redistribution and use in source and binary forms, with or with out
|
||||
modification, are not permitted in outside of SolutionBox Inc.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __FHS_RAIDMOND_GLOBAL_VALUE_H__
|
||||
#define __FHS_RAIDMOND_GLOBAL_VALUE_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#include "Logger.h"
|
||||
|
||||
struct st_config
|
||||
{
|
||||
// Common Part
|
||||
std::string szLogDir;
|
||||
int nLogLevel;
|
||||
|
||||
// fhs_raidmond Part
|
||||
int nCheckTerm;
|
||||
|
||||
int nReportPort;
|
||||
|
||||
int nEventLevel;
|
||||
|
||||
std::string szSMSHost;
|
||||
int nSMSPort;
|
||||
std::string szSMSSendfile;
|
||||
|
||||
|
||||
// »ý¼ºÀÚ
|
||||
st_config()
|
||||
{
|
||||
nLogLevel = 0;
|
||||
nCheckTerm = 0;
|
||||
nReportPort = 0;
|
||||
nEventLevel = 0;
|
||||
nSMSPort = 0;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// @brief Global config object.
|
||||
extern struct st_config g_envConfig;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __FHS_RAIDMOND_GLOBAL_VALUE_H__ */
|
||||
|
||||
@@ -0,0 +1,349 @@
|
||||
#include "fhs_raidmond.h"
|
||||
#include "GetConfig.h"
|
||||
#include "Child.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/// config object initialize
|
||||
struct st_config g_envConfig;
|
||||
|
||||
/// daemon flag
|
||||
static bool _isdaemon = true;
|
||||
|
||||
/// @brief Program version 출력 함수.
|
||||
/// @return void
|
||||
static void ShowVersion(void)
|
||||
{
|
||||
cerr << "[info] " << PROG_NAME << " Version :" << PROG_VERSION << endl;
|
||||
}
|
||||
|
||||
|
||||
/// @brief Program version 사용 방법 출력 함수.
|
||||
/// @return void
|
||||
static void ShowUsages(void)
|
||||
{
|
||||
ShowVersion();
|
||||
cerr << "usage: " << PROG_NAME << " [-vhcD]" << endl;
|
||||
cerr << "options are: " << endl;
|
||||
cerr << "-v : print current version" << endl;
|
||||
cerr << "-c <path> : Log Diretory" << endl;
|
||||
cerr << "-D : running console mode" << endl;
|
||||
cerr << "-h : help " << endl;
|
||||
}
|
||||
|
||||
/// @brief Child 프로세스 생성(fork) 함수
|
||||
/// @return void
|
||||
static void MakeChild(void)
|
||||
{
|
||||
pid_t processId;
|
||||
// Child 프로세스 fork
|
||||
processId = fork();
|
||||
if( processId < 0 ) // Fork fail
|
||||
{
|
||||
int errorNum = errno;
|
||||
LOG(LERR, "Child Process create failed. [%d][%s]", errorNum, strerror(errorNum) );
|
||||
return;
|
||||
}
|
||||
else if( processId == 0 ) // Parent Process => Child Process
|
||||
{
|
||||
// Child Process Main 함수 호출 및 종료처리.
|
||||
ChildMain();
|
||||
exit( EXIT_SUCCESS );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parent Process => Logging
|
||||
_LOG(LNOT, "Child Process create success. PID[%d]" , processId);
|
||||
// 잠시 대기
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Parent Process 에서 child Process 가 종료된 경우 시그널 처리를 위한 함수
|
||||
/// @param nSignalNumber [in] 발생한 시그널 Number
|
||||
/// @return void
|
||||
static void sigchld_hdl( int nSignalNumber )
|
||||
{
|
||||
pid_t killPid;
|
||||
int nKillStatus;
|
||||
while( ( killPid = waitpid( -1, &nKillStatus, WNOHANG ) ) > 0 )
|
||||
{
|
||||
// 자식 프로세스가 Signal 에 의해 종료되었는지 검사.
|
||||
if( WIFSIGNALED( nKillStatus ) )
|
||||
{
|
||||
LOG(LWAR, "Child process[%d] killed by signal[%d]", killPid, WTERMSIG( nKillStatus ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LWAR, "Child process[%d] killed. Not signal", killPid );
|
||||
// Child 프로세스가 EXIT_FAILURE 반환 ( 초기화 실패시 )
|
||||
// 해당 내역을 화면 및 로그 상에 출력하고
|
||||
// 자식 프로세스를 재생성 처리하지 않는다.
|
||||
if( WIFEXITED( nKillStatus ) )
|
||||
{
|
||||
if( WEXITSTATUS( nKillStatus ) == EXIT_FAILURE )
|
||||
{
|
||||
LOG(LERR, "Child Process[%d] initilaize failed.", killPid );
|
||||
LOG(LERR, "Parent Process[%d] exit by Child. Good Bye..", getpid());
|
||||
cerr << "[error] " << PROG_NAME << ": Process exit by Child process initialize failed. check log file." << endl;
|
||||
usleep(500000);
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
}
|
||||
}
|
||||
// Child Process 재생성 처리.
|
||||
MakeChild();
|
||||
}
|
||||
// 오류 발생시 해당 내역 로깅
|
||||
if( killPid < 0 )
|
||||
{
|
||||
int errorNum = errno;
|
||||
LOG(LERR, "Parent process error: SIG_CHLD receive but waitpid return error[%d][%s]", errorNum, strerror(errorNum));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/// @brief Parent Process 종료 Signal 을 전달받은 경우 이를 처리하기 위한 함수.
|
||||
/// @param nSignalNumber [in] 발생한 시그널 Number
|
||||
/// @return void
|
||||
static void SigTermParent( int nSignalNumber )
|
||||
{
|
||||
// Signal Number 에 따른 로깅처리.
|
||||
if( nSignalNumber == SIGTERM )
|
||||
{
|
||||
LOG(LWAR, "Parent Process[%d] exit job start by user signal [SIGTERM]", getpid() );
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LWAR, "Parent Process[%d] exit job start by abnormal signal [%d]", getpid(), nSignalNumber );
|
||||
}
|
||||
// Process 종료관련 작업 추가
|
||||
LOG(LWAR, "Parent Process[%d] exit job end. Good Bye..", getpid());
|
||||
// KILL - Child
|
||||
kill(0, SIGTERM);
|
||||
// waitpid
|
||||
while(waitpid(-1, NULL, WNOHANG) > 0);
|
||||
|
||||
usleep(500000);
|
||||
exit( EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
/// @brief Parent Process 에서 Core 생성 관련 Signal 을 받은 경우 이를 처리하기 위한 함수.
|
||||
/// @param nSignalNumber [in] 발생한 시그널 Number
|
||||
/// @return void
|
||||
static void SigCoreParent( int nSignalNumber )
|
||||
{
|
||||
LOG(LERR, "Parent Process[%d] abnoraml exit. Check Core file. Receive signal [%d]", getpid(), nSignalNumber );
|
||||
//LOG(LERR, "Core file path : [%s/%s.core]", g_envConfig.szLogDir.c_str(), PROG_NAME );
|
||||
// Process 종료관련 작업 추가
|
||||
|
||||
// Log Directory 상에 Core 파일 생성처리.
|
||||
chdir( g_envConfig.szLogDir.c_str() );
|
||||
signal( nSignalNumber, SIG_DFL );
|
||||
// Core dump 생성을 위한 신호 발생처리.=> ?
|
||||
raise( nSignalNumber );
|
||||
}
|
||||
|
||||
/// @brief Parent 프로세스 signal 처리 설정을 위한 함수
|
||||
/// @return void
|
||||
static void SetSignalParent()
|
||||
{
|
||||
sigset_t set;
|
||||
struct sigaction act;
|
||||
sigfillset( &set );
|
||||
sigprocmask( SIG_SETMASK, &set, NULL );
|
||||
memset( &act, 0x00, sizeof(act) );
|
||||
sigfillset( &act.sa_mask );
|
||||
/* 무시할 신호 목록 */
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigaction( SIGPIPE, &act, NULL); /* 파이프 디스크립터 오류 발생시 Process가 죽는 것은 방지하기 위하여 설정 */
|
||||
sigaction( SIGHUP , &act, NULL); /* Process를 기동시킨 관리자의 로그아웃시 발생 시그널 */
|
||||
sigaction( SIGQUIT, &act, NULL); /* 키보드에 의한 Abort 신호 처리 => ? */
|
||||
|
||||
if(_isdaemon)
|
||||
{
|
||||
sigaction( SIGINT , &act, NULL); /* ^C 키를 누른 경우 받는 신호 => demon 으로 기동되기 땜시 이 신호 못받음 */
|
||||
}
|
||||
else
|
||||
{
|
||||
act.sa_handler = SigTermParent;
|
||||
sigaction( SIGINT, &act, NULL); /* ^C 키를 누른 경우 받는 신호 => kill -TERM 과 동일한 처리함 */
|
||||
}
|
||||
|
||||
// Child Process 종료에 대한 처리기 설정.
|
||||
act.sa_handler = sigchld_hdl;
|
||||
sigaction( SIGCHLD, &act, NULL);
|
||||
/* 각종 에러나 사용자의 종료 신호 처리 */
|
||||
act.sa_handler = SigTermParent;
|
||||
sigaction( SIGTERM, &act, NULL); /* kill -TERM 에 의한 프로세스 종료시 */
|
||||
/* Core 관련 signal 처리 : 오류 처리 및 Debug(core dump) 목적 */
|
||||
// dadamin : 팀 기준 적용
|
||||
//act.sa_handler = SigCoreParent;
|
||||
//sigaction( SIGILL , &act, NULL); /* Illegal instruction */
|
||||
//sigaction( SIGFPE , &act, NULL); /* Erroneout arithmetic operation */
|
||||
//sigaction( SIGBUS , &act, NULL); /* Access to undefined portion of a memory object */
|
||||
//sigaction( SIGSEGV, &act, NULL); /* Invalid memory reference */
|
||||
//sigaction( SIGSYS , &act, NULL); /* Bad System Call */
|
||||
//sigaction( SIGXCPU, &act, NULL); /* CPU-time limit exceeded */
|
||||
//sigaction( SIGXFSZ, &act, NULL); /* File-size limit exceeded */
|
||||
sigemptyset(&set); /* 신호 처리기 처리 설정 위한 블록 해제 */
|
||||
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||
}
|
||||
// daemon 생성 함수
|
||||
static bool daemon_create(bool bcreate)
|
||||
{
|
||||
// set parent signal
|
||||
SetSignalParent();
|
||||
|
||||
// set mask
|
||||
umask(0);
|
||||
|
||||
// daemon
|
||||
if(bcreate && daemon(false, false) != 0 ) // after this line, parent's pid will be changed.
|
||||
{
|
||||
cerr << "[error] Daemonize Failed.(errno : " << errno << ")" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/// @brief std 상에 trim 함수가 없어서 직접 구현 아니면 boost/algorithm/string.hpp 상의 boost::trim 함수 사용
|
||||
/// @return void
|
||||
static void Trim( string & str )
|
||||
{
|
||||
if( str.length() == 0 )
|
||||
return ;
|
||||
// 문자열 뒤의 공백, TAB, CR 등의 문자 제거처리.
|
||||
string::size_type pos = str.find_last_not_of(" \a\b\f\n\r\t\v");
|
||||
if( pos != string::npos )
|
||||
str.erase( pos + 1 );
|
||||
// 문자열 앞의 공백, TAB, CR 등의 문자 제거처리.
|
||||
pos = str.find_first_not_of(" \a\b\f\n\r\t\v");
|
||||
if( pos != string::npos )
|
||||
str.erase( 0, pos );
|
||||
}
|
||||
/// @brief 현재 Process가 기동중인지 여부를 판단하기 위한 함수( 프로세스 중복 실행 체크)
|
||||
/// @return 이미 해당 프로세스가 기동 중인 경우 true 반환, 그렇지 않으면 false 반환.
|
||||
static bool IsCurrentProcessRun()
|
||||
{
|
||||
char tempBuffer[512];
|
||||
FILE * fd = NULL;
|
||||
bool bRun = false;
|
||||
snprintf( tempBuffer, sizeof(tempBuffer), "pgrep -x %s | sort", PROG_NAME );
|
||||
fd = popen( tempBuffer, "r" );
|
||||
if( fd == NULL )
|
||||
{
|
||||
cerr << "[error] Process duplication check failed.[popen error][" << strerror(errno) << "]" << endl;
|
||||
// 오류 발생시 true 반환하여 프로세스 실행 방지처리
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset( tempBuffer, 0x00, sizeof(tempBuffer) );
|
||||
while( fgets( tempBuffer, sizeof(tempBuffer)-1, fd) != NULL )
|
||||
{
|
||||
string tempPid( tempBuffer );
|
||||
Trim(tempPid);
|
||||
if( atoi( tempPid.c_str() ) != getpid() )
|
||||
{
|
||||
cout << "[info] Process duplication found. pid[" << atoi( tempPid.c_str() ) << "]" << endl;
|
||||
bRun = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pclose( fd );
|
||||
return bRun;
|
||||
}
|
||||
}
|
||||
// main function
|
||||
int main( int argc, char * argv[] )
|
||||
{
|
||||
string cofigpath = DEFAULT_CONFIG_FILE;
|
||||
// parse command line arguments
|
||||
int o;
|
||||
while ((o = getopt(argc, argv, "vhDc:")) >= 0)
|
||||
{
|
||||
switch (o)
|
||||
{
|
||||
case 'h': // help
|
||||
ShowUsages();
|
||||
return EXIT_SUCCESS;
|
||||
break;
|
||||
case 'v': // version
|
||||
ShowVersion();
|
||||
return EXIT_SUCCESS;
|
||||
break;
|
||||
case 'D': // consol mode
|
||||
_isdaemon = false;
|
||||
cerr << "Runnig Console mode." << endl;
|
||||
break;
|
||||
case 'c': // config file
|
||||
cofigpath = optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 프로그램 중복 실행 체크
|
||||
if( IsCurrentProcessRun() == true )
|
||||
{
|
||||
cerr << "[warning] Process[" << PROG_NAME << "] is already running...." << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// load config
|
||||
string szErrorMessage;
|
||||
if(!GetConfig( cofigpath, g_envConfig, szErrorMessage ) )
|
||||
{
|
||||
cerr << "[error] Process[" << PROG_NAME << "]: " << szErrorMessage << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// init log
|
||||
if( CLogger::Init( PROG_NAME, g_envConfig.szLogDir.c_str(), g_envConfig.nLogLevel ) == false )
|
||||
{
|
||||
cerr << "[error] Process[" << PROG_NAME << "]: Log init failed." << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
// Global log object set
|
||||
|
||||
// daemon create
|
||||
if(!daemon_create(_isdaemon))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
// Process 기동 관련 정보 로깅
|
||||
_LOG(LINF, "***********************************************************" );
|
||||
_LOG(LINF, " %s (FHS RAID Monitor Daemon) Start. Version: %s", PROG_NAME, PROG_VERSION );
|
||||
_LOG(LINF, "***********************************************************" );
|
||||
_LOG(LINF, "Config file : %s", cofigpath.c_str() );
|
||||
_LOG(LINF, "Log Path : %s/%s", g_envConfig.szLogDir.c_str(), PROG_NAME );
|
||||
_LOG(LINF, "Logging Level : %d", g_envConfig.nLogLevel );
|
||||
_LOG(LINF, "health check term : %d", g_envConfig.nCheckTerm );
|
||||
_LOG(LINF, "report thread port : %d", g_envConfig.nReportPort );
|
||||
_LOG(LINF, "event level : %d", g_envConfig.nEventLevel );
|
||||
_LOG(LINF, "sms send host : %s", g_envConfig.szSMSHost.c_str() );
|
||||
_LOG(LINF, "sms send port : %d", g_envConfig.nSMSPort);
|
||||
_LOG(LINF, "sms send file : %s", g_envConfig.szSMSSendfile.c_str() );
|
||||
_LOG(LINF, "***********************************************************" );
|
||||
|
||||
// fork child
|
||||
MakeChild();
|
||||
|
||||
// set process title
|
||||
#if defined(__FreeBSD__)
|
||||
setproctitle( "Parent [monitor Child process]" );
|
||||
#endif
|
||||
// wait
|
||||
while( 1 )
|
||||
{
|
||||
pause();
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user