/****************************************************************************
** File name    :  HTSLVService.cpp
** Description  :  main file
** Create date  :  2019.09.01
** Auther by    :  Liuyx
** Version info :  V1.0.01
** Copyright (C) 2002-2019 xi'an huatek, Inc Co., Ltd
** Update record:
** DATE         AUTHER   DESC
** -------------------------------------------------------------------------
** 2019.09.01   Liuyx    first build
****************************************************************************/
#include "HTGlobal.h"

static const char *_FILE_ = "HTSLVService.cpp";
CDBMySQL* CDBMySQL::p_dbHandle = NULL;

static char is_down = 0;

// 终止所有业务工作线程
static void cancel_thread_work(void)
{
#ifndef _WIN32
    int i = 0;
    if (thread_handle_modbus_recv) {
        pthread_cancel(thread_handle_modbus_recv);
        pthread_join(thread_handle_modbus_recv, NULL);
        pthread_kill(thread_handle_modbus_recv, SIGURG);
    }
    vPrtLogMsg(LOG_DEBUG, RET_OK, "thread_handle_modbus_recv shutdown.");

    if (thread_handle_iec61850_recv) {
        pthread_cancel(thread_handle_iec61850_recv);
        pthread_join(thread_handle_iec61850_recv, NULL);
        pthread_kill(thread_handle_iec61850_recv, SIGURG);
    }
    vPrtLogMsg(LOG_DEBUG, RET_OK, "thread_handle_iec61850_recv shutdown.");

    //if (thread_handle_db_insert) {
    //    pthread_cancel(thread_handle_db_insert);
    //    pthread_join(thread_handle_db_insert, NULL);
    //    pthread_kill(thread_handle_db_insert, SIGURG);
    //}
    //vPrtLogMsg(LOG_DEBUG, RET_OK, "thread_db_insert_proc shutdown.");
#endif
}
static void sig_exit(int signo)
{
    vPrtLogMsg(LOG_DEBUG, errno, "recv signal, service shutdown.sig:%d", signo);

    cancel_thread_work();
    vPrtLogMsg(LOG_DEBUG, errno, "unloading service is done...1");
    g_Running = 0;  // 先停止所有的业务线程

    _SLEEP(1000 * 2);

    vPrtLogMsg(LOG_DEBUG, errno, "unloading service is done...2");
    unLoadServiceEvent();// 卸载运行配置
    is_down = 0;
    vPrtLogMsg(LOG_DEBUG, errno, "unloading service is done.");
}

void sig_chld(int signo)
{
#ifndef _WIN32
    pid_t        pid;
    int         stat;
    while ((pid = waitpid(-1, &stat, WNOHANG)) > 0)
        vPrtLogMsg(LOG_DEBUG, RET_OK, "child %d terminated\n", pid);
#endif
    return;
}

// 创建守护进程环境
static int HTStartBackgroundProcess()
{
#ifndef _WIN32
    pid_t pid;

    // 1.转变为后台进程
    if ((pid = fork()) != 0)
        exit(0);

    // 2.离开原先的进程组
    setsid();

    // 3.禁止再次打开控制终端
    if ((pid = fork()) != 0)
        exit(0);

    // 4.关闭打开的文件描述符，避免浪费系统资源
    /*
    rlimit rlim;
    if(getrlimit(RLIMIT_NOFILE,&rlim) == 0)
    {
    for(int fd=3; fd<=(int)rlim.rlim_cur; fd++)
    {
    close(fd);
    }
    }
    */

    // 5.改变当前的工作目录，避免卸载不了文件系统
    //if (chdir("/") == -1) exit(1);

    // 6.重设文件掩码，防止某些属性被父进程屏蔽
    umask(0);
    setpgrp();

    // 7.重定向标准输入，输出，错误流，因为守护进程没有控制终端
    /*
    if ((fd = open("/dev/null", O_RDWR)) == -1)
    exit(1);
    dup2(fd, STDIN_FILENO);
    dup2(fd, STDOUT_FILENO);
    dup2(fd, STDERR_FILENO);
    close(fd);
    */
    signal(SIGINT, sig_exit);  // Program terminated with signal 11, Segmentation fault.
    signal(SIGTERM, sig_exit);
    // 8.屏蔽信号
    signal(SIGHUP, SIG_IGN);
    signal(SIGQUIT, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGTTOU, SIG_IGN);
    signal(SIGTTIN, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);

    struct sigaction sig;

    sig.sa_handler = SIG_IGN;
    sig.sa_flags = 0;
    sigemptyset(&sig.sa_mask);
    sigaction(SIGHUP, &sig, NULL);
#endif	
    return 0;
}


static void Usage(char *prgname)
{
    printf("==>> Usage: \n");
    printf("      %s [start | stop | ver]\n", prgname);
    //    printf("Parameters:\n");
    printf("Examples:\n");
    printf("      --> %s  start                          ... Startup Service\n", prgname);
    printf("      --> %s  stop                           ... Shutdown Service\n", prgname);
    printf("      --> %s  version                        ... Show version\n", prgname);
    printf(" Press any key to continue...\n");
    getchar();
}

static void task_kill()
{
    char szCmd[128] = { 0 };
    int pid = iGetPid();
#ifdef _WIN32
    sprintf(szCmd, "taskkill /PID %d /F", pid);
#else
    sprintf(szCmd, "kill -9 %d >/dev/null 2>&1", pid);
#endif
    system(szCmd);
}


#if 1
int main(int argc, char* argv[])
{
    printf("单位:[%s]\n", "mm/s²");
    printf_s("单位:[%s]\n", "mm/s²"); 
    cout << "单位:" << "mm / s²" << endl;

    if (argc != 2) {
        Usage(argv[0]);
        return 0;
    }
    if (argc == 2) {
        if (!stringcasecmp("start", argv[1])) {
            int i = 0;
            is_down = 1;

            if (RET_OK != loadServiceEvent()) return 0;    // 加载运行配置
            HTStartBackgroundProcess();
            HTInitThreadHandle();
            vSetPid();  // 记录PID

            ht_pthread_create_background(&thread_handle_cache_proc, thread_cache_proc, NULL);         // 内存数据同步线程
            //ht_pthread_create_background(&thread_handle_file_parser, thread_file_parser_proc, NULL);   // 内存数据同步线程
            ht_pthread_create_background(&thread_handle_database_proc, thread_database_proc, NULL);       // 检查数据入库线程
            ht_pthread_create_background(&thread_handle_dbalarm_proc, thread_dbalarm_proc, NULL);       // 实时告警入库线程
#if 1
            if (g_TConfig.getCommProtocol() == 1)
                ht_pthread_create_background(&thread_handle_modbus_recv, thread_modbus_service_proc, NULL);   // Modbus接收线程
            else if (g_TConfig.getCommProtocol() == 2)
                ht_pthread_create_background(&thread_handle_iec61850_manager_proc, thread_iec61850_manager_proc, NULL);   // IEC61850接收线程
            else {
                vPrtLogMsg(LOG_ERROR, 0, "Communication protocol not configure,please check protocol config...");
                return 0;
            }
#else       
            pthread_t thread_handle_getcomtrade_files;
            ht_pthread_create_background(&thread_handle_getcomtrade_files, thread_iec61850_getcomtrade_files, NULL);
#endif
            printf("Service start ...... OK\n");
            while (1) {
                if (!is_down) break;
                _SLEEP(2000);
            }
            vPrtLogMsg(LOG_DEBUG, 0, "free manager database connection pool:%s/%s@%s successed!",
                g_TConfig.getdbUserName(), g_TConfig.getdbUserPass(), g_TConfig.getdbName());
            vPrtLogMsg(LOG_DEBUG, 0, "HTService shutdown completed immediately!");
            vFreeLogMutex(); // 关闭log文件锁与句柄
            return 0;
        }
        if (!stringcasecmp("stop", argv[1])) {
            task_kill();
            printf("Service stop ...... OK\n");
            return 0;
        }
        if (!stringcasecmp("version", argv[1])) {
            task_kill();
            printf("%s : %s\n", argv[0], HT_VERSION_NO);
            return 0;
        }
    }
    Usage(argv[0]);
    return 0;
}
#else

int main(int argc, char *argv[])
{
    char st[32] = { 0 };
    char et[32] = { 0 };
    //if (RET_OK != loadServiceEvent()) return 0;    // 加载运行配置
    tint64 dl = atoll("20191008132154");

    char inbuf[] = "主变1通道A项.";
    char out[128] = { 0 };
    printf("%s\n", inbuf);
    utf8_to_gbk(inbuf, strlen(inbuf), out, sizeof(out));
    printf("%s\n", out);
    char str[128] = { 0 };
    gbk_to_utf8(out, strlen(out), str, sizeof(str));
    printf("%s\n", str);

    vGetHostTimeFmtOnMillsecond(st);
    vGetHostTimeFmtOnMillsecond(et);
    printf("\nPress any key to exit! use time=%s  %s)\n", st, et);
    getchar();
    return 0;
}
#endif


