컴퓨터활용/프로프레임

프로프레임 PFM_TRY 에 대한 이해

멜번초이 2008. 6. 20. 09:14

PFM_TRY 는 프로프레임에서 가장 빈번히 사용되므로 정확한 이해가 필요하다. PFM_TRY 는 원래 프로프레임 1.0 에서는 SYS_TRY 였고 2.0 에서는 PSC_TRY 였다. 오늘의 PFM_TRY 를 사용하게 된 것은 신한은행 차세대 프로젝트를 하던 3.0 부터 이다.  자바와 같은 OOP 객체지향 프로그램에서 흔히 사용하는 try  .. catch 를 흉내낸 것이지만 나름대로 훌륭한 역할을 해 내고 있다.

PFM_TRY 는 pfmLogMacro.h 에 다음과 같이 정의되어 있다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#ifndef _PFM_NO_TRYLOG
#define PFM_TRY( _Ftn )                                                             \
        do {                                                                        \
            struct timeval s_time_val;                                              \
            long _db_chk;                                                           \
            _db_chk = _pfmDbCheckAndTryLog('T'"AP", __FILE__, __func__, __LINE__);\
            if (_db_chk == RC_ERR)                                                  \
                _pfmTryStart( __FILE__, __func__, __LINE__, &s_time_val, #_Ftn, 0); \
            rc = _Ftn;                                                              \
            if (_db_chk == RC_ERR)                                                  \
                _pfmTryEnd( __FILE__, __func__, __LINE__, &s_time_val, #_Ftn, rc);  \
            if( rc != RC_NRM) goto PFM_CATCH;                                       \
        } while (0)
#define PFM_TRYNJ( _Ftn )                                                           \
        do {                                                                        \
            struct timeval s_time_val;                                              \
            long _db_chk;                                                           \
            _db_chk = _pfmDbCheckAndTryLog('T'"AP", __FILE__, __func__, __LINE__);\
            if (_db_chk == RC_ERR)                                                  \
                _pfmTryStart( __FILE__, __func__, __LINE__, &s_time_val, #_Ftn, 0); \
            rc = _Ftn;                                                              \
            if (_db_chk == RC_ERR)                                                  \
                _pfmTryEnd( __FILE__, __func__, __LINE__, &s_time_val, #_Ftn, rc);  \
        } while (0)
#else
#define PFM_TRY( _Ftn )
#define PFM_TRYNJ( _Ftn )
#endif
 
cs

정의에서 볼 수 있듯이 입력된 함수를 그대로 수행한 다음에 그 결과 리턴되는 값에 따라서 분기를 한다. 정상(RC_NRM) 이 리턴될 경우에는 그냥 밑으로 흘러 내리고 그 외의 값으로 리턴될 경우에는 PFM_CATCH 로 jump 하는 단순한 역할이다.  따라서 PFM_TRY 를 사용하였다면 반드시 동일한 BLOCK 내에 PFM_CATCH 라는 라벨이 존재해야 한다. PFM_TRY 를 이용하면 함수를 호출하기 전 후에는 함수의 입구, 출구를 로그로 남겨주기 때문에 로직을 추적하여 따라가기에 편리하다.  

그리고 이 매크로를 do ... while 로 묶어 놓은 것은 PFM_TRY() 뒤에 ; 을 반드시 찍도록 하기 위한 목적이다. do ... while 로 싸지 않았다면 ; 없이 PFM_TRY 를 사용해도 컴파일시 오류가 나지 않으므로 프로그램을 표준화할 수 없다. 어떤 것은 ; 으로 끝나고 어떤 라인은 ; 이 없다면 혼란스러울 수 있다.

반면에 PFM_TRYNJ 는 함수를 수행한 후에 리턴 값에 상관없이 무조건 아래로 흘러 내려간다. goto PFM_CATCH 가 없는 것만 다르다. 

1
2
3
4
5
6
7
PFMTRY [a000_init_proc(context)               ] 입구
PFMTRY [a000_init_proc(context)               ] 출구 RC [0] TIME [00.000032]
PFMTRY [b000_inputvalid_proc(context)         ] 입구
PFMTRY [b000_inputvalid_proc(context)         ] 출구 RC [0] TIME [00.000013]
PFMTRY [c000_main_proc(context)               ] 입구
PFMTRY [c100_fex_commbuf_create(context)      ] 입구
PFMTRY [pfmDlCall1("pfmApLog"&pfmApLog_io)  ] 입구
cs

PFM_TRY 를 빠져 나올 때 해당 구간의 수행시간을 같이 LOG에 남겨준다. 이 시간은 PFM_TRY 입구 부터 출구 까지의 수행 시간이다. 이것을 이용하여 어느 구간에서 수행시간이 많이 걸렸는지 체크할 수 있다.