BranchDeviceFSM.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. #pragma once
  2. #include "SpFSM.h"
  3. #include "BranchDevice_server_g.h"
  4. #include "BranchDevice_def_g.h"
  5. #include "BranchDeviceClass.h"
  6. #include "TWProcHelper.h"
  7. #include <tchar.h>
  8. #include <strsafe.h>
  9. #include "../../Tool/spbranch/branch_def.h"
  10. using namespace SpBranch;
  11. #include <map>
  12. using namespace BranchDevice;
  13. typedef ErrorCodeEnum ( *LpCreateDevCom)(DeviceBaseClass *&baseObj);
  14. typedef ErrorCodeEnum ( *LpReleaseDevCom)(DeviceBaseClass *&pBaseObj);
  15. // Completion keys for the completion port
  16. #define COMPKEY_TERMINATE ((UINT_PTR) 0)
  17. #define COMPKEY_STATUS ((UINT_PTR) 1)
  18. #define COMPKEY_JOBOBJECT ((UINT_PTR) 2)
  19. #define CMDLINE_SIZE 520
  20. #define DEFAULT_MSG_SIZE 256
  21. #define MAX_MSG_SIZE 512
  22. #define DEFAULT_INFO_SIZE 630
  23. enum EvtType
  24. {
  25. USER_EVT_QUIT = (EVT_USER + 1),
  26. USER_EVT_OPEN,
  27. USER_EVT_CMD,
  28. USER_EVT_GETINFO,
  29. USER_EVT_OPENFINISHED,
  30. USER_EVT_CREATEPROCESS,
  31. USER_EVT_CREATEPROCESSFINISHED,
  32. USER_EVT_JOBNOTIFYSTART,
  33. USER_EVT_JOBNOTIFYFINISH,
  34. };
  35. struct BranchDevHandle
  36. {
  37. char szDevName[64];
  38. char szDevDllPath[MAX_PATH];
  39. //-1 dll_path error or get dev name error;
  40. //-2 process closed;
  41. //-3 invalid DevSN(temporary);
  42. //-4 get dev_params failed;
  43. //-5 invalid pipe status or create process failed;
  44. //-6 open device failed,
  45. //-7 load dll failed
  46. //=0 Normal
  47. //>0 returned from QueryDevice.
  48. int nStatus;
  49. int nReserved;
  50. char szInfo[DEFAULT_INFO_SIZE];
  51. };
  52. struct RWStruct {
  53. RWStruct()
  54. :hParentWrite(NULL),
  55. hParentRead(NULL),
  56. hChildWrite(NULL),
  57. hChildRead(NULL),
  58. dwProcessID(0),
  59. hFinishedFlag(NULL)
  60. {
  61. //empty.
  62. InitializeCriticalSection(&csExe);
  63. }
  64. ~RWStruct()
  65. {
  66. Cleanup();
  67. DeleteCriticalSection(&csExe);
  68. }
  69. BOOL IsValidRW()
  70. {
  71. if( ( hParentWrite == NULL || hParentWrite == INVALID_HANDLE_VALUE ) ||
  72. ( hParentRead == NULL || hParentRead == INVALID_HANDLE_VALUE ) ||
  73. ( hChildWrite == NULL || hChildWrite == INVALID_HANDLE_VALUE ) ||
  74. ( hChildRead == NULL || hChildRead == INVALID_HANDLE_VALUE ) ||
  75. dwProcessID == 0
  76. )
  77. {
  78. return FALSE;
  79. }
  80. return TRUE;
  81. }
  82. void Cleanup()
  83. {
  84. if(!( hParentWrite == NULL || hParentWrite == INVALID_HANDLE_VALUE ))
  85. {
  86. CloseHandle(hParentWrite);
  87. hParentWrite = NULL;
  88. }
  89. if(!( hParentRead == NULL || hParentRead == INVALID_HANDLE_VALUE ))
  90. {
  91. CloseHandle(hParentRead);
  92. hParentRead = NULL;
  93. }
  94. if(!( hChildWrite == NULL || hChildWrite == INVALID_HANDLE_VALUE ))
  95. {
  96. CloseHandle(hChildWrite);
  97. hChildWrite = NULL;
  98. }
  99. if(!( hChildRead == NULL || hChildRead == INVALID_HANDLE_VALUE ))
  100. {
  101. CloseHandle(hChildRead);
  102. hChildRead = NULL;
  103. }
  104. if(!( hFinishedFlag == NULL || hFinishedFlag == INVALID_HANDLE_VALUE ))
  105. {
  106. CloseHandle(hFinishedFlag);
  107. hFinishedFlag = NULL;
  108. }
  109. dwProcessID = 0;
  110. }
  111. HANDLE hParentWrite;
  112. HANDLE hParentRead;
  113. HANDLE hChildWrite;
  114. HANDLE hChildRead;
  115. DWORD dwProcessID;
  116. HANDLE hFinishedFlag;
  117. CRITICAL_SECTION csExe;
  118. };
  119. typedef RWStruct *PRWStruct;
  120. class CBranchDeviceFSM : public FSMImpl<CBranchDeviceFSM>
  121. {
  122. public:
  123. CBranchDeviceFSM():
  124. m_nDevNum(0),
  125. m_pDevHandles(NULL),
  126. m_pProcHelper(NULL),
  127. m_bNeedJob(FALSE),
  128. m_hNotifyFinishedEvent(NULL),
  129. m_pRWStr(NULL)
  130. {
  131. m_eCurState = Error_NotInit;
  132. m_pProcHelper = new CTWProcHelper();
  133. InitializeCriticalSection(&s_cs);
  134. }
  135. ~CBranchDeviceFSM()
  136. {
  137. Cleanup();
  138. DeleteCriticalSection(&s_cs);
  139. if(m_pProcHelper)
  140. {
  141. delete m_pProcHelper;
  142. m_pProcHelper = NULL;
  143. }
  144. }
  145. virtual ErrorCodeEnum OnInit();
  146. virtual ErrorCodeEnum OnExit();
  147. void SelfTest(EntityTestEnum eTestType,CSmartPointer<ITransactionContext> pTransactionContext);
  148. enum {s0, s1, s2, s3};
  149. BEGIN_FSM_STATE(CBranchDeviceFSM)
  150. FSM_STATE_ENTRY(s0, "Creating", s0_on_entry, s0_on_exit, s0_on_event)
  151. FSM_STATE_ENTRY(s1, "Opening", s1_on_entry, s1_on_exit, s1_on_event)
  152. FSM_STATE_ENTRY(s2, "Idle", s2_on_entry, s2_on_exit, s2_on_event)
  153. FSM_STATE_ENTRY(s3, "Failed", s3_on_entry, s3_on_exit, s3_on_event)
  154. END_FSM_STATE()
  155. BEGIN_FSM_RULE(CBranchDeviceFSM, s0)
  156. FSM_RULE_ENTRY(s0, s1, USER_EVT_CREATEPROCESSFINISHED, 0)
  157. FSM_RULE_ENTRY(s1, s2, USER_EVT_OPENFINISHED, 0)
  158. END_FSM_RULE()
  159. virtual void s0_on_entry();
  160. virtual void s0_on_exit();
  161. virtual unsigned int s0_on_event(FSMEvent* e);
  162. virtual void s1_on_entry();
  163. virtual void s1_on_exit();
  164. virtual unsigned int s1_on_event(FSMEvent* e);
  165. virtual void s2_on_entry();
  166. virtual void s2_on_exit();
  167. virtual unsigned int s2_on_event(FSMEvent* e);
  168. virtual void s3_on_entry();
  169. virtual void s3_on_exit();
  170. virtual unsigned int s3_on_event(FSMEvent* e);
  171. ErrorCodeEnum OpenDevs();
  172. ErrorCodeEnum OpenSpecifiedDev(int devSN);
  173. ErrorCodeEnum CreateAdapterLoadedProcesses();
  174. ErrorCodeEnum ReleaseDevs(bool bCloseDev = true);
  175. ErrorCodeEnum ReleaseSpcfDev(int devSN, bool bCloseDev);
  176. int GetDevCount() { return m_nDevNum; }
  177. void HandleCMD(SpReqAnsContext<BranchDeviceService_OpCmd_Req,
  178. BranchDeviceService_OpCmd_Ans>::Pointer ctx);
  179. void HandleGetInfo(SpReqAnsContext<BranchDeviceService_GetDevInfo_Req,
  180. BranchDeviceService_GetDevInfo_Ans>::Pointer ctx);
  181. static CRITICAL_SECTION s_cs;
  182. static UINT WINAPI DispatchThreadFunc( void* pArguments );
  183. SpReqAnsContext<BranchDeviceService_OpCmd_Req, BranchDeviceService_OpCmd_Ans>::Pointer m_ctx;
  184. BOOL JobInitialize();
  185. void JobNotify();
  186. void GetProcessName(DWORD PID, PTSTR szProcessName, size_t cchSize)
  187. {
  188. int aimIdx = -1;
  189. for(int idx=0; idx<m_nDevNum; idx++)
  190. {
  191. if(m_pRWStr[idx] != NULL && m_pRWStr[idx]->dwProcessID == PID)
  192. {
  193. aimIdx = idx;
  194. break;
  195. }
  196. }
  197. if(aimIdx != -1)
  198. {
  199. _tcscpy_s(szProcessName, cchSize, m_pDevHandles[aimIdx].szDevName);
  200. return;
  201. }
  202. if(!m_bNeedJob)
  203. {
  204. _tcscpy_s(szProcessName, cchSize, TEXT("???"));
  205. return;
  206. }
  207. return m_pProcHelper->GetProcessName(PID, szProcessName, cchSize);
  208. }
  209. //AnonyPipe
  210. BOOL CreateSpecifiedProcess(int);
  211. //default 30sec returned back.
  212. ErrorCodeEnum ProcessExchange(int nIdentifier,
  213. SpBranch_Command_Req& req, SpBranch_Command_Ans& ans,
  214. DWORD dwMillSec = 30000);
  215. BOOL RestartChildProcess(int idx);
  216. private:
  217. void Cleanup()
  218. {
  219. LOG_FUNCTION();
  220. EnterCriticalSection(&s_cs);
  221. if(m_bNeedJob)
  222. {
  223. m_bNeedJob = FALSE;
  224. UINT uExitCode = 0;
  225. m_pProcHelper->Terminate(uExitCode);
  226. // Post a special key that tells the completion port thread to terminate
  227. PostQueuedCompletionStatus(m_hIOCP, 0, COMPKEY_TERMINATE, NULL);
  228. //WaitForSingleObject(m_hNotifyFinishedEvent, 30000);
  229. Sleep(500);
  230. CloseHandle(m_hIOCP);
  231. CloseHandle(m_hNotifyFinishedEvent);
  232. for(int idx=0; idx<m_nDevNum; idx++)
  233. {
  234. if(m_pDevHandles != NULL && m_pDevHandles[idx].nReserved == 1)
  235. {
  236. if(m_pRWStr != NULL && m_pRWStr[idx] != NULL)
  237. {
  238. if(m_pProcHelper != NULL)
  239. m_pProcHelper->DestoryProcess(m_pRWStr[idx]->dwProcessID);
  240. }
  241. }
  242. }
  243. }
  244. if(m_nDevNum > 0)
  245. {
  246. Dbg("to destory malloced object...");
  247. //ReleaseDevs();
  248. free(m_pDevHandles);
  249. m_pDevHandles = NULL;
  250. for(int idx=0; idx<m_nDevNum; idx++)
  251. {
  252. m_pRWStr[idx]->Cleanup();
  253. delete m_pRWStr[idx];
  254. m_pRWStr[idx] = NULL;
  255. }
  256. free(m_pRWStr);
  257. m_pRWStr = NULL;
  258. m_nDevNum = 0;
  259. Dbg("Finish destorying.");
  260. }
  261. LeaveCriticalSection(&s_cs);
  262. }
  263. private:
  264. int m_nDevNum;
  265. BranchDevHandle* m_pDevHandles;
  266. CTWProcHelper* m_pProcHelper;
  267. BOOL m_bNeedJob;
  268. // Completion port that receives Job notifications
  269. HANDLE m_hIOCP;
  270. HANDLE m_hNotifyFinishedEvent;
  271. //AnonyPipe
  272. PRWStruct* m_pRWStr;
  273. ErrorCodeEnum m_eCurState;
  274. //For DualActive adapte -Josephus@201775 16:57:11
  275. CSimpleStringA m_strSpBranchPath;
  276. };
  277. class OperateCMDEvent : public FSMEvent
  278. {
  279. public:
  280. OperateCMDEvent() : FSMEvent(USER_EVT_CMD){}
  281. ~OperateCMDEvent(){}
  282. SpReqAnsContext<BranchDeviceService_OpCmd_Req,
  283. BranchDeviceService_OpCmd_Ans>::Pointer m_ctx;
  284. virtual void OnUnhandled()
  285. {
  286. if(m_ctx != NULL)
  287. {
  288. m_ctx->Answer(Error_InvalidState);
  289. }
  290. }
  291. };
  292. class GetInfoEvent : public FSMEvent
  293. {
  294. public:
  295. GetInfoEvent() : FSMEvent(USER_EVT_GETINFO){}
  296. ~GetInfoEvent(){}
  297. SpReqAnsContext<BranchDeviceService_GetDevInfo_Req,
  298. BranchDeviceService_GetDevInfo_Ans>::Pointer m_ctx;
  299. virtual void OnUnhandled()
  300. {
  301. if(m_ctx != NULL)
  302. {
  303. m_ctx->Answer(Error_InvalidState);
  304. }
  305. }
  306. };
  307. struct GetInfoTask : public ITaskSp
  308. {
  309. CBranchDeviceFSM* m_fsm;
  310. SpReqAnsContext<BranchDeviceService_GetDevInfo_Req,
  311. BranchDeviceService_GetDevInfo_Ans>::Pointer m_ctx;
  312. GetInfoTask(CBranchDeviceFSM* fsm): m_fsm(fsm){}
  313. void Process()
  314. {
  315. m_fsm->HandleGetInfo(m_ctx);
  316. return;
  317. }
  318. void SetContext(
  319. SpReqAnsContext<BranchDeviceService_GetDevInfo_Req,
  320. BranchDeviceService_GetDevInfo_Ans>::Pointer ctx)
  321. {
  322. m_ctx = ctx;
  323. return;
  324. }
  325. };
  326. struct OperateCMDTask : public ITaskSp
  327. {
  328. CBranchDeviceFSM* m_fsm;
  329. SpReqAnsContext<BranchDeviceService_OpCmd_Req,
  330. BranchDeviceService_OpCmd_Ans>::Pointer m_ctx;
  331. OperateCMDTask(CBranchDeviceFSM* fsm): m_fsm(fsm){}
  332. void Process()
  333. {
  334. //CTWProcHelper::SetThreadPrivilege(TRUE);
  335. m_fsm->HandleCMD(m_ctx);
  336. return;
  337. }
  338. void SetContext(
  339. SpReqAnsContext<BranchDeviceService_OpCmd_Req,
  340. BranchDeviceService_OpCmd_Ans>::Pointer ctx)
  341. {
  342. m_ctx = ctx;
  343. return;
  344. }
  345. };
  346. struct JobNotifyTask : public ITaskSp
  347. {
  348. CBranchDeviceFSM* m_fsm;
  349. JobNotifyTask(CBranchDeviceFSM* fsm): m_fsm(fsm){}
  350. void Process()
  351. {
  352. m_fsm->PostEventFIFO(new FSMEvent(USER_EVT_JOBNOTIFYSTART));
  353. m_fsm->JobNotify();
  354. m_fsm->PostEventFIFO(new FSMEvent(USER_EVT_JOBNOTIFYFINISH));
  355. }
  356. };
  357. struct OpenDeviceTask : public ITaskSp
  358. {
  359. CBranchDeviceFSM* m_fsm;
  360. OpenDeviceTask(CBranchDeviceFSM* fsm): m_fsm(fsm){}
  361. void Process()
  362. {
  363. //Open branchDevice sequentially. [Josephus in 10:19:43 2016/6/23]
  364. Sleep(800);
  365. m_fsm->OpenDevs();
  366. m_fsm->PostEventFIFO(new FSMEvent(USER_EVT_OPENFINISHED));
  367. }
  368. };
  369. struct CreateProcessTask : public ITaskSp
  370. {
  371. CBranchDeviceFSM* m_fsm;
  372. CreateProcessTask(CBranchDeviceFSM* fsm): m_fsm(fsm){}
  373. void Process()
  374. {
  375. m_fsm->CreateAdapterLoadedProcesses();
  376. m_fsm->PostEventFIFO(new FSMEvent(USER_EVT_CREATEPROCESSFINISHED));
  377. }
  378. };