DownloadFSM.cpp 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159
  1. #include "stdafx.h"
  2. #include "DownloadFSM.h"
  3. #include "Event.h"
  4. #include "Download_msg_g.h"
  5. #include <fileutil.h>
  6. #include <strutil.h>
  7. #include "SpIni.h"
  8. #include "EventCode.h"
  9. static ErrorCodeEnum ParseIPAddress(const char *str, CSimpleStringA &ip, int &port)
  10. {
  11. ErrorCodeEnum Error = Error_Unexpect;
  12. if (str) {
  13. char tmp1[32] = {};
  14. char tmp2[16] = {};
  15. sscanf(str, "%s %s", tmp1, tmp2);
  16. if (tmp1[0] != 0 && tmp2[0] != 0)
  17. {
  18. ip = tmp1;
  19. port = atoi(tmp2);
  20. Error = Error_Succeed;
  21. }
  22. else
  23. return Error;
  24. }
  25. return Error;
  26. }
  27. static ErrorCodeEnum ParseBoolean(const char *str, BOOL &bValue)
  28. {
  29. ErrorCodeEnum Error = Error_Unexpect;
  30. if (str) {
  31. if (_stricmp(str, "false") == 0) {
  32. bValue = FALSE;
  33. Error = Error_Succeed;
  34. } else if (_stricmp(str, "true") == 0) {
  35. bValue = TRUE;
  36. Error = Error_Succeed;
  37. } else {
  38. Dbg("unknown boolean value:%s", str);
  39. }
  40. }
  41. return Error;
  42. }
  43. DownloadFSM::DownloadFSM()
  44. : m_pConnection(NULL), m_arr_downlist(NULL), m_current(NULL)
  45. , m_last_filelist(NULL),m_DFlist(NULL),m_currentFileTask(NULL)
  46. {
  47. isStartUp =false;
  48. }
  49. DownloadFSM::~DownloadFSM()
  50. {
  51. if (m_last_filelist)
  52. free(m_last_filelist);
  53. if (m_DFlist!=NULL){
  54. std::list<DownloadFileTask*>::iterator iter;
  55. for(iter=m_DFlist->begin();iter!=m_DFlist->end();++iter){
  56. delete *iter;
  57. }
  58. m_DFlist->clear();
  59. delete m_DFlist;
  60. }
  61. if (m_currentFileTask!=NULL){
  62. std::list<download_file_t*>::iterator iter;
  63. for(iter=m_currentFileTask->begin();iter!=m_currentFileTask->end();++iter){
  64. delete *iter;
  65. }
  66. m_currentFileTask->clear();
  67. delete m_currentFileTask;
  68. }
  69. }
  70. ErrorCodeEnum DownloadFSM::LoadServerConfigFromCenterSetting()
  71. {
  72. CSmartPointer<IEntityFunction> spFunction = m_pEntity->GetFunction();
  73. CSmartPointer<IConfigInfo> spConfig;
  74. ErrorCodeEnum Error = spFunction->OpenConfig(Config_CenterSetting, spConfig);
  75. if (Error == Error_Succeed) {
  76. CSimpleStringA str;
  77. Error = spConfig->ReadConfigValue("Download", "Server", str);
  78. if (Error == Error_Succeed) {
  79. Error = ParseIPAddress(str, m_server1, m_server1_port);
  80. }
  81. if (Error == Error_Succeed)
  82. {
  83. ErrorCodeEnum ErrorCode;
  84. ErrorCode = spConfig->ReadConfigValue("Download", "Server_Backup", str);
  85. if (ErrorCode == Error_Succeed)
  86. {
  87. ErrorCode = ParseIPAddress(str, m_server2, m_server2_port);
  88. }
  89. if (ErrorCode!=Error_Succeed)
  90. {
  91. m_server2 = NULL;
  92. m_server2_port = 0;
  93. }
  94. }
  95. }
  96. return Error;
  97. }
  98. bool DownloadFSM::checkFileStr(CSimpleStringA strFile,int count)
  99. {
  100. bool flag =true;
  101. CAutoArray<CSimpleStringA> fList = strFile.Split('$');
  102. if(fList.GetCount() == count){
  103. for(int i=0; i<fList.GetCount(); i++){
  104. CAutoArray<CSimpleStringA> info = fList[i].Split('|');
  105. if(info.GetCount() != 2){
  106. Dbg("downloadFile.ini fileList fileInfo param is error");
  107. flag=false;
  108. break;
  109. }
  110. }
  111. }else{
  112. Dbg("downloadFile.ini fileList param is error, flist num not equal count");
  113. flag=false;
  114. }
  115. return flag;
  116. }
  117. //加载运行时文件任务
  118. ErrorCodeEnum DownloadFSM::LoadDownloadFileList()
  119. { //时间戳|文件名$
  120. //lwt 修改成日志文件互备模式:当运行时文件破坏时,用备份文件替代,当运行文件正常时,覆盖更新下备份文件,以防止备份文件之前是错误的。
  121. CSmartPointer<IEntityFunction> spFunction = m_pEntity->GetFunction();
  122. CSmartPointer<IConfigInfo> spConfig;
  123. ErrorCodeEnum Error = spFunction->OpenConfig(Config_Run, spConfig);
  124. if (Error != Error_Succeed) {
  125. Dbg("open downloadFile.ini fail, please check out downloadFile.ini!");
  126. return Error_IO;
  127. }
  128. int count=0;
  129. CSimpleStringA strFile="";
  130. CSimpleStringA strFileBack="";
  131. CSimpleStringA strFinalFile="";//最终需要加载的文件列表
  132. int tmpCount;
  133. Error = spConfig->ReadConfigValueInt("downloadFile", "count", tmpCount);
  134. if(Error != Error_Succeed){
  135. Dbg("read downloadFile.ini param count fail!");
  136. return Error_IO;
  137. }else{
  138. count= tmpCount;
  139. Dbg("downloadFile count is %d",count);
  140. }
  141. Error = spConfig->ReadConfigValue("downloadFile", "fileList", strFile);
  142. if(Error != Error_Succeed){
  143. Dbg("read downloadFile.ini param fileList fail!");
  144. return Error_IO;
  145. }else{
  146. Dbg("downloadFile fileList is [%s]",strFile.GetData());
  147. }
  148. Error = spConfig->ReadConfigValue("downloadFile", "fileListBack", strFileBack);
  149. if(Error != Error_Succeed){
  150. Dbg("read downloadFile.ini param fileListBack fail!");
  151. return Error_IO;
  152. }else{
  153. Dbg("downloadFile fileListBack is [%s]",strFileBack.GetData());
  154. }
  155. if(count == 0){
  156. //因可能文件不存在,也返回0,默认初始化下文件,保证文件创建和字段创建
  157. spConfig->WriteConfigValueInt("downloadFile", "count", count);
  158. spConfig->WriteConfigValue("downloadFile", "fileList", strFile.GetData());
  159. }
  160. //判断是否读入数据效验成功,成功则用运行时文件覆盖写入备份文件,否则用备份文件写回运行时文件
  161. if(checkFileStr(strFile,count)){
  162. strFinalFile=strFile;
  163. //运行时通过检验
  164. if(spConfig->WriteConfigValue("downloadFile", "fileListBack", strFile.GetData())==Error_Succeed){
  165. Dbg("downloadFile fileListBack is rewrite success! content is [%s]",strFile.GetData());
  166. }else{
  167. Dbg("downloadFile fileListBack is rewrite fail! content is [%s]",strFile.GetData());
  168. }
  169. }else{
  170. CAutoArray<CSimpleStringA> fListback = strFileBack.Split('$');
  171. //备份文件是否效验通过,不通过,则运行时和备份文件全部清空
  172. if(checkFileStr(strFileBack,fListback.GetCount())){
  173. //备份通过检验
  174. strFinalFile=strFileBack;
  175. if(spConfig->WriteConfigValueInt("downloadFile", "count", fListback.GetCount())==Error_Succeed){
  176. Dbg("downloadFile count is rewrite success! content is [%d]",fListback.GetCount());
  177. }else{
  178. Dbg("downloadFile count is rewrite fail! content is [%d]",fListback.GetCount());
  179. return Error_IO;
  180. }
  181. if(spConfig->WriteConfigValue("downloadFile", "fileList", strFileBack.GetData())==Error_Succeed){
  182. Dbg("downloadFile fileList is rewrite success! content is [%s]",strFileBack.GetData());
  183. }else{
  184. Dbg("downloadFile fileList is rewrite fail! content is [%s]",strFileBack.GetData());
  185. return Error_IO;
  186. }
  187. }else{
  188. //未通过检验,则全部置空
  189. strFinalFile="";
  190. Dbg("downloadFile.ini reset");
  191. if(spConfig->WriteConfigValueInt("downloadFile", "count", 0)!=Error_Succeed){
  192. Dbg("downloadFile count reset fail");
  193. }
  194. if(spConfig->WriteConfigValue("downloadFile", "fileList", "")!=Error_Succeed){
  195. Dbg("downloadFile fileList reset fail");
  196. }
  197. if(spConfig->WriteConfigValue("downloadFile", "fileListBack", "")!=Error_Succeed){
  198. Dbg("downloadFile fileListBack reset fail");
  199. }
  200. }
  201. }
  202. Dbg("downloadFile final filelist content [%s]",strFinalFile.GetData());
  203. //装载文件到内存中
  204. CAutoArray<CSimpleStringA> fList = strFinalFile.Split('$');
  205. for(int i=0; i<fList.GetCount(); i++){
  206. CAutoArray<CSimpleStringA> info = fList[i].Split('|');
  207. CSimpleStringA expireTime = info[0];
  208. CSimpleStringA fileName= info[1];
  209. //加入任务队列
  210. DownloadFileTask *pTask = new DownloadFileTask();
  211. pTask->FileName=fileName;
  212. pTask->ExpireTime = (DWORD)atoi(expireTime.GetData());
  213. m_DFlist->push_back(pTask);
  214. CSmallDateTime expire(pTask->ExpireTime);
  215. Dbg("initial load task: expiretime[%d],expiredate[%s],filename[%s]",pTask->ExpireTime, expire.ToTimeString().GetData(), pTask->FileName.GetData());
  216. }
  217. return Error_Succeed;
  218. }
  219. //保存运行时文件任务
  220. ErrorCodeEnum DownloadFSM::SaveDownloadFileList()
  221. {
  222. ErrorCodeEnum ret = Error_Succeed;
  223. CSmartPointer<IEntityFunction> spFunction = m_pEntity->GetFunction();;
  224. CSmartPointer<IConfigInfo> spConfig;
  225. ErrorCodeEnum Error = spFunction->OpenConfig(Config_Run, spConfig);
  226. if (Error == Error_Succeed) {
  227. int count = m_DFlist->size();
  228. std::list<DownloadFileTask*>::iterator iter;
  229. CSimpleStringA str = "";
  230. for(iter=m_DFlist->begin();iter!=m_DFlist->end();++iter){
  231. DownloadFileTask* p = *iter;
  232. CSimpleStringA s1 = CSimpleStringA::Format("%d|",p->ExpireTime);
  233. CSimpleStringA s2 = CSimpleStringA::Format("%s$",p->FileName.GetData());
  234. Dbg("prepare save download file expiretime is %d, name is %s",p->ExpireTime,p->FileName.GetData());
  235. str.Append(s1.GetData());
  236. str.Append(s2.GetData());
  237. }
  238. Dbg("prepare write downloadFile/count : %d",count);
  239. Dbg("prepare write downloadFile/fileList : %s",str.GetData());
  240. Dbg("prepare write downloadFile/fileListBack : %s",str.GetData());
  241. Error = spConfig->WriteConfigValueInt("downloadFile", "count", count);
  242. if(Error!=Error_Succeed){
  243. Dbg("write downloadFile/count fail : %d",count);
  244. ret=Error_IO;
  245. }
  246. Error = spConfig->WriteConfigValue("downloadFile", "fileList", str.GetData());
  247. if(Error!=Error_Succeed){
  248. Dbg("write downloadFile/fileList fail : %s",str.GetData());
  249. ret=Error_IO;
  250. }
  251. Error = spConfig->WriteConfigValue("downloadFile", "fileListBack", str.GetData());
  252. if(Error!=Error_Succeed){
  253. Dbg("write downloadFile/fileListBack fail : %s",str.GetData());
  254. ret=Error_IO;
  255. }
  256. return ret;
  257. }else{
  258. Dbg("SaveDownloadFileList is fail , open downloadFile.ini fail!");
  259. return Error_Exception;
  260. }
  261. }
  262. //添加下载任务:加锁
  263. ErrorCodeEnum DownloadFSM::addDownLoadFileWork(CSimpleStringA fileName,DWORD expireTime)
  264. {
  265. EnterCriticalSection(&m_cs);
  266. //查询是否存在文件名,文件名唯一,不存在则加入,存在则忽略
  267. //先删除再加入
  268. std::list<DownloadFileTask*>::iterator iter;
  269. //删除所有文件名相同的文件
  270. for(iter=m_DFlist->begin();iter!=m_DFlist->end();){
  271. DownloadFileTask* p = *iter;
  272. if(p->FileName==fileName){
  273. iter = m_DFlist->erase(iter);
  274. delete p;
  275. }else{
  276. ++iter;
  277. }
  278. }
  279. //添加新的任务
  280. DownloadFileTask *pTask= new DownloadFileTask();
  281. pTask->FileName = fileName;
  282. pTask->ExpireTime = expireTime;
  283. m_DFlist->push_back(pTask);
  284. //保存队列到文件
  285. ErrorCodeEnum Error = SaveDownloadFileList();
  286. if(Error==Error_Succeed){
  287. Dbg("addDownLoadFileWork is success,fileName: %s",fileName.GetData());
  288. }else{
  289. Dbg("addDownLoadFileWork is fail,fileName: %s",fileName.GetData());
  290. }
  291. LeaveCriticalSection(&m_cs);
  292. return Error;
  293. }
  294. //取消下载任务:加锁
  295. ErrorCodeEnum DownloadFSM::deleteDownLoadFileWork(CSimpleStringA fileName)
  296. {
  297. EnterCriticalSection(&m_cs);
  298. Dbg("deleteDownLoadFileWork file [%s] prepare delete ",fileName.GetData());
  299. int iCount=m_DFlist->size();
  300. Dbg("deleteDownLoadFileWork prepare delete m_DFlist count is %d ",iCount);
  301. //查询是否存在文件名,存在则删除,不存在则忽略
  302. std::list<DownloadFileTask*>::iterator iter;
  303. for(iter=m_DFlist->begin();iter!=m_DFlist->end();++iter){
  304. DownloadFileTask* p = *iter;
  305. //尝试修改先移除后delete,看是否还出现问题
  306. if(strcmp(p->FileName.GetData(),fileName.GetData())==0){
  307. Dbg("deleteDownLoadFileWork file [%s] is deleted",fileName.GetData());
  308. iter = m_DFlist->erase(iter);
  309. delete p;
  310. break;
  311. }
  312. }
  313. iCount = m_DFlist->size();
  314. Dbg("deleteDownLoadFileWork deleted m_DFlist count is %d ",iCount);
  315. //保存队列到文件
  316. ErrorCodeEnum Error = SaveDownloadFileList();
  317. if(Error==Error_Succeed){
  318. Dbg("deleteDownLoadFileWork is success,fileName: %s",fileName.GetData());
  319. }else{
  320. Dbg("deleteDownLoadFileWork is fail,fileName: %s",fileName.GetData());
  321. }
  322. LeaveCriticalSection(&m_cs);
  323. return Error;
  324. }
  325. ErrorCodeEnum DownloadFSM::deleteCurrentDownloadFile(CSimpleStringA fileName){
  326. EnterCriticalSection(&m_cs);
  327. //表明是当前正在文件,则把当前文件置空,并删除零时文件,否则之不需要删除当前文件
  328. if(m_current!=NULL){
  329. if(m_currentFileName==fileName){
  330. Dbg("current downloadfile prepare delete ,filename is [%s]",fileName.GetData());
  331. download_storage_close(m_current,false,true);//删除
  332. m_currentFileName="";
  333. m_current=NULL;
  334. Dbg("current downloadfile is deleted ,filename is [%s]",fileName.GetData());
  335. }
  336. }
  337. //删除对应的对象
  338. std::list<download_file_t*>::iterator fIter;
  339. for(fIter=m_currentFileTask->begin();fIter!=m_currentFileTask->end();++fIter){
  340. download_file_t* p = *fIter;
  341. if(strcmp(LPCSTR(p->name),fileName.GetData())==0){
  342. delete p;
  343. fIter = m_currentFileTask->erase(fIter);
  344. break;
  345. }
  346. }
  347. LeaveCriticalSection(&m_cs);
  348. return Error_Succeed;
  349. }
  350. //过滤检查下载任务时效性:加锁
  351. ErrorCodeEnum DownloadFSM::checkWorkExpireTime()
  352. {
  353. EnterCriticalSection(&m_cs);
  354. Dbg("checkWorkExpireTime begin exec");
  355. std::list<DownloadFileTask*>::iterator iter=m_DFlist->begin();
  356. bool bDelete = false;
  357. while(iter!=m_DFlist->end()){
  358. DownloadFileTask* p = *iter;
  359. CSimpleStringA fileName = p->FileName;
  360. DWORD expireTime = p->ExpireTime;
  361. CSmallDateTime expire(expireTime);
  362. //判断是否超过时效性,超时的去除,并广播
  363. if(CSmallDateTime::GetNow()>expire){
  364. CSimpleStringA strExpireTime = expire.ToTimeString();
  365. Dbg("send broadcast for file [%s] downloadResult status : Error_timeOut , expiretime [%s]", fileName.GetData(), strExpireTime.GetData());
  366. returnDownloadFileResult(fileName.GetData(),Error_TimeOut,"downloadFile expireTime is timeOut");
  367. delete p;
  368. iter = m_DFlist->erase(iter);
  369. bDelete=true;
  370. }else{
  371. ++iter;
  372. }
  373. }
  374. //保存队列到文件
  375. ErrorCodeEnum Error=Error_Succeed;
  376. if(bDelete){
  377. Error = SaveDownloadFileList();
  378. if(Error==Error_Succeed){
  379. Dbg("checkWorkExpireTime is success");
  380. }else{
  381. Dbg("checkWorkExpireTime is fail");
  382. }
  383. }
  384. LeaveCriticalSection(&m_cs);
  385. return Error;
  386. }
  387. bool DownloadFSM::isDownloadTask(const char * filename){
  388. EnterCriticalSection(&m_cs);
  389. bool isTask=false;
  390. std::list<DownloadFileTask*>::iterator iter;
  391. for(iter = m_DFlist->begin();iter!=m_DFlist->end();++iter){
  392. DownloadFileTask* p = *iter;
  393. if(strcmp(p->FileName.GetData(),filename)==0){
  394. isTask=true;
  395. break;
  396. }
  397. }
  398. LeaveCriticalSection(&m_cs);
  399. return isTask;
  400. }
  401. ErrorCodeEnum DownloadFSM::returnDownloadFileResult(const char* filename,ErrorCodeEnum error,CSimpleStringA errorMsg){
  402. DownloadResult result;
  403. result.errorCode = error;
  404. result.errorMsg = errorMsg ;
  405. ErrorCodeEnum retError = SpSendBroadcast(GetEntityBase()->GetFunction(), SP_MSG_OF(DownloadResult), SP_MSG_SIG_OF(DownloadResult), result);
  406. return retError;
  407. }
  408. ErrorCodeEnum DownloadFSM::returnDownloadProgress(download_file_t* file,download_storage_t * currentStorage){
  409. DownloadProgress dProgress;
  410. dProgress.currentFile = file->name;
  411. dProgress.fileNum = (int)m_DFlist->size();
  412. dProgress.progress=0;
  413. int temp10 = (int)((file->length>>15)/10);//10%左右的块号
  414. int block = currentStorage->offset_block_id;//当前块号
  415. bool isBroadcast =false;
  416. if(block==1){
  417. dProgress.progress=0;
  418. isBroadcast =true;
  419. }else if(block==temp10){
  420. dProgress.progress=10;
  421. isBroadcast =true;
  422. }else if(block==temp10*2){
  423. dProgress.progress=20;
  424. isBroadcast =true;
  425. }else if(block==temp10*3){
  426. dProgress.progress=30;
  427. isBroadcast =true;
  428. }else if(block==temp10*4){
  429. dProgress.progress=40;
  430. isBroadcast =true;
  431. }else if(block==temp10*5){
  432. dProgress.progress=50;
  433. isBroadcast =true;
  434. }else if(block==temp10*6){
  435. dProgress.progress=60;
  436. isBroadcast =true;
  437. }else if(block==temp10*7){
  438. dProgress.progress=70;
  439. isBroadcast =true;
  440. }else if(block==temp10*8){
  441. dProgress.progress=80;
  442. isBroadcast =true;
  443. }else if(block==temp10*9){
  444. dProgress.progress=90;
  445. isBroadcast =true;
  446. }else if(block<<15 >= file->length){
  447. dProgress.progress=100;
  448. isBroadcast =true;
  449. }
  450. ErrorCodeEnum retError=Error_Succeed;
  451. if(isBroadcast){
  452. Dbg("file [%s] progress is %d",(LPCSTR)file->name,dProgress.progress);
  453. ErrorCodeEnum retError = SpSendBroadcast(GetEntityBase()->GetFunction(), SP_MSG_OF(DownloadProgress), SP_MSG_SIG_OF(DownloadProgress), dProgress);
  454. }
  455. return retError;
  456. }
  457. void DownloadFSM::OnStateTrans( int iSrcState, int iDstState )
  458. { //告警状态跳转
  459. Dbg("trans from %s to %s", GetStateName(iSrcState), GetStateName(iDstState));
  460. }
  461. void DownloadFSM::OnSysVarEvent( const char *pszKey, const char *pszValue,const char *pszOldValue,const char *pszEntityName )
  462. {
  463. if(strcmp("CallState",pszKey)==0){
  464. Dbg("rx sysvar %s from %s, %s to %s", pszKey, pszEntityName, pszOldValue, pszValue);
  465. if (pszValue[0] == 'O') {
  466. Dbg("download state prepare jump enable ");
  467. PostEventFIFO(new FSMEvent(USER_EVT_JMP_ENABLE));
  468. } else {
  469. Dbg("download state prepare jump disable");
  470. PostEventFIFO(new FSMEvent(USER_EVT_JMP_DISABLE));
  471. }
  472. }
  473. if(strcmp("UIState",pszKey)==0){
  474. Dbg("rx sysvar %s from %s, %s to %s", pszKey, pszEntityName, pszOldValue, pszValue);
  475. //public enum UIState : int
  476. //{
  477. // Menu = 'M', //目录浏览
  478. // RandomAd = 'A', //随机广告
  479. // TargetAd = 'T', //目标广告
  480. // FillOut = 'F', //业务填单
  481. // Confirm = 'C', //交易确认
  482. // Submitting = 'S', //业务提交
  483. // Respone = 'R', //请求回报
  484. // Frozen = 'Z' //暂停响应
  485. //}
  486. if(!isStartUp){
  487. if(pszValue[0] == 'M'){
  488. isStartUp = true;
  489. Dbg("system page isStartup");
  490. }
  491. }
  492. }
  493. }
  494. ErrorCodeEnum DownloadFSM::OnInit()
  495. {
  496. ErrorCodeEnum Error;
  497. //初始化列表
  498. m_DFlist = new std::list<DownloadFileTask*>();
  499. m_currentFileTask = new std::list<download_file_t*>();
  500. Error=LoadDownloadFileList();
  501. //if (Error == Error_Succeed) {
  502. // LOG_TRACE("load fileList success!");
  503. //}
  504. //Error=Error_CheckSum;
  505. if (Error != Error_Succeed) {
  506. LOG_TRACE("load fileList failed!");
  507. return Error;
  508. }
  509. //初始化临界区
  510. InitializeCriticalSection(&m_cs);
  511. //初始化中台服务器地址
  512. Error = LoadServerConfigFromCenterSetting();
  513. if (Error != Error_Succeed) {
  514. LogWarn(Severity_High, Error, 0, "从集中配置读取配置信息失败");
  515. return Error;
  516. }
  517. //初始化终端文件夹地址
  518. CSimpleStringA str;
  519. m_pEntity->GetFunction()->GetPath("Download", str);
  520. strcpy(m_base_path, str.GetData());
  521. //订阅callState
  522. Error = m_pEntity->GetFunction()->RegistSysVarEvent("CallState", this);
  523. if(Error!=Error_Succeed){
  524. LOG_TRACE("RegistSysVarEvent CallState fail");
  525. return Error;
  526. }
  527. //订阅MenuChoice:判断是否页面在主菜单
  528. Error = m_pEntity->GetFunction()->RegistSysVarEvent("UIState",this);
  529. if(Error!=Error_Succeed){
  530. LOG_TRACE("RegistSysVarEvent UIState fail");
  531. return Error;
  532. }
  533. if (Error == Error_Succeed) {
  534. AddStateHooker(this);
  535. }
  536. //......
  537. return Error;
  538. }
  539. ErrorCodeEnum DownloadFSM::OnExit()
  540. {
  541. //取消callState订阅
  542. m_pEntity->GetFunction()->UnregistSysVarEvent("CallState");
  543. //订阅MenuChoice:判断是否页面在主菜单
  544. m_pEntity->GetFunction()->UnregistSysVarEvent("UIState");
  545. //删除列表
  546. if (m_DFlist!=NULL){
  547. std::list<DownloadFileTask*>::iterator iter;
  548. for(iter=m_DFlist->begin();iter!=m_DFlist->end();++iter){
  549. delete *iter;
  550. }
  551. m_DFlist->clear();
  552. delete m_DFlist;
  553. }
  554. if (m_currentFileTask!=NULL){
  555. std::list<download_file_t*>::iterator iter;
  556. for(iter=m_currentFileTask->begin();iter!=m_currentFileTask->end();++iter){
  557. delete *iter;
  558. }
  559. m_currentFileTask->clear();
  560. delete m_currentFileTask;
  561. }
  562. //释放临界区
  563. DeleteCriticalSection(&m_cs);
  564. return Error_Succeed;
  565. }
  566. void DownloadFSM::s0_on_entry()
  567. {
  568. LOG_FUNCTION();
  569. //通过直接获取变量值来判断是否进入了启动界面
  570. if(!isStartUp){
  571. CSimpleStringA strState;
  572. ErrorCodeEnum Error2 = m_pEntity->GetFunction()->GetSysVar("UIState",strState);
  573. if(Error2 == Error_Succeed&&strState=="M"){
  574. isStartUp =true;
  575. Dbg("system page isStartup");
  576. }
  577. }
  578. CSimpleStringA strValue;
  579. //连线状态CallState。定义客户和柜员连线电话状态。有6种状态:离线O、尝试连线柜员C、免提通话H、连线失败F、断线B。
  580. //初始状态为O。详细见“连线状态管理-连线状态转移图”部分
  581. ErrorCodeEnum Error = m_pEntity->GetFunction()->GetSysVar("CallState", strValue);
  582. if (Error == Error_Succeed && strValue[0] == 'O' && isStartUp)
  583. {
  584. // only download when CallState in offline state
  585. PostEventLIFO(new FSMEvent(USER_EVT_JMP_ENABLE));
  586. }
  587. else
  588. {
  589. ScheduleTimer(1, 10000);
  590. }
  591. }
  592. void DownloadFSM::s0_on_exit()
  593. {
  594. LOG_FUNCTION();
  595. CancelTimer(1);
  596. }
  597. unsigned int DownloadFSM::s0_on_event(FSMEvent* event)
  598. {
  599. if (event->iEvt == EVT_TIMER)
  600. {
  601. //通过直接获取变量值来判断是否进入了启动界面
  602. if(!isStartUp){
  603. CSimpleStringA strState;
  604. ErrorCodeEnum Error2 = m_pEntity->GetFunction()->GetSysVar("UIState",strState);
  605. if(Error2 == Error_Succeed&&strState=="M"){
  606. isStartUp =true;
  607. Dbg("system page isStartup");
  608. }
  609. }
  610. // 检查呼叫状态
  611. CSimpleStringA strValue;
  612. ErrorCodeEnum Error = m_pEntity->GetFunction()->GetSysVar("CallState", strValue);
  613. if (Error == Error_Succeed && strValue[0] == 'O' && isStartUp)
  614. {
  615. // only download when CallState in offline state
  616. PostEventLIFO(new FSMEvent(USER_EVT_JMP_ENABLE));
  617. }
  618. else
  619. {
  620. ScheduleTimer(1, 10000);
  621. }
  622. }
  623. return 0;
  624. }
  625. void DownloadFSM::s1_on_entry()
  626. {
  627. LOG_FUNCTION();
  628. ScheduleTimer(1, 30000);
  629. }
  630. void DownloadFSM::s1_on_exit()
  631. {
  632. LOG_FUNCTION();
  633. CancelTimer(1);
  634. }
  635. unsigned int DownloadFSM::s1_on_event(FSMEvent* event)
  636. {
  637. return 0;
  638. }
  639. void DownloadFSM::s2_on_entry()
  640. {
  641. LOG_FUNCTION();
  642. //过滤任务列表中超过时效任务
  643. ErrorCodeEnum error = checkWorkExpireTime();
  644. //当有任务时创建连接
  645. if(m_DFlist->size()>0){
  646. if (!m_pConnection) {
  647. m_pConnection = new DownloadConnection(m_pEntity, this);
  648. if(m_pConnection->ConnectFromCentralSetting() && m_pConnection->IsConnectionOK()){
  649. //创建成功
  650. }else{
  651. m_pConnection->Close();
  652. m_pConnection->DecRefCount();
  653. m_pConnection = NULL;
  654. }
  655. }
  656. if (!m_pConnection) {
  657. ScheduleTimer(2, 30000); // try 30 seconds later
  658. } else {
  659. PostEventLIFO(new FSMEvent(USER_EVT_JMP_GETFILEINFO));
  660. }
  661. }else{
  662. PostEventFIFO(new FSMEvent(USER_EVT_NOTASK)); // 跳回S1状态
  663. }
  664. }
  665. void DownloadFSM::s2_on_exit()
  666. {
  667. CancelTimer(2);
  668. }
  669. unsigned int DownloadFSM::s2_on_event(FSMEvent* event)
  670. {
  671. if (event->iEvt == EVT_TIMER) {
  672. //过滤任务列表中超过时效任务
  673. ErrorCodeEnum error = checkWorkExpireTime();
  674. //当有任务时创建连接
  675. if(m_DFlist->size()>0){
  676. m_pConnection = new DownloadConnection(m_pEntity, this);
  677. if(m_pConnection->ConnectFromCentralSetting() && m_pConnection->IsConnectionOK()){
  678. //创建成功
  679. }else{
  680. m_pConnection->Close();
  681. m_pConnection->DecRefCount();
  682. m_pConnection = NULL;
  683. }
  684. if (!m_pConnection) {
  685. ScheduleTimer(2, 30000); // try 30 seconds later
  686. } else {
  687. PostEventLIFO(new FSMEvent(USER_EVT_JMP_GETFILEINFO));
  688. }
  689. }else{
  690. PostEventFIFO(new FSMEvent(USER_EVT_NOTASK)); // 跳回S1状态
  691. }
  692. }
  693. return 0;
  694. }
  695. void DownloadFSM::s3_on_entry()
  696. {
  697. LOG_FUNCTION();
  698. m_arr_downlist = NULL;
  699. //复制任务
  700. EnterCriticalSection(&m_cs);
  701. std::list<download_file_t*>::iterator fIter;
  702. for(fIter= m_currentFileTask->begin();fIter!=m_currentFileTask->end();++fIter){
  703. delete *fIter;
  704. }
  705. m_currentFileTask->clear();//清空之前批次的任务
  706. std::list<DownloadFileTask*>::iterator dIter;
  707. for(dIter=m_DFlist->begin();dIter!=m_DFlist->end();++dIter){
  708. //加入任务队列
  709. DownloadFileTask* p = *dIter;
  710. download_file_t* f = new download_file_t();
  711. //strcpy_s(f->name,64,p->FileName);//copy filename
  712. strcpy_s(f->name,256,p->FileName);//copy filename
  713. m_currentFileTask->push_back(f);
  714. }
  715. LeaveCriticalSection(&m_cs);
  716. if(m_currentFileTask->size()>0){
  717. Dbg("sendListreq ,count [%d]",m_currentFileTask->size());
  718. //m_pConnection->SendListReq();//发送获取文件列表请求
  719. m_pConnection->SendListNReq();//发送获取新国密文件列表请求
  720. }else{
  721. //无任务时跳回S1
  722. Dbg("no new files to download");
  723. m_pConnection->Close();
  724. m_pConnection->DecRefCount();
  725. m_pConnection = NULL;
  726. PostEventFIFO(new FSMEvent(USER_EVT_NOTASK)); // 跳回S1状态
  727. }
  728. }
  729. void DownloadFSM::s3_on_exit()
  730. {
  731. LOG_FUNCTION();
  732. //释放m_arr_downlist;
  733. if(m_arr_downlist!=NULL){
  734. download_free_filelist(m_arr_downlist);
  735. m_arr_downlist = NULL;
  736. }
  737. }
  738. unsigned int DownloadFSM::s3_on_event(FSMEvent* event)
  739. {
  740. if (event->iEvt == USER_EVT_FILEINO_ANS) {
  741. ListAnsEvent *ans = (ListAnsEvent*)event;
  742. if (ans->m_reply->ResultCode == DownloadCtlCode::ReturnList) {
  743. //解析中台返回的xml信息,得到下载文件信息列表。
  744. m_arr_downlist = download_parse_filelist(ans->m_reply->ListXmlContent, ans->m_xml_length);
  745. if(m_arr_downlist!=NULL){
  746. Dbg("return fileInfo list count is [%d]",m_arr_downlist->nelts);
  747. //如果存在返回值则检查
  748. if(m_arr_downlist->nelts>0){
  749. //循环判断需要下载的文件,对于已经下载完成的文件,则广播通知成功,不存在的则去除,其他都下载
  750. std::list<download_file_t*>::iterator iter=m_currentFileTask->begin();
  751. while(iter!=m_currentFileTask->end()){
  752. download_file_t* f = *iter;
  753. CSimpleStringA filename=f->name;
  754. int i=new_download_check_filelist(m_base_path, m_arr_downlist,f);
  755. //文件不在列表中,去除
  756. if(i==0){
  757. Dbg("file [%s] is not exist in filelist , wait a moment download ", f->name);
  758. delete f;//删除对象内容
  759. iter = m_currentFileTask->erase(iter);
  760. }
  761. //下载完成,广播通知
  762. if(i==2){
  763. Dbg("send broadcast for file [%s] downloadResult status success 1", f->name);
  764. returnDownloadFileResult(filename.GetData(),Error_Succeed,"downloadFile success");
  765. deleteDownLoadFileWork(filename);
  766. delete f;//删除对象内容
  767. iter = m_currentFileTask->erase(iter);
  768. }
  769. //准备后面下载的文件
  770. if(i==1){
  771. //先删除已下载的文件
  772. if(download_delete_file(m_base_path,f)){
  773. Dbg("file [%s] prepare download ", f->name);
  774. ++iter;//下一个
  775. }else{
  776. //删除原文件失败,则去除此次下载
  777. delete f;//删除对象内容
  778. iter = m_currentFileTask->erase(iter);
  779. }
  780. }
  781. }
  782. //判断是否需要下载新文件
  783. if(m_currentFileTask->size()>0){
  784. Dbg("find %d new files to download", m_currentFileTask->size());
  785. return 1; // goto s4
  786. }else{
  787. Dbg("no new files to download");
  788. m_pConnection->Close();
  789. m_pConnection->DecRefCount();
  790. m_pConnection = NULL;
  791. return 2; // goto s5
  792. }
  793. }else{
  794. //无信息列表,返回S1
  795. Dbg("download list return empty");
  796. m_pConnection->Close();
  797. m_pConnection->DecRefCount();
  798. m_pConnection = NULL;
  799. return 2; // goto s5
  800. }
  801. }else{
  802. Dbg("download list return NULL");
  803. m_pConnection->Close();
  804. m_pConnection->DecRefCount();
  805. m_pConnection = NULL; // goto s1
  806. }
  807. } else {
  808. Dbg("FileInfo ans result code:%d", ans->m_reply->ResultCode);
  809. m_pConnection->Close();
  810. m_pConnection->DecRefCount();
  811. m_pConnection = NULL; // goto s1
  812. }
  813. } else if (event->iEvt == USER_EVT_DISCONNECT) {
  814. m_pConnection->Close();
  815. m_pConnection->DecRefCount();
  816. m_pConnection = NULL;
  817. } else if (event->iEvt == USER_EVT_JMP_DISABLE) {
  818. m_pConnection->Close();
  819. m_pConnection->DecRefCount();
  820. m_pConnection = NULL;
  821. }
  822. return 0;
  823. }
  824. void DownloadFSM::s4_on_entry()
  825. {
  826. //获取新下载任务开始下载
  827. m_isDisable = false;//设置可用
  828. LogEvent(Severity_Middle, EVENT_MOD_DOWNLOAD_STARTSYNC, "开始同步下载");
  829. //Sleep(3000000);
  830. nextTask();
  831. }
  832. void DownloadFSM::s4_on_exit()
  833. {
  834. LOG_FUNCTION();
  835. if (m_pConnection) {
  836. m_pConnection->Close();
  837. m_pConnection->DecRefCount();
  838. m_pConnection = NULL;
  839. }
  840. //清空任务
  841. std::list<download_file_t*>::iterator iterTemp;
  842. for(iterTemp= m_currentFileTask->begin();iterTemp!=m_currentFileTask->end();++iterTemp){
  843. delete *iterTemp;
  844. }
  845. m_currentFileTask->clear();
  846. }
  847. unsigned int DownloadFSM::s4_on_event(FSMEvent* event)
  848. {
  849. //循环下载
  850. if (event->iEvt == USER_EVT_FILE_ANS){
  851. //判断是否需要推出
  852. if (!m_isDisable) {
  853. download_file_t* file;
  854. FileAnsEvent* ans = (FileAnsEvent*)event;
  855. //可能外部把当前的任务给删除了,通过m_current是否为空来判断,如果不为空,则继续下载,否则下一个文件下载
  856. if (m_current != NULL) {
  857. std::list<download_file_t*>::iterator fIter = m_currentFileTask->begin();//默认获取第一个,
  858. file = *fIter;
  859. CSimpleStringA filename = file->name;
  860. if (ans->m_reply->ResultCode != DownloadCtlCode::ErrorBlock) {
  861. download_storage_update(m_current, ans->m_reply->FileContent, ans->m_content_length);
  862. //广播进度给前台显示,块号,总长度
  863. returnDownloadProgress(file, m_current);
  864. if (m_current->offset_block_id << 15 >= file->length) {
  865. //因需要计算md5值,故需要先关闭前面连接句柄,否则打开文件失败
  866. #ifdef RVC_OS_WIN
  867. if (m_current->temp_handle != INVALID_HANDLE_VALUE) {
  868. CloseHandle(m_current->temp_handle);
  869. m_current->temp_handle = INVALID_HANDLE_VALUE;
  870. }
  871. #else
  872. if (m_current->temp_handle != NULL) {
  873. fclose(m_current->temp_handle);
  874. m_current->temp_handle = NULL;
  875. }
  876. #endif // RVC_OS_WIN
  877. //判断是否MD5一致,一致则下载成功,否则删除临时文件,重新等待下次下载
  878. int flag = download_check_MD5(m_current, file);
  879. if (flag == 0) {
  880. download_storage_close(m_current, true, false);//改名
  881. Dbg("send broadcast for file [%s] downloadResult status : success 2", file->name);
  882. returnDownloadFileResult(filename.GetData(), Error_Succeed, "downloadFile success");
  883. deleteDownLoadFileWork(filename);//下载任务列表中任务删除
  884. Dbg("file download success! [%s]", file->name);
  885. }
  886. else {
  887. download_storage_close(m_current, false, true);//删除
  888. Dbg("file download fail! file MD5 is error ,file is delete and wait a moment download again [%s]", (LPCSTR)file->name);
  889. }
  890. delete file;
  891. m_currentFileTask->erase(fIter);//删除已完成的
  892. m_current = NULL;
  893. nextTask();// goto S4
  894. }
  895. else {
  896. m_pConnection->SendFileReq((LPCSTR)file->name, m_current->offset_block_id); // continue goto S4
  897. }
  898. }
  899. else {
  900. //块号传输错误,删除错误的临时文件,跳转到S5,并等待一段时间下载
  901. Dbg("file download fail! file download error [%s] , errorcode [%d]", m_current->temp_path, ans->m_reply->ResultCode);
  902. download_storage_close(m_current, false, true);//删除
  903. m_current = NULL;
  904. m_currentFileName = "";
  905. PostEventLIFO(new FSMEvent(USER_EVT_JMP_SYNC));//goto S5
  906. }
  907. }
  908. else {
  909. //获取下一个下载文件
  910. Dbg("current downloadfile is deleted , download next file");
  911. nextTask();
  912. }
  913. }
  914. else {
  915. Dbg("CallState is online ,prepare to disable");
  916. PostEventFIFO(new FSMEvent(USER_EVT_JMP_DISABLE_S0));
  917. }
  918. }else if (event->iEvt == USER_EVT_DISCONNECT) {
  919. if (m_current) {
  920. download_storage_close(m_current,false,false);//关闭
  921. m_current = NULL;
  922. }
  923. m_currentFileName="";
  924. } else if (event->iEvt == USER_EVT_JMP_DISABLE_S0) {
  925. if (m_current) {
  926. download_storage_close(m_current,false,false);//关闭
  927. m_current = NULL;
  928. }
  929. m_currentFileName="";
  930. }
  931. else if (event->iEvt == USER_EVT_JMP_DISABLE) {
  932. m_isDisable = true;//设置disable标志位
  933. }
  934. return 0;
  935. }
  936. void DownloadFSM::s5_on_entry()
  937. {
  938. LOG_FUNCTION();
  939. //清理临时文件
  940. array_header_t *arr = fileutil_get_sub_files_a(m_base_path);
  941. if (arr) {
  942. int i;
  943. for (i = 0; i < arr->nelts; ++i) {
  944. char *path = (char*)ARRAY_IDX(arr, i, char*);
  945. if (str_has_suffix(path, ".temp") || str_has_suffix(path, ".info")) {
  946. #ifdef RVC_OS_WIN
  947. DeleteFileA(path);
  948. #else
  949. remove(path);
  950. #endif // RVC_OS_WIN
  951. }
  952. }
  953. toolkit_array_free2(arr);
  954. }
  955. LogEvent(Severity_Middle, EVENT_MOD_DOWNLOAD_SYNCHRONIZED, "下载目录同步完成");
  956. ScheduleTimer(5, 180000); // 3分钟后再次同步目录
  957. }
  958. void DownloadFSM::s5_on_exit()
  959. {
  960. LOG_FUNCTION();
  961. CancelTimer(5);
  962. }
  963. unsigned int DownloadFSM::s5_on_event(FSMEvent* event)
  964. {
  965. if (event->iEvt == EVT_TIMER)
  966. {
  967. PostEventLIFO(new FSMEvent(USER_EVT_SYNC_FINISHED));
  968. }
  969. return 0;
  970. }
  971. void DownloadFSM::nextTask(){
  972. download_file_t *file=NULL;
  973. m_current = NULL;
  974. std::list<download_file_t*>::iterator fIter=m_currentFileTask->begin();
  975. while(fIter!=m_currentFileTask->end()){
  976. file = *fIter;
  977. CSimpleStringA filename = file->name;
  978. m_current = download_storage_open(m_base_path, file);
  979. m_currentFileName = (LPCSTR)file->name;
  980. if(m_current!=NULL){
  981. //打开文件成功,判断是否完成
  982. if (m_current->offset_block_id<<15 >= file->length) { // finished!
  983. //因需要计算md5值,故需要先关闭前面连接句柄,否则打开文件失败
  984. #ifdef RVC_OS_WIN
  985. if (m_current->temp_handle != INVALID_HANDLE_VALUE) {
  986. CloseHandle(m_current->temp_handle);
  987. m_current->temp_handle = INVALID_HANDLE_VALUE;
  988. }
  989. #else
  990. if (m_current->temp_handle != NULL) {
  991. fclose(m_current->temp_handle);
  992. m_current->temp_handle = NULL;
  993. }
  994. #endif // RVC_OS_WIN
  995. int flag = download_check_MD5(m_current,file);
  996. //判断是否MD5一致,一致则下载成功,否则删除临时文件,重新等待下次下载
  997. if(flag==0){
  998. download_storage_close(m_current,true,false);//改名
  999. Dbg("send broadcast for file [%s] downloadResult status success 3", (LPCSTR)file->name);
  1000. returnDownloadFileResult(filename.GetData(),Error_Succeed,"downloadFile success");
  1001. deleteDownLoadFileWork(filename);//下载任务列表中任务删除
  1002. Dbg("file download success! [%s]", (LPCSTR)file->name);
  1003. }else{
  1004. //删除临时文件
  1005. download_storage_close(m_current,false,true);//删除
  1006. Dbg("file download fail! file MD5 is error ,file is delete and wait a moment download again [%s]", (LPCSTR)file->name);
  1007. }
  1008. m_current = NULL;
  1009. delete file;//删除对象内容
  1010. fIter = m_currentFileTask->erase(fIter);//正在下载的文件列表去除文件,并指向下一个文件
  1011. } else {
  1012. break;//进行任务下载
  1013. }
  1014. }else{
  1015. //打开文件失败,接着下一个任务
  1016. Dbg("file download fail! file storage open fail [%s]", (LPCSTR)file->name);
  1017. delete file;//删除对象内容
  1018. fIter = m_currentFileTask->erase(fIter);//正在下载的文件列表去除文件,并指向下一个文件
  1019. }
  1020. }
  1021. if (m_current) {
  1022. Dbg("begin download file: %s", file->name);
  1023. m_pConnection->SendFileReq(file->name, m_current->offset_block_id);
  1024. } else {
  1025. //下载完成
  1026. m_currentFileName = "";
  1027. PostEventLIFO(new FSMEvent(USER_EVT_JMP_SYNC));//goto S5
  1028. }
  1029. }