| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- /***************************************************************************
- * Licensed Materials - Property of IBM
- * Copyright IBM Corp. 2013 All rights reserved.
- *
- * Source filename : dc.c
- * Description : Read records from files and send the contain to TO by TTAPI
- *
- * Parameter :
- * 1 start mode: 0- automatic mode, start by crontab; 1- re-run modle;
- * 2 DC monitoring target file path;
- * 3 DC monitoring target filename;
- * 4 servername, on which the program runs
- * 5 send log data mode, 1-TTAPI mode 2-Socket mode 3-Mixed mode with TTAPI & Socket
- *
- * Author : Wang An Nian
- *
- * Update History
- * DATE OWNER DESCRIPTION
- * ----------- ------------ -----------
- * 2012-11-06 Wang An Nian Generated
- * 2013-11-06 Wang An Nian Domestic
- * 2014-xx-xx Wang An Nian While list Function added
- * 2014-08-18 Wang An Nian MCIS TXN fillter added -p403
- * 1 if connect failed then retry socket,if socket send fail then retry socket
- * 2 add MCIS white name list filter function
- * 3 SIGPIPE ignored
- * 4 if monitored file is null, do not exit and wait till life cycle ended
- *
- * 2014-09-xx Wang An Nian Euro Africa modification
- * 5 socket sending for abroad transactions ( have not finished yet)
- *
- * 2014-12-30 Li Bo Feng Fix problems & Code Formatting
- * 1. 调整代码可读性,不改变处理逻辑
- * 代码函数分割
- * 常量定义,结构定义 dc.h
- * 通用函数 dc_code
- * 参数处理 dc_args
- * 网络直连发送处理 dc_socket
- * TT发送处理 dc_ttapi
- * 文件缓存处理 dc_file_buffer
- * 目标数据处理过程 dc_target
- * 主程序 dc.c
- * 2. 修改文件监控轮询时间
- * 原来检查文件是否存在间隔时间为 2 分钟, 改为 10 秒
- * 原来检查文件是否有内容间隔时间为 1 分钟, 改为 10 秒
- * 原来检查文件内容是否为当前监控周期内容间隔时间为 1 分钟, 改为 10 秒
- * 原来检查文件内容是否有新增内容间隔时间为 5 秒,保持为 5 秒
- * 3. 去掉再运行模式 - 从文件尾读取交易流水日志数据
- * 因为实际代码已经不支持该模式,参数已经不起作用
- * 4. 增加内存释放
- * 动态申请的内存,需要释放
- *
- * 2015-1-6 Li Bo Feng Code structure Formatting & File bufferred reading
- * 1. 调整代码结构
- * 合并重复代码
- * 简化代码逻辑
- * 增加函数返回码
- * 2. 增加扫描内容控制方式,依据
- * 方便测试期间回放旧数据,配置依据环境变量
- * SCAN_BEGIN_TIME=1970-1-1 00:00:00
- * SCAN_END_TIME=1970-1-1 00:00:00
- * 根据起始时间点、结束时间点、数据时间、当前时间决定数据是否发送
- * 根据数据交易码白名单决定数据发送目标
- * 3. 增加数据回放时间同步功能
- * 回放旧数据时,保持数据扫描周期与数据时间一致,精确到 DATA_SCAN_INTERVAL_SECONDS = 10 秒
- * 4. 增加文件缓存功能
- * 增加 FileBuffer 基础功能
- * 一次读入整块内容
- * 5. 增加文件变更重读功能
- * 文件内容发生变化(非追加变化,内容修改或减少),重新读取文件内容
- * 6. 增加文件内容校验功能
- * 每次读取内容时,重复读取部分上次缓存内容,比较两次读取内容的重叠区域,以此判定文件内容是否改变
- * 7. 增加文件定时刷新功能
- * 回放旧数据,系统处于等待数据周期时,及时发现数据变化
- *
- * 2015-1-13 Li Bo Feng new function & Performance Optimizing
- * 1. 增加 Socket 发送心跳功能
- * 心跳间隔 NETWORK_IDLE_HEARTBEAT_SECONDS = 10 秒
- * 2. 调整程序日志输出内容
- * 增加可读性
- * 增加日志分类输出: Error Metrics State Detail Flow
- * 3. 增加处理状态控制
- * 用状态控制取代逻辑控制,简化数据处理逻辑
- *
- * 2015-1-15 Li Bo Feng new function & Performance Optimizing
- * 1. 数据扫描性能优化
- * 运行参数集中管理功能
- * 通过 key-value Mapping 结构存储配置信息
- * 提高白名单及编码转换匹配效率
- *
- * 2015-1-26 Li Bo Feng
- * 1. 调整启动参数
- * 第5个启动参数 send_mode, 形式改为下列各参数的16进制数值组合
- * 1000 SEND_MODE_ABROAD_SOCKET
- * 0100 SEND_MODE_DOMESTIC_SOCKET
- * 0010 SEND_MODE_ABROAD_TTAPI
- * 0001 SEND_MODE_DOMESTIC_TTAPI
- * 对应的服务器(地址:端口)设置关键字改为
- * SOCKET_ABROAD_SERVER="地址:端口"
- * SOCKET_DOMESTIC_SERVER="地址:端口"
- * TTAPI_ABROAD_SERVER="tcp:地址:端口"
- * TTAPI_DOMESTIC_SERVER="tcp:地址:端口"
- * 2. 功能调整
- * 根据配置, 可同时发送 国内/海内 Socket/TTAPI
- *
- * 2015-2-2 Li Bo Feng
- * 1. 增加TTAPI输出字段内容
- * ChannelID (Added Field) Channel and its transaction id information, only have this when it's the first hop
- * ReturnCode (Added Field) Return code in the application log
- * TragetSystem (Added Field) ComponentName(aka. system name) of the target system, only have this for data timetype 02 and 03
- * 2. 调整To Socket Server输出字段内容
- * TragetTxnID (Added Field) 有目标交易码的系统,在LinkSys后增加","分割的目标交易码
- *
- *
- * 2015-2-10 Li Bo Feng
- * 1. 增加调试环境
- * windows-cygwin 环境下可编译执行
- *
- * 2015-3-4 Li Bo Feng
- * 1. DC运行日志文件输出
- * 原日志输出不能以日期时间分割输出,影响实现程序常驻
- * 按指定时间模式分隔,
- * 根据当前时间,修正参数给定的文件名中的时间标记 [YYYY] [MM] [DD] [HH] [MI]
- * 按指定周期删除旧文件
- * 为提高效率进程间需同步删除旧文件
- * 2. 文件名时间模式转换功能
- * 根据当前时间,修正参数给定的文件名中的时间标记 [YYYY] [MM] [DD] [HH] [MI]
- *
- * 2015-3-5 Li Bo Feng
- * 1. 取消环境变量设置 FILESWITCHMODE
- * 以时间模式文件名取代
- * 2. 增加环境变量设置 IDLE_TIMEOUT_HOURS
- * 空闲超时
- *
- * 2015-3-10 Li Bo Feng
- * 1. 互斥运行逻辑
- * 保留原来的定时启动,以系统防止意外终止
- * 如果启动时发现指定日志文件已经有DC进程在处理,立即结束当前进程
- * 2. 执行效率优化
- * 测试机运行 平均CPU占比 0.1% 以下,内存占用 10MB 以下
- *
- * 2015-3-16 Li Bo Feng
- * 1. 时间偏移量修正
- * 通过环境变量设定虚拟当前时间 virtual_current_time
- * VIRTUAL_TIME=缺省为当前时间`date +"%Y-%m-%d %H:%M:%S"`
- * 文件名中的时间与当前时间的偏移量修正,用于目标交易日志文件名及DC运行日志文件名的定时更换
- * 目标交易日志数据时间与当前时间的偏移量修正,用于目标交易日志回放/测试中,同步数据扫描周期
- * 2. 修正文件名模式转换功能
- * 根据虚拟当前时间,修正参数给定的文件名中的时间标记 [YYYY] [MM] [DD] [HH] [MI]
- * 根据系统当前时间,修正参数给定的文件名中的时间标记 [yyyy] [mm] [dd] [hh] [mi]
- * 根据当前进程ID,修正参数给定的文件名中的PID标记 [pid] [PID]
- *
- * 2015-3-17 Li Bo Feng
- * 1. 调整启动参数
- * 合并参数 file_path 和 file_name,以便于进程查询处理
- * 2. 调整启动参数
- * 参数 send_mode, 形式改为下列各参数的标记字符组合,以增加可读性,如:AS|DS
- * AS SEND_MODE_ABROAD_SOCKET
- * DS SEND_MODE_DOMESTIC_SOCKET
- * AT SEND_MODE_ABROAD_TTAPI
- * DT SEND_MODE_DOMESTIC_TTAPI
- * 对应的服务器(地址:端口)设置在config.map文件中配置,根据业务需求调整配置关键字如下:
- * socket.server.abroad.NFXS=地址:端口
- * socket.server.abroad.BOCNET=地址:端口
- * socket.server.domestic.BOCNET=地址:端口
- * ttapi.server.abroad=tcp:地址:端口
- * ttapi.server.domestic=tcp:地址:端口
- *
- * 2015-3-19 Li Bo Feng
- * 1. 增加按时间同步扫描功能
- * 扫描数据的时间与虚拟当前时间同步
- * SCAN_DATA_BY_TIME=default 1 :scan data by virtual time / 0 :scan data from top of file and immediately begin.
- *
- * 2015-3-25
- * 1. 持续运行测试
- * date etime cputime rss
- * 2015-3-23 3-01:33:10 00:00:24 1952
- * 2015-3-25 5-03:38:34 00:00:40 1952
- * 2015-3-26 6-05:36:11 00:00:48 1952
- * 2015-3-30 10-07:39:12 00:01:20 1952
- *
- *
- * 2015-3-30 Li Bo Feng
- * 1. 调整参数,增加运行参数 SysName,AppName,ServerName,InstanceName
- * 解锁与文件名的关联,避免每个系统的规则不一样导致的程序硬代码
- *
- *
- * 2015-4-6 Li Bo Feng
- * 1. Fix内存泄露问题
- * 删除旧日志时,扫描目录功能(scandir)导致内存泄露
- * 重写,改用readdir功能扫描目录.
- * 2. 压力测试
- * 同时开启36进程,持续运行5天,系统状态正常
- * 3. 修改amake脚本,同时打包三个版本: 测试,演练,生产.
- * 4. 修改dc.sh启动脚本,根据task.lst自动选择不同运行环境参数
- * task.lst中可同时配置所有环境的运行参数
- *
- * 2015-4-16 Li Bo Feng
- * 1. 发布版本 3.0
- *
- *
- * 2015-5-8 Li Bo Feng
- * 1. 应用交易日志输出一次写盘信息不完整,导致不能完整读取一行日志记录
- * 需要在读取记录不完整(没有换行符)的情况下,需要等待数据完整后,再进行数据解析
- * 2. 等待数据完整中,如果发现新交易日志文件已经产生,则直接解析最后的不完整记录,并放弃等待
- * 等待时间 15 ~ 20秒 =
- * 数据文件再刷新间隔 TIMEOUT_REFRESH_FILE_BUFFER_SECONDS 5秒
- * 等待文件变更间隔 WAIT_FOR_FILE_CHANGE_SECONDS 10秒
- * 数据扫描间隔 DATA_SCAN_INTL_SECONDS 5秒
- *
- * 2015-5-11 Li Bo Feng
- * 1. 发布版本 3.1
- *
- * 2015-9-2 Li Bo Feng
- * 1. 增加程序注释信息
- * 2. 调整程序格式
- *
- * 2015-11-23 Li Bo Feng
- * 1. 修正叠加数据的容错处理
- * 当文件切换时,读取到的内容可能发生错乱
- * 增加更严格的记录数据格式判断,包括:
- * 记录时间格式判断
- * 记录重叠判断
- * 2. 增加缺省程序日志的输出
- * 缺省输出告警信息:
- * 忽略的记录
- * 等待数据状态
- * 3. 发布版本 3.2
- *
- ***************************************************************************/
- /*
- * 环境变量说明:
- * VIRTUAL_TIME
- * 虚拟当前时间,用于确定虚拟当前时间和系统当前时间的时间偏移,缺省值与系统当前时间一致
- *
- * SCAN_BEGIN_TIME
- * 扫描数据开始时间点,格式为yyyy-mm-dd hh:mi:ss,缺省空表示从虚拟当前时间开始扫描数据
- * SCAN_END_TIME
- * 扫描数据结束时间点,格式为yyyy-mm-dd hh:mi:ss,缺省空表示不限制结束时间
- * IDLE_TIMEOUT_HOURS
- * 空闲超时(小时数),待处理数据没有任何变化,导致空闲超时,程序自动退出,缺省为0表示不设置空闲超时
- *
- * TXNCDFILE
- * 交易码白名单配置文件
- * TXNFILE
- * 交易码/交易名称映射配置文件
- * RTNCDFILE
- * 交易返回码配置文件
- * FSYSMATCH
- * 应用系统别名配置文件
- * CONFIG_FILE
- * mapping样式的通用配置文件
- * 渠道信息配置
- * channel.BOCNET=BOCNET
- * 数据接收服务器地址端口
- * socket.server.domestic.BOCNET=127.0.0.1:5001
- * socket.server.abroad.BOCNET=127.0.0.1:5001
- * socket.server.abroad.NFXS=127.0.0.1:5005
- * ttapi.server.domestic=tcp:127.0.0.1:5455
- * ttapi.server.abroad=tcp:127.0.0.1:5455
- *
- * ABLOG_KEEP_HOURS
- * 本程序(DC)运行日志保留时间,缺省120小时(5天)
- * ABLOG_STDOUT
- * 是否输出到标准输出,0 不输出, 缺省为 1 输出
- * ABLOG_FILE
- * 本程序(DC)运行日志输出文件
- * 如果不指定输出文件,日志信息会输出到标准输出(忽略ABLOG_STDOUT指定)
- * 文件名支持时间模式替换,自动修正参数给定的文件名中的替换标记
- * 模式中可以替换内容包括:
- * [PID] 用当前进程id
- * [YYYY] 虚拟当前时间的年
- * [yyyy] 系统当前时间的年
- * [MM] 虚拟当前时间的月
- * [mm] 系统当前时间的月
- * [DD] 虚拟当前时间的日
- * [dd] 系统当前时间的日
- * [HH] 虚拟当前时间的时
- * [hh] 系统当前时间的时
- * [MI] 虚拟当前时间的分
- * [mi] 系统当前时间的分
- * ABLOG_CLASS
- * 本程序(DC)运行日志输出内容,由下列标识文字用逗号分隔组合而成,如"Error,Metrics"
- * All 缺省,全部信息
- * Error 程序运行错误信息
- * Metrics 程序运行过程重要提示信息
- * State 程序运行状态提示信息
- * Detail 程序运行详细信息
- * Flow 程序运行流程
- * Flow_Public 公共的程序运行流程
- * Flow_Private 私有的程序运行流程
- * Flow_Restricted 受限的程序运行流程
- * Flow_Minor 次要的程序运行流程
- *
- * SCAN_DATA_BY_TIME
- * =default 1 :scan data by virtual time / 0 :scan data from top of file and immediately begin.
- *
- * VALIDATE_DATA
- * 是否验证数据,0 不验证,缺省 1 验证
- * CHECK_FILE_STATUS
- * 检查文件状态
- * 读文件前,是否检查文件非追加变更状态(删除,改名,裁减,重写,修改),
- * 缺省0不检查,缓存数据使用完后,继续读取文件内容过程中,才会发现文件非追加变更(删除,裁减,重写,修改),改名不影响数据继续读取
- * 1检查,检查到文件发生非追加变更立即重读,放弃缓存中的数据,测试或回放旧数据时可以通过此设置
- *
- */
- /*
- * 数据扫描周期设定方式:
- * 开始条件:
- * 1. 从指定数据时间点开始发送
- * SCAN_BEGIN_TIME=yyyy-MM-dd HH:mm:ss
- * SCAN_BEGIN_TIME=0 //不限开始时间,从文件头开始
- *
- * 处理频率/周期:
- * 1. 按分钟对应数据发生速率,精确到 5 秒
- *
- * 结束条件:
- * 1. 到达指定数据时间点结束
- * SCAN_END_TIME=yyyy-MM-dd HH:mm:ss
- * SCAN_END_TIME=0 //持续运行,程序不会退出
- * 2. 空闲超时(小时)
- * IDLE_TIMEOUT_HOURS=0 // 待处理数据没有任何变化,导致空闲超时,程序自动退出
- *
- */
- #include "dc.h"
- #include "dc_code.h"
- #include "dc_args.h"
- #include "dc_socket.h"
- #include "dc_ttapi.h"
- #include "dc_target.h"
- #include "ab_map.h"
- /*------------------------------------------------------------------------
- * MAIN()
- *
- * 运行参数说明:
- * scan_from_new
- * 第1个参数,是否只扫描新增内容, 0 从头开始扫描数据, 1从文件尾开始扫描新产生的数据
- * 在打开文件时就已经确定,读取位置,优先级很高,但只有刚开始时起作用,文件切换或重读时,此参数将失去意义.
- * log_file_path
- * 第2个参数,目标日志文件路径,文件名支持模式替换
- * 模式中可以替换内容包括:
- * [PID] 用当前进程id
- * [YYYY] 虚拟当前时间的年
- * [yyyy] 系统当前时间的年
- * [MM] 虚拟当前时间的月
- * [mm] 系统当前时间的月
- * [DD] 虚拟当前时间的日
- * [dd] 系统当前时间的日
- * [HH] 虚拟当前时间的时
- * [hh] 系统当前时间的时
- * [MI] 虚拟当前时间的分
- * [mi] 系统当前时间的分
- * sys_name
- * 第3个参数,系统名称
- * app_name
- * 第4个参数,应用名称
- * server_name
- * 第5个参数,应用服务器名称
- * istance_name
- * 第6个参数,实例名称
- * send_mode
- * 第7个参数,数据发送模式,下列各参数的标记字符组合,如:AS|DS
- * AS SEND_MODE_ABROAD_SOCKET
- * DS SEND_MODE_DOMESTIC_SOCKET
- * AT SEND_MODE_ABROAD_TTAPI
- * DT SEND_MODE_DOMESTIC_TTAPI
- *
- * RTN:
- * others - reference to return code
- *
- *------------------------------------------------------------------------*/
- int main(int argc, char *argv[])
- {
- ABLOG_Entry(Public, main);
- DEFINE_DC_RETURN_CODE();
- int iRtn;
- // 防止因网络异常导致程序退出
- // 当服务器close一个连接时,若client端接着发数据。根据TCP 协议的规定,会收到一个RST响应,
- // client再往这个服务器发送数据时,系统会发出一个SIGPIPE信号给进程,告诉进程这个连接已经断开了,不要再写了。
- // 根据信号的默认处理规则SIGPIPE信号的默认执行动作是terminate(终止、退出),所以client会退出。
- // 若不想客户端退出可以把SIGPIPE设为SIG_IGN
- // 这时SIGPIPE交给了系统处理。
- // 服务器采用了fork的话,要收集垃圾进程,防止僵尸进程的产生,可以这样处理:
- // signal(SIGCHLD,SIG_IGN); 交给系统init去回收。
- // 这里子进程就不会产生僵尸进程了。
- signal(SIGPIPE, SIG_IGN);
- // 收集验证启动参数
- iRtn = check_args(argc, argv);
- if (iRtn == DC_RET_OK)
- {
- ABLOG_Printf(Metrics,
- (ABLOG,"[I] <---------------------------------------------------------------->"));
- ABLOG_Printf(Metrics,
- (ABLOG,"[I] <------------------------ Log DC Started ------------------------>"));
- ABLOG_Printf(Metrics,
- (ABLOG,"[I] <---------------------------------------------------------------->"));
- // 程序日志文件变更时,打印程序运行参数信息
- on_ablog_reinitialized = print_args;
- // DC处理主过程
- iRtn = main_process();
- ABLOG_Printf(Metrics,
- (ABLOG,"[I] <------------------------- Log DC end -------------------------->"));
- }
- // 清理启动参数使用的资源
- clear_args();
- // 清理ab_code 使用的资源
- clear_coding();
- // 数据超时退出属于正常退出
- ABLOG_Return_Code(iRtn == DC_RET_TIMEOUT_QUIT?DC_RET_OK:iRtn);
- }
|