Commit 443c9bf2 by wuyang.zou

<1> 插件初始化登录ODS优化;[守护程序存在,不能及时收到POS的初始化数据]

插件收到POS的初始化数据 则更新本地文件进行持久化; 【自测OK; FileName: PosRequestInitData.json 】
插件启动后 读取初始化信息文件,如果6分钟没有收到初始数据则 检测 POS的接受消息端口是否正常监听,是则进行模拟登录;【自测OK; 端口正常:OK; 端口异常:OK ;】

<2> 插件针对启动项文件是否包含插件启动项信息进行读取,并伴随登录接口将数据上传【自测OK; KEY: plugin_boot_config 】

<3> 插件兜底长连接假死的自检:存在待推送订单且长时间没有接受到推送则进行长连接主动断开后重连;【自测OK】
10倍心跳周期中无推送订单记录(6分钟) 读取ODS心跳数据待推送订单数量[wait_push_order_sum 小于10倍心跳周期前的数量];
则断开重连(同时附带重连原因: KEY: plugin_relogin_reason );
parent cb5cd820
# CMake 最低版本要求
cmake_minimum_required (VERSION 2.8)
# 新增两个宏定义
#SET(CMAKE_BUILD_TYPE "RelWithDebInfo")
#SET(CMAKE_INSTALL_PREFIX "/usr/local")
# 指定gcc
SET(CMAKE_C_COMPILER "/usr/bin/gcc")
SET(CMAKE_CXX_COMPILER "/usr/bin/g++")
# 项目名称
project (proTakeaway)
#生成可执行文件名称
SET(TARGET_NAME takeaway)
#支持C++11
add_compile_options(-std=c++11)
#设置执行文件输出目录
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#设置编译后的可执行程序优先调用本地库(和可执行程序在同一个文件夹下的库)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
SET(CMAKE_SKIP_BUILD_RPATH TRUE)
SET(CMAKE_INSTALL_RPATH "\$ORIGIN")
# 查找目录下的所有源文件,并将名称保存到 DIR_ 变量中
aux_source_directory(./3rdParty/easylogging/ DIR_LOGS)
aux_source_directory(./src/ DIR_SRCS)
aux_source_directory(./utility/ DIR_UTILITY)
# 指定生成目标
add_executable (${TARGET_NAME} ${DIR_LOGS} ${DIR_SRCS} ${DIR_UTILITY})
# 添加链接库
target_link_libraries(${TARGET_NAME} pthread)
......@@ -40,4 +40,15 @@ products[i].specs[j] 数组对象字段: extraPrice:套餐子商品加价价格
3.8 2021-07-26 wuyang.zou Version: 1.2.7-2 RC //新增属性字段:
orderCoupons[i] 数组对象字段: 仅orderCoupons[i].type="P"->是商品券时存在 ①bonusDayBusinessType:日商类型 ->入门店(S)默认值,入总部(T); ② bonusDayBusinessAmt:日商金(单位分);
3. 9 2021-10-13 wuyang.zou Version: 1.2.8 RC //新增插件的备注 属性字段;
\ No newline at end of file
3.9 2021-10-13 wuyang.zou Version: 1.2.8 RC //新增插件的备注 属性字段;
4.0 2022-06-30 wuyang.zou Version: 1.3.1 RC
<4.0.1> 插件初始化登录ODS优化;[守护程序存在,不能及时收到POS的初始化数据]
插件收到POS的初始化数据 则更新本地文件进行持久化; 【自测OK; FileName: PosRequestInitData.json 】
插件启动后 读取初始化信息文件,如果6分钟没有收到初始数据则 检测 POS的接受消息端口是否正常监听,是则进行模拟登录;【自测OK; 端口正常:OK; 端口异常:OK ;】
<4.0.2> 插件针对启动项文件是否包含插件启动项信息进行读取,并伴随登录接口将数据上传【自测OK; KEY: plugin_boot_config 】
<4.0.3> 插件兜底长连接假死的自检:存在待推送订单且长时间没有接受到推送则进行长连接主动断开后重连;【自测OK】
10倍心跳周期中无推送订单记录(6分钟) 读取ODS心跳数据待推送订单数量[wait_push_order_sum 小于10倍心跳周期前的数量];
则断开重连(同时附带重连原因: KEY: plugin_relogin_reason );
\ No newline at end of file
{"fm_cmd":1000,"listen_port":24445,"storeId":"208888","pos_id":"5","operator_id":"zouwuyang","is_master":false,"plugin_comment":"123.60.107.183","ver":1,"version":"1.3.1 RC"}
\ No newline at end of file
[SYS]
port=24446
#<<贝瑞>>
#config.ini 文件 中 [ODS] 模块中的
#(生产环境外网 IP)
#ip: 103.13.247.77
#(测试环境外网 IP [内网IP:10.0.103.116] )
#ip: 103.13.247.78
#<<全家>
#config.ini 文件 中 [ODS] 模块中的
#(生产环境外网 IP [内网IP:10.0.100.70] )
#ip: 103.13.247.72
#(测试环境外网 IP [内网IP:10.0.102.14] )
#ip: 103.13.247.73
#(生产环境外网 IP [内网IP:10.251.100.70] )
#ip: 123.60.107.182
#(测试环境外网 IP [内网IP:10.251.102.14] )
#ip: 123.60.107.183
[ODS]
ip=api.ods.chinafamilymart.com.cn
......
@echo OFF
if not "%~1"=="p" start /min cmd.exe /c %0 p&exit
set _selfAppName=cmd
set _task=takeaway_d.exe
set _svr=E:\zouwuyang\FamilyMart\PosPluginClient\familyMart_takeaway\bin\takeaway_d.exe
set _svrWorkDir=E:\zouwuyang\FamilyMart\PosPluginClient\familyMart_takeaway\bin\
echo ******** %time% Daemon - Daemon Plugin Bat Begin Running ...******** >nul
rem 检查 Daemon Script Running Or Not[ Can't gt 1, Will Been Call More 2];
for /f "delims=" %%a in ('tasklist /nh^|find /i "%_selfAppName%" /c') do set _daemonCount=%%a
echo ******** %time% CheckOrStart:: %_daemonCount% ******** >nul
if %_daemonCount% geq 3 (
echo ******** %time% CheckOrStart:: Daemon Second Running, Count geq 3 [first equ 2] Then Exit ...******** >nul
exit
) else (
echo ******** %time% CheckOrStart:: Daemon Fist Running, Then Go ...******** >nul
)
:CheckOrStart
rem 检查 Plugin App Running Or Not;
ping 127.0.0.257 -n 30 >nul & tasklist /nh | findstr /i %_task% >nul
:: echo %ERRORLEVEL% >nul
if ERRORLEVEL 1 (
echo %ERRORLEVEL%
echo ******** %time% CheckOrStart:: App Not Running ...******** >nul & goto StartSvr
) else (
echo %ERRORLEVEL%
echo ******** %time% CheckOrStart:: App Running ...******** >nul & goto CheckAgain
)
:StartSvr
echo ******** %time% StartSvr:: Restart Plugin Begin...******** >nul
cd %_svrWorkDir%
start %_svr%
echo ******** %time% StartSvr:: Restart Plugin End ...******** >nul
ping 127.0.0.257 -n 20 >nul & goto CheckOrStart
:CheckAgain
echo ******** %time% CheckAgain:: Plugin App Running, Keep Check After 200s ...******** >nul
ping 127.0.0.257 -n 20 >nul & goto CheckOrStart
\ No newline at end of file
#!/bin/sh
cd /opt/pos/zhclient
nohup /opt/pos/zhclient/zh_client > /dev/null &
nohup /opt/pos/fmtakeout/takeaway_d.exe > /dev/null &
export LANG=zh_CN.GBK
export LC_ALL=zh_CN.GBK
CREAM_JAR_DIR=/opt/pos/cream
CREAM_JAR_BAK_DIR=/opt/pos/cream_bak
GROOVY_HOME=/opt/pos/groovy-1.7
POS_HOME=/opt/pos
cd $POS_HOME
export DISPLAY=:0.0
/usr/X11R6/bin/xhost +
/usr/bin/x11vnc -forever -shared -ncache 10 -clip 800x600+0+0 -display :0 &
sh bin/setvolume.sh
sh bin/deploy_sandini.sh
/bin/chmod a+rw /dev/ttyS*
#/bin/chmod a+x bin/catAdapter
/sbin/modprobe lp
# Classpath for Cream --
if test -n "$CLASSPATH" ; then
CLASSPATH="${CREAM_JAR_DIR}/cream.jar:${POS_HOME}/conf:${CLASSPATH}"
else
CLASSPATH="${CREAM_JAR_DIR}/cream.jar:${POS_HOME}/conf"
fi
CLASSPATH="${CLASSPATH}:${GROOVY_HOME}/embeddable/groovy-all-1.7.10.jar"
for n in ${POS_HOME}/lib/*.jar ; do
CLASSPATH="${n}:${CLASSPATH}"
done
# Upgrade cream --
if [ -f cream_hot.jar ]; then
/bin/cp -f cream_hot.jar ${CREAM_JAR_DIR}/cream.jar
/bin/mv -f cream_hot.jar ${CREAM_JAR_BAK_DIR}/cream_hot.jar.`date +%Y-%m-%d`
fi
if [ -f cream.jar.pack.gz ]; then
/usr/bin/unpack200 cream.jar.pack.gz ${CREAM_JAR_DIR}/cream.jar
/bin/mv -f cream.jar.pack.gz ${CREAM_JAR_BAK_DIR}/cream.jar.pack.gz.`date +%Y-%m-%d`
fi
# Run Cream POS --
LD_LIBRARY_PATH=${POS_HOME}/native:${POS_HOME}
export LD_LIBRARY_PATH
MAIN_CLASS=hyi.cream.POSTerminalApplication
#MAIN_CLASS=hyi.cream.Bootstrapper
/usr/bin/java -Duser.language="zh" -Duser.region="CN" -DuseFakeCAT=false -DskipConnectServer=true \
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 \
-Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=192.168.0.207 \
-Djava.library.path=${POS_HOME}/native -Dfile.encoding=GBK -cp $CLASSPATH ${MAIN_CLASS} \
-screensize 800x600 \
>> log/stdout.log 2>> log/stderr.log
# Shrink log files
tail -c 50240000 log/stdout.log > log/stdout_.log; mv -f log/stdout_.log log/stdout.log
tail -c 50240000 log/stderr.log > log/stderr_.log; mv -f log/stderr_.log log/stderr.log
tail -c 50240000 log/player.log > log/player_.log; mv -f log/player_.log log/player.log
tail -c 50240000 log/trace_state.log > log/trace_state_.log; mv -f log/trace_state_.log log/trace_state.log
rm -f /root/.serverauth*
pkill x11vnc

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
# Blend for Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "familyMart_takeaway", "familyMart_takeaway\familyMart_takeaway.vcxproj", "{B24A017B-387C-49C2-A321-3554AD9A1D48}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "takeaway_ut", "takeaway_ut\takeaway_ut.vcxproj", "{395675BD-3E73-4656-A9D0-24A94B28C20C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "fmPluginDaemon", "fmPluginDaemon", "{54A3388C-3886-46E1-87A9-6865E87582E4}"
ProjectSection(SolutionItems) = preProject
fmPluginDaemon\fmPluginDaemon.c = fmPluginDaemon\fmPluginDaemon.c
fmPluginDaemon\Makefile = fmPluginDaemon\Makefile
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
......
......@@ -155,6 +155,7 @@
<ClInclude Include="..\base\BaseDefine.h" />
<ClInclude Include="..\base\CommonStruct.h" />
<ClInclude Include="..\src\JsonModule.h" />
<ClInclude Include="..\src\PosHandle.h" />
<ClInclude Include="..\src\SocketModule.h" />
<ClInclude Include="..\utility\utility.h" />
<ClInclude Include="..\utility\zini.h" />
......@@ -163,6 +164,7 @@
<ClCompile Include="..\3rdParty\easylogging\easylogging++.cc" />
<ClCompile Include="..\src\JsonModule.cpp" />
<ClCompile Include="..\src\main.cpp" />
<ClCompile Include="..\src\PosHandle.cpp" />
<ClCompile Include="..\src\SocketModule.cpp" />
<ClCompile Include="..\utility\utility.cpp" />
<ClCompile Include="..\utility\zini.cpp" />
......
......@@ -51,6 +51,9 @@
<ClInclude Include="..\src\SocketModule.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\PosHandle.h">
<Filter>src</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\3rdParty\easylogging\easylogging++.cc">
......@@ -71,5 +74,8 @@
<ClCompile Include="..\src\SocketModule.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\PosHandle.cpp">
<Filter>src</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
fmPluginDaemon: fmPluginDaemon.o
gcc -o fmPluginDaemon fmPluginDaemon.o
fmPluginDaemon.o: fmPluginDaemon.c
gcc -c fmPluginDaemon.c
clean:
rm *.o
rm fmPluginDaemon
\ No newline at end of file
@echo OFF
if not "%~1"=="p" start /min cmd.exe /c %0 p&exit
set _selfAppName=cmd
set _task=takeaway_d.exe
set _svr=E:\zouwuyang\FamilyMart\PosPluginClient\familyMart_takeaway\bin\takeaway_d.exe
set _svrWorkDir=E:\zouwuyang\FamilyMart\PosPluginClient\familyMart_takeaway\bin\
echo ******** %time% Daemon - Daemon Plugin Bat Begin Running ...******** >nul
rem 检查 Daemon Script Running Or Not[ Can't gt 1, Will Been Call More 2];
for /f "delims=" %%a in ('tasklist /nh^|find /i "%_selfAppName%" /c') do set _daemonCount=%%a
echo ******** %time% CheckOrStart:: %_daemonCount% ******** >nul
if %_daemonCount% geq 3 (
echo ******** %time% CheckOrStart:: Daemon Second Running, Count geq 3 [first equ 2] Then Exit ...******** >nul
exit
) else (
echo ******** %time% CheckOrStart:: Daemon Fist Running, Then Go ...******** >nul
)
:CheckOrStart
rem 检查 Plugin App Running Or Not;
ping 127.0.0.257 -n 30 >nul & tasklist /nh | findstr /i %_task% >nul
:: echo %ERRORLEVEL% >nul
if ERRORLEVEL 1 (
echo %ERRORLEVEL%
echo ******** %time% CheckOrStart:: App Not Running ...******** >nul & goto StartSvr
) else (
echo %ERRORLEVEL%
echo ******** %time% CheckOrStart:: App Running ...******** >nul & goto CheckAgain
)
:StartSvr
echo ******** %time% StartSvr:: Restart Plugin Begin...******** >nul
cd %_svrWorkDir%
start %_svr%
echo ******** %time% StartSvr:: Restart Plugin End ...******** >nul
ping 127.0.0.257 -n 20 >nul & goto CheckOrStart
:CheckAgain
echo ******** %time% CheckAgain:: Plugin App Running, Keep Check After 200s ...******** >nul
ping 127.0.0.257 -n 20 >nul & goto CheckOrStart
\ No newline at end of file
#include<unistd.h>
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/param.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<time.h>
#include<sys/wait.h>
#include<fcntl.h>
#include<limits.h>
#define BUFSZ 150
// 监控 App 间隔周期 (单位: s)
#define MONITOR_APP_INTERVAL 60
#define MONITOR_APP_NAME "takeaway"
// POS Real Start Command :: nohup /opt/pos/fmtakeout/takeaway > /dev/null &
#define MONITOR_APP_START_COMMAND "nohup /opt/pos/fmtakeout/takeaway > /dev/null & "
#define MONITOR_APP_RUN_DIR "/opt/pos/zhclient/"
#define MONITOR_LOG_DIR "/opt/pos/fmtakeout/"
#define MONITOR_LOG_NAME "/opt/pos/fmtakeout/fmPluginDaemon.log"
void init_daemon()
{
int pid;
int i;
pid=fork();
if(pid<0)
exit(1); //创建错误,退出
else if(pid>0) //父进程退出
exit(0);
setsid(); //使子进程成为组长
pid=fork();
if(pid>0)
exit(0); //再次退出,使进程不是组长,这样进程就不会打开控制终端
else if(pid<0)
exit(1);
//关闭进程打开的文件句柄
for(i=0;i<NOFILE;i++)
close(i);
chdir(MONITOR_LOG_DIR); //改变目录
umask(0);//重设文件创建的掩码
return;
}
void err_quit(char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
// 判断程序是否在运行
int does_service_work()
{
FILE* fp;
int count;
char buf[BUFSZ];
char command[150];
sprintf(command, "%s%s%s" ,"ps -ef | grep ", MONITOR_APP_NAME , " | grep -v grep | wc -l" );
if((fp = popen(command,"r")) == NULL)
err_quit("popen");
if( (fgets(buf,BUFSZ,fp))!= NULL )
{
count = atoi(buf);
}
pclose(fp);
return count;
}
void main()
{
FILE *fp = NULL;
time_t t;
int count;
init_daemon();
fp=fopen(MONITOR_LOG_NAME,"w+"); //守护程序初次启动,避免日志无限增大,对日志进行覆盖;
if ( fp > 0 ) {
fclose(fp);
fp = NULL;
}
while(1)
{
sleep( MONITOR_APP_INTERVAL ); //等待一分钟再写入
count = does_service_work();
fp=fopen(MONITOR_LOG_NAME,"a"); //为记录后续状态,对日志文件进行追加;
if ( fp != NULL ) {
time(&t);
if(count>0)
{
fprintf(fp,"FmPluginDaemon:: Current Time Is:%s And The Process Exists, The App Count Is %d\n",asctime(localtime(&t)), count); //转换为本地时间输出
fclose(fp);
fp = NULL ;
}
else
{
fprintf(fp,"FmPluginDaemon:: Current Time Is:%s And The Process Does Not Exist, Restart It!\n",asctime(localtime(&t))); //转换为本地时间输出
fclose(fp);
fp = NULL ;
chdir(MONITOR_APP_RUN_DIR); //改变被守护程序启动目录位置,同时也会改变DaemonApp的当前路径;
system(MONITOR_APP_START_COMMAND); //启动服务 注意自己可执行程序的目录
}
} else
{
exit(-1);
}
}
return;
}
\ No newline at end of file
......@@ -8,11 +8,6 @@
#include "../3rdParty/easylogging/easylogging++.h"
#include <iostream>
std::string g_store_id = "";
std::string g_pos_id = "";
bool g_pos_ismaster = false;
std::string g_plugin_comment = "";
using namespace rapidjson;
JsonModule::JsonModule()
......@@ -487,15 +482,32 @@ int JsonModule::isHeartbeatData(IN const char* data)
{
rapidjson::Document document; // 定义一个Document对象
document.Parse(data); // 解析,Parse()无返回值,也不会抛异常
if (document.HasParseError()) // 通过HasParseError()来判断解析是否成功
if (document.HasParseError()) // 通过HasParseError()来判断解析是否成功: 解析失败: 返回 3;
{
LOG(ERROR) << "isHeartbeatData JSON parse error:" << document.GetParseError() << ":" << document.GetErrorOffset();
return 3;
}
if(document.HasMember("fm_cmd")){
if(document["fm_cmd"].GetInt() == 3)
// ODS 正常推送 心跳消息类型;
if(document.HasMember("fm_cmd")) {
if (document["fm_cmd"].GetInt() == 3) {
g_ods_heart_10x_index++;
// 如果报文是心跳数据,且 是10次ODS心跳周期,则读取心跳报文中的待推送订单数;
if (0 == g_ods_heart_10x_index % 10) {
g_ods_wait_push_order_last_sum = g_ods_wait_push_order_this_sum;
if (document.HasMember("wait_push_order_sum")) {
g_ods_wait_push_order_this_sum = document["wait_push_order_sum"].GetInt();
}
else {
g_ods_wait_push_order_this_sum = 0; // 考虑ODS多实例升级过程中: 部分实例有返回,部分实例没有返回,将会导致待推送数据不准确;
}
}
return 1;
}
}
// ODS 正常推送消息类型;
return 2;
}
......@@ -568,7 +580,7 @@ bool JsonModule::convertInitDataPos2Ods(IN const std::string& data, OUT std::str
writer.Int(1);
writer.Key("version");
writer.String(VERSION);
writer.String(g_plugin_version.data() );
writer.EndObject();
......@@ -844,6 +856,7 @@ bool JsonModule::getOdsResponseData(IN int status_code, IN const std::string &ms
int fm_cmd = document1["fm_cmd"].GetInt();
LOG(INFO)<<"fm_cmd:"<<fm_cmd;
bool rlt=false;
if(fm_cmd==REQUEST_TYPE_NEWORDER_PUSH){
rlt=_getOrderResponseJson(posResponse,orderData,odsData,result);
......@@ -920,7 +933,7 @@ bool JsonModule::convertDataPos2Ods(IN const std::string &data, OUT std::string
bool JsonModule::convertDataOds2Pos(IN const std::string &data, OUT std::string &result)
{
bool rlt=true;
int pushType=getPushType(data.c_str());
int pushType=getPosOdsPushType(data.c_str());
if(pushType==ODS_PUSH_TYPE_STOCKWARN){ //库存预警
stockWarnObj warn_obj;
......@@ -1796,15 +1809,16 @@ void JsonModule::_getStockWarnObj(IN const char* json,OUT stockWarnObj &warn_obj
}
}
int JsonModule::getPushType(IN const char* data)
int JsonModule::getPosOdsPushType(IN const char* data)
{
rapidjson::Document document; // 定义一个Document对象
document.Parse(data); // 解析,Parse()无返回值,也不会抛异常
if (document.HasParseError()) // 通过HasParseError()来判断解析是否成功
{
LOG(ERROR) << "getPushType JSON parse error:" << document.GetParseError() << ":" << document.GetErrorOffset();
LOG(ERROR) << "getPosOdsPushType JSON parse error:" << document.GetParseError() << ":" << document.GetErrorOffset();
return 0;
}
if(document.HasMember("fm_cmd")){
return document["fm_cmd"].GetInt();
}
......@@ -1878,6 +1892,8 @@ bool JsonModule::_getOrderResponseJson(IN const std::string& posResponse, IN con
writer.Bool(g_pos_ismaster);
writer.Key("plugin_comment");
writer.String(g_plugin_comment.c_str());
writer.Key("plugin_boot_config");
writer.String(g_posPluginBootConfig.c_str());
writer.Key("child_store_id");
writer.String(child_store_id.c_str());
......@@ -2195,9 +2211,66 @@ void JsonModule::setInitData(IN const char* data)
g_pos_ismaster = document["is_master"].GetBool();
}
void JsonModule::saveLocalPosInitData(IN const char* data)
{
std::string strBinPath = GetProcDir();
std::string strFile = strBinPath + "PosRequestInitData.json";
std::ofstream fileStream(strFile.c_str(), std::ios::binary | std::ios::out );
if (!fileStream.is_open()) {
LOG(ERROR) << "saveLocalPosInitData:: Open File: PosRequestInitData.json Failed ";
return;
}
rapidjson::Document doc;
doc.Parse(data);
if (doc.HasParseError()) {
LOG(ERROR) << "saveLocalPosInitData:: Rapidjson Parse Error :" << doc.GetParseError();
return;
}
fileStream.write(data, std::strlen(data) );
fileStream.close();
return;
}
std::string JsonModule::getLocalPosInitData()
{
std::string strBinPath = GetProcDir();
std::string strFile = strBinPath + "PosRequestInitData.json";
std::ifstream fileStream(strFile.c_str(), std::ios::binary | std::ios::in | std::ios::ate );
if (!fileStream.is_open()) {
LOG(INFO) << "getLocalPosInitData:: Open File: PosRequestInitData.json Failed, May Be Not Exist ";
return "";
}
char * buffer = nullptr; long size;
size = fileStream.tellg();
buffer = new char[size + 1];
fileStream.seekg(0, std::ios::beg);
fileStream.read(buffer, size);
buffer[size] = '\0';
std::string posRequestInitData = buffer;
delete[] buffer; buffer = nullptr;
fileStream.close();
rapidjson::Document doc;
doc.Parse(posRequestInitData.c_str());
if (doc.HasParseError()) {
LOG(ERROR) << "getLocalPosInitData:: Rapidjson Parse Error :" << doc.GetParseError();
return "";
}
return posRequestInitData;
}
std::string JsonModule::getTestOrderJson() {
std::string strBinPath = GetProcDir();
std::string strTestOrderFile = strBinPath += "testOrderJson.json";
std::string strTestOrderFile = strBinPath + "testOrderJson.json";
std::ifstream fileStream(strTestOrderFile.c_str(), std::ios::binary | std::ios::in | std::ios::ate );
if (!fileStream.is_open()) {
......@@ -2213,6 +2286,7 @@ std::string JsonModule::getTestOrderJson() {
buffer[size] = '\0';
std::string testOrderData = buffer;
delete[] buffer; buffer = nullptr;
fileStream.close();
rapidjson::Document doc;
doc.Parse( testOrderData.c_str() );
......
......@@ -7,12 +7,15 @@
#include "../base/CommonStruct.h"
#include "../base/BaseDefine.h"
extern std::string g_plugin_version;
extern std::string g_store_id;
extern std::string g_pos_id;
extern bool g_pos_ismaster;
extern std::string g_plugin_comment;
#define VERSION "1.2.8 RC" //版本号;
extern std::string g_posPluginBootConfig;
extern int g_ods_wait_push_order_this_sum;
extern int g_ods_wait_push_order_last_sum;
extern int g_ods_heart_10x_index;
class JsonModule
......@@ -106,7 +109,7 @@ public:
* 参数:[1]待判断数据
* 返回:...
* */
int getPushType(IN const char* data);
int getPosOdsPushType(IN const char* data);
/* 功能:缓存初始化信息,其它接口需要门店信息字段时可以直接拿取
* 参数:[1]初始化json
......@@ -114,6 +117,21 @@ public:
* */
void setInitData(IN const char* data);
/* 功能:保存POS初始化信息到本地文件,为了插件守护程序 重启插件后直接连接ODS做准备;
* 参数:[1]初始化json
* 返回:...
* */
void saveLocalPosInitData(IN const char* data);
/* 功能:通过本地POS初始化文件 读取到应用程序中,为了插件守护程序 重启插件后直接连接ODS做准备;
* 参数:[1]初始化json
* 返回:...
*/
std::string getLocalPosInitData();
/* 功能: Win32 模式 读取 本地测试订单数据
* 参数:
* 返回: testOrderJson.json 文件的报文数据;
......
#ifndef POS_HANDLE_H
#define POS_HANDLE_H
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include "SocketModule.h"
#include "JsonModule.h"
#include "../utility/utility.h"
#include "../3rdParty/easylogging/easylogging++.h"
#ifdef WIN32
#include <Windows.h>
#else
#include <pthread.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#endif
extern std::string ods_ip;
extern std::string pos_ip;
extern int ods_push_port;
extern int ods_recv_port;
extern int client_listen_port;
extern int pos_listen_port;
extern bool bInitDone;
extern std::string g_init_data;
extern std::string g_init_data_ods_back;
extern std::string g_local_pos_init_data; // 上一次 POS 初始化请求报文 本地化数据;
extern std::string g_set_pos_priority; // 设置pos优先级
extern std::string g_set_pos_priority_ods_back;
extern bool bPriorityDone;
extern TCPClient longConnectionOds;
#ifdef WIN32
extern std::string g_simulator_role;
extern std::string g_simulator_pos_req_data;
extern std::string g_simulator_pos_resp_data;
extern std::string g_plugin_auto_login_init;
extern TCPClient g_simulator_pos_client;
#endif
class PosHandle
{
public:
static PosHandle* getInstance() {
return &handle;
}
static void logRolloutHandler(const char* filename, std::size_t size);
static void getIpByDns(IN std::string &ods_ip);
// 线程处理函数:监听 Pos Send Request;
#ifdef WIN32
static bool PosHandle::simulator_pos_send_init();
static DWORD WINAPI listen_pos_func(LPVOID lpParamter);
#else
static void* listen_pos_func(void* arg);
#endif // WIN32
static bool check_plugin_already_exist();
static bool check_pos_already_exist();
static std::string check_boot_app_enable_str(std::string fileName, std::string appName );
static void kill_origin_process();
//函数,订单信息发送给pos
static bool order_send_to_pos(IN std::string &order_json, IN std::string &ods_json, OUT std::string &back_json);
static void attach_plugin_reloginReason_bootConfig(IN OUT std::string &init_data, IN std::string relogin_reason, IN std::string boot_config);
static std::string& replace_all(std::string& str, const std::string& old_value, const std::string& new_value)
{
while (true) {
std::string::size_type pos(0);
if ((pos = str.find(old_value)) != std::string::npos)
str.replace(pos, old_value.length(), new_value);
else
break;
}
return str;
}
static std::string& replace_all_distinct(std::string& str, const std::string& old_value, const std::string& new_value)
{
for (std::string::size_type pos(0); pos != std::string::npos; pos += new_value.length()) {
if ( ( pos = str.find(old_value, pos) ) != std::string::npos )
str.replace(pos, old_value.length(), new_value);
else
break;
}
return str;
}
private:
static PosHandle handle;
PosHandle();
~PosHandle();
PosHandle(const PosHandle&) {}
};
#endif
\ No newline at end of file
......@@ -110,9 +110,9 @@ TEST_F(jsonModule_ut, convertDataOds2Pos)
EXPECT_TRUE(rlt2);
}
TEST_F(jsonModule_ut, getPushType)
TEST_F(jsonModule_ut, getPosOdsPushType)
{
std::string strOut;
int rlt = jsonTool.getPushType(strPosInit.data());
int rlt = jsonTool.getPosOdsPushType(strPosInit.data());
EXPECT_EQ(rlt,1000);
}
......@@ -304,4 +304,93 @@ void kill_process_by_name(const char *name)
os_sleep(3); //延时,防止杀掉进程后,端口还没有释放
}
#endif
}
// CreateProcess :创建另一个进程运行守护程序;
void create_process_daemon() {
#ifdef WIN32
// 1、判断daemon脚本文件是否存在,
std::string strBinPath = GetProcDir();
std::string strDaemonAppPath(strBinPath.data());
strDaemonAppPath.append("fmPluginDaemon.bat");
WIN32_FIND_DATA wfd;
HANDLE hFind = FindFirstFile(strDaemonAppPath.c_str() , &wfd );
if (INVALID_HANDLE_VALUE == hFind) {
LOG(INFO) << "strDaemonAppPath:" << strDaemonAppPath.c_str() << " No Exist !!!";
return;
}
else {
// 1.2、将daemon脚本文件进行可执行权限 赋权
CloseHandle(hFind); // Windows 忽略 文件的可执行权限;
// 1.3、启动daemon脚本程序到子进程中;
// CreateProcess(NULL, "regedit.exe"
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
LPTSTR pszCmd = new TCHAR[strDaemonAppPath.length() + 1];
memset(pszCmd, 0, sizeof(TCHAR)*(strDaemonAppPath.length() + 1));
strcpy(pszCmd, strDaemonAppPath.c_str() );
CreateProcess(NULL, pszCmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
// WaitForSingleObject(pi.hProcess, INFINITE);
// CloseHandle(pi.hProcess);
// system("start regedit.exe"); // Meybe Block Main Process;
LOG(INFO) << "Start Another Process Success , DaemonAppPath:" << strDaemonAppPath.c_str();
}
#else
// 1、判断daemon程序文件是否存在,
// 2、将daemon程序文件进行可执行权限 赋权
std::string strBinPath = GetProcDir();
std::string strDaemonAppPath(strBinPath.data());
strDaemonAppPath.append("fmPluginDaemon");
if (access(strDaemonAppPath.c_str(), X_OK) == 0) {
LOG(INFO) << "create_process_daemon:: DaemonAppPath:" << strDaemonAppPath.c_str() << " Exist And Has Execute Permission ";
} else {
LOG(INFO) << "create_process_daemon:: DaemonAppPath:" << strDaemonAppPath.c_str() << " Non-Exist Or No Execute Permission ";
return;
}
// 3、判断daemon程序是否已经启动,已经启动着无需重复启动;
if ( does_daemon_work() )
LOG(INFO) << "create_process_daemon:: DaemonApp: Is Running No Need Run Another One";
else {
LOG(INFO) << "create_process_daemon:: DaemonApp: Haven't Run, Start DaemonApp Now ";
// 4、启动daemon程序;
system( strDaemonAppPath.c_str() );
}
#endif
}
int does_daemon_work()
{
#ifdef WIN32
LOG(INFO) << "does_daemon_work:: DaemonApp Is Running, No Need Check Status ";
return 0;
#else
FILE* fp;
int count;
char buf[150];
char command[150];
sprintf(command, "%s%s%s", "ps -ef | grep ", "fmPluginDaemon", " | grep -v grep | wc -l");
if ((fp = popen(command, "r")) == NULL) {
LOG(INFO) << "does_daemon_work:: Check DaemonApp Is Running Command Error !!! popen Failed Skip DaemonApp";
// exit(EXIT_FAILURE);
return 100;
}
if ((fgets(buf, 150, fp)) != NULL)
{
count = atoi(buf);
}
pclose(fp);
return count;
#endif
}
\ No newline at end of file
......@@ -28,4 +28,9 @@ void os_sleep(int seconds);
//根据进程名称杀死进程
void kill_process_by_name(const char *name);
// CreateProcess :创建另一个进程运行守护程序;
void create_process_daemon();
int does_daemon_work();
#endif
......@@ -166,10 +166,10 @@ std::string ZIni::readString(std::string strSectName,
{
return strDefault;
}
if (strTemp.length() > strKeyName.length() + 1 &&
0 == strTemp.compare(0,
strKeyName.length(), strKeyName) &&
'=' == strTemp[strKeyName.length()])
if ( strTemp.length() > strKeyName.length() + 1
&& 0 == strTemp.compare(0,strKeyName.length(), strKeyName)
&& '=' == strTemp[strKeyName.length()] )
{
return (strTemp.substr(strKeyName.length() + 1));
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment