/*
 *========================================================================
 *
 *   시스템명 : 요금징수 시스템
 *   파 일 명 : ft_remain.c
 *   작 성 자 : 조보용 (catacath@neighbor21.co.kr)
 *   작 성 일 : 2012.10.10
 *   수 정 일 :
 *   설    명 : File & DB Table간 변환 Main
 *
 *========================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
#include <arpa/inet.h>
#include <dirent.h>

#include "dir_path.h"
#include "path_def.h"
#include "file_no.h"
#include "file_nm.h"
#include "chg_struc.h"

#define    MAX_REHND_LIST    128

void     abort_proc();
int     scanning_rehndlog();
//int     oracle_connect();
int     request_rehnd_proc();
int     file_tbl_chng();
int     delete_rehndlog();
//int     oracle_disconnect();

extern    int    logon_ora_svr;
static   int    cmp_time();
int        n_rehnd_file;
int        f_recnum;
int        f_errno;

static struct rehnd_list
{
    char    isfile[16];            /* sam file name    */
    int    n_records;            /* # of records        */
    int    v_time;
} rehnd_list[MAX_REHND_LIST];


/*==============================================================================
* 1. 모 듈 명 :  main
* 2. 모듈기능 :  REHND 파일을 체크하는 메인 프로시저
* 3. 입    력 :  
* 4. 입 출 력 :  
* 5. 출    력 : 
* 6. Fuction Return: 
*=============================================================================*/
int main()
{
    char    debug_f[128];
    int    ii, status;

    lb_user_chg();

    proc_log("\nStart ...\n");

    signal(SIGTERM, abort_proc);

    for (;;)
    {
        if (getppid() <= 1)
            break;

        c_DbConnect();
//        oracle_connect();

        /******************************************/
        /* Checking rehnd log file           */
        /******************************************/

        n_rehnd_file = scanning_rehndlog();

        if (n_rehnd_file <= 0)    
        {
            sleep(10);
            continue;
        }

        sighold(SIGTERM);

        for (ii = 0; ii < n_rehnd_file; ii++)
            request_rehnd_proc(ii);

        disconnect_db();

        sigrelse(SIGTERM);
    }
}
/*==============================================================================
* NAME    : request_rehnd_proc()
* DESC    : Check된 REHND LOGGING DATA를 
*=============================================================================*/
int request_rehnd_proc(idx)
int    idx;
{
    struct    chg_struc    chg_struc;
    char        ispath[128];
    int        isfd, isrc, ii, temp, ret;
    char uid[20];
    char pwd[20];
    
    
    memset(&chg_struc, 0x0, sizeof(struct chg_struc));
    
    if (rehnd_list[idx].n_records <= 0)
        return(0);

    sprintf(ispath, "%s/%s/%s",DIR_TCS,DIR_CONV,rehnd_list[idx].isfile);

    proc_log("read_proc() ispath=[%s], n_record=%d\n",    ispath, rehnd_list[idx].n_records);

    isfd = lb_open(ispath, FINOUT +FC_MANULOCK);
    
    if (isfd < 0)
        return(0);
    
    for (ii=0;;ii++)
    {
        
        isrc = lb_read(isfd, &chg_struc, FNEXT  , sizeof(struct chg_struc));
        
        if (isrc <= 0)
        {
            if (lseek(isfd, 0, SEEK_CUR)==lseek(isfd, 0, SEEK_END))
            {
                lb_close(isfd);
                delete_rehndlog(rehnd_list[idx].isfile);
                return(0);
            }
            
            if (lb_dummy_chk(&chg_struc, sizeof(struct chg_struc)))
            {

                proc_log("SKIP FIDN(%d) DIRF(%d) IRBH(%d)\n", chg_struc.file_id, chg_struc.tbl2file_div, chg_struc.seq_no);
                if (ii == rehnd_list[idx].n_records)
                    break;
                else 
                    continue;
            }
            else
            {
                lb_delete(isfd, FNO_REHNDLOG, &chg_struc_key[0], &chg_struc);
                continue;
            }
        }
        
        lb_delete(isfd, FNO_REHNDLOG, &chg_struc_key[0], &chg_struc);
        
        chg_struc.caller = 99;
        
        ret=file_tbl_chng(&chg_struc);

        if(ii%1000==1 || ii==rehnd_list[idx].n_records)
            proc_log("#%03d %s ins %d %d/%d ret=%d",chg_struc.file_id, file_nm[chg_struc.file_id].file_info, isrc, ii, rehnd_list[idx].n_records, ret);
    }
    
    lb_close(isfd);
    
    if (ii == rehnd_list[idx].n_records)
        delete_rehndlog(rehnd_list[idx].isfile);
    
    return(0);
}
/*==============================================================================
* NAME    : scanning_rehndlog()
* DESC    : DIR_CONV directory에서 REHND FILE을 LISTUP
*      REHND LOGING FILE은 매시간대별로 FILE명을 다르게 구분 처리
*=============================================================================*/
int scanning_rehndlog()
{
    struct    write_info    write_info;
    struct    stat i_stat;
    struct    tm   *c_tm;
    struct     dirent *dirent;  
    time_t    c_clock;
    char        d_path[128], f_path[128], i_name[32], i_path[128];
    int        di_nrecords, n_file, v_time, f_time;
    int        ii, isfd, isrc, isrn;
    DIR        *dir;

    sprintf(d_path, "%s/%s", DIR_TCS, DIR_CONV);
    dir = opendir(d_path);
    
    if (dir == NULL)
        return(0);

    c_clock = time(0);
    c_tm = localtime(&c_clock);
    sprintf(write_info.year, "%04d", c_tm->tm_year + 1900);
    sprintf(write_info.mon, "%02d", c_tm->tm_mon + 1);
    sprintf(write_info.day, "%02d", c_tm->tm_mday);
    sprintf(write_info.hr, "%02d", c_tm->tm_hour);
    v_time = (atoi(write_info.year)*1000000)+(atoi(write_info.mon)*10000)+(atoi(write_info.day)*100)+atoi(write_info.hr);

    n_file = 0;
    
    while ((dirent = readdir(dir)) != NULL)
    {
        if (strlen(dirent->d_name) != 10) /* yyyymmddhh */
        {
            sprintf(f_path, "%s/%s", d_path, dirent->d_name);
            remove(f_path);
            continue;
        }
        
        memcpy(i_name, dirent->d_name, 10);
        i_name[10] = '\0';
        sprintf(i_path, "%s/%s", d_path, i_name);
        
        isrc = stat(i_path, &i_stat);
        
        if (isrc == -1 || i_stat.st_size <= 0)
        {
            if (v_time > atoi(i_name))
                delete_rehndlog(i_name);
                
            continue;
        }

        proc_log("scanning_rehnd file=[%s]\n", i_name); 

        di_nrecords = i_stat.st_size / sizeof(struct chg_struc);
        
        proc_log("scanning_rehnd record=[%d]\n", di_nrecords); 
        /**************************************************/
        /* 이전 시간대 LOG FILE중 RECORD가 없는 경우 삭제 */
        /**************************************************/
        
        f_time = atoi(i_name);
        
        proc_log("REHND time = %d current time=%d\n", f_time, v_time);

        if (di_nrecords <= 0 && f_time < v_time)
        {
            proc_log("Delete old flushed rehnd [%s]\n", i_name);
            delete_rehndlog(i_name);
            continue;
        }

        strcpy(rehnd_list[n_file].isfile, i_name);
        rehnd_list[n_file].v_time = atoi(i_name);
        rehnd_list[n_file].n_records = di_nrecords;
        n_file++;
        
        if (n_file >= MAX_REHND_LIST)
            break;
    }
    
    closedir(dir);
    
    if (n_file > 1)
        qsort(rehnd_list, n_file, sizeof(struct rehnd_list), cmp_time);

    /**************************************************************/
    /* 현시간대 LOGGING FILE 생성                      */
    /* 화일경합에 의한 SAM-F의 오류 방지를 위해 이곳에서만 BUILD  */
    /**************************************************************/
    
    write_info.lane_div = 3;
    isfd = lb_fchk(&write_info, FNO_REHNDLOG, FINPUT+FC_MANULOCK);
    
    if (isfd >= 0) lb_close(isfd);

    for (ii = 0, isrn = 0; ii < n_file; ii++)
    {
        proc_log("rehnd_list[%d]=[%s] records=%d\n", ii, rehnd_list[ii].isfile, rehnd_list[ii].n_records); 

        isrn += rehnd_list[ii].n_records;
    }

    if (isrn == 0)
        return(0);
    else
        return(n_file);
}
/*==============================================================================
* NAME    : delete_rehndlog()
* DESC    : Delete REDO log file.
*=============================================================================*/
int delete_rehndlog(isname)
char    *isname;
{
    char    ispath[128];

    sprintf(ispath, "%s/%s/%s", DIR_TCS, DIR_CONV, isname);
    
    proc_log("delete_rehndlog() [%s]\n", isname); 

    remove(ispath);
    return(0);
}
/*==============================================================================
* NAME    : sig_handler()
* DESC    : Signal handler (do nothing, only for synchronzed processing event.
*=============================================================================*/
static void sig_handler(signo)
int    signo;
{
    signal(signo, sig_handler);
}
/*==============================================================================
* NAME    : cmp_time()
* DESC    : REDO list의 화일시간 비교
*=============================================================================*/
static int cmp_time(rehnd1, rehnd2)
struct rehnd_list *rehnd1,*rehnd2;
{
    if (rehnd1->v_time == rehnd2->v_time)
        return(0);

    if (rehnd1->v_time > rehnd2->v_time)
        return(1);
    else
        return(-1);
}
/*==============================================================================
* NAME    : abort_proc()
* DESC    : Abort phpsdbf process
*=============================================================================*/
void abort_proc(signo)
int    signo;
{
	disconnect_db();
//    oracle_disconnect();
    exit(0);
}
