Терминальный проект КиберПлат [open source]
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

543 lines
16KB

  1. /* @file Инициализация и получение сервисов. */
  2. // Boost
  3. #include <boost/cast.hpp>
  4. // SDK
  5. #include <SDK/PaymentProcessor/Components.h>
  6. #include <SDK/PaymentProcessor/Core/EventTypes.h>
  7. // Project
  8. #include "System/IApplication.h"
  9. #include "Services/ServiceNames.h"
  10. #include "Services/EventService.h"
  11. #include "Services/PrintingService.h"
  12. #include "Services/FundsService.h"
  13. #include "Services/HIDService.h"
  14. #include "Services/DeviceService.h"
  15. #include "Services/CryptService.h"
  16. #include "Services/DatabaseService.h"
  17. #include "Services/PluginService.h"
  18. #include "Services/SettingsService.h"
  19. #include "Services/NetworkService.h"
  20. #include "Services/PaymentService.h"
  21. #include "Services/GUIService.h"
  22. #include "Services/TerminalService.h"
  23. #include "Services/RemoteService.h"
  24. #include "Services/HookService.h"
  25. #include "Services/SchedulerService.h"
  26. #include "Services/ServiceController.h"
  27. namespace PP = SDK::PaymentProcessor;
  28. namespace CServiceController
  29. {
  30. const int ShutdownRetryInterval = 1300;
  31. const QString RestartParameters = "RESTART_PARAMETERS";
  32. }
  33. //---------------------------------------------------------------------------
  34. ServiceController::ServiceController(IApplication * aApplication) :
  35. mApplication(aApplication),
  36. mFinalizeTimer(nullptr),
  37. mReturnCode(0)
  38. {
  39. }
  40. //---------------------------------------------------------------------------
  41. ServiceController::~ServiceController()
  42. {
  43. shutdownServices();
  44. }
  45. //---------------------------------------------------------------------------
  46. void ServiceController::registerService(PP::IService * aService)
  47. {
  48. mRegisteredServices.insert(aService->getName(), aService);
  49. }
  50. //---------------------------------------------------------------------------
  51. void ServiceController::onEvent(const PP::Event & aEvent)
  52. {
  53. switch (aEvent.getType())
  54. {
  55. case PPSDK::EEventType::Shutdown:
  56. {
  57. shutdownMachine();
  58. break;
  59. }
  60. case PPSDK::EEventType::Reboot:
  61. {
  62. rebootMachine();
  63. break;
  64. }
  65. case PPSDK::EEventType::Restart:
  66. {
  67. if (aEvent.hasData())
  68. {
  69. mUserProperties[CServiceController::RestartParameters] = aEvent.getData();
  70. }
  71. restartApplication();
  72. break;
  73. }
  74. case PP::EEventType::CloseApplication:
  75. case PP::EEventType::TerminateApplication:
  76. {
  77. shutdownServices();
  78. break;
  79. }
  80. case PP::EEventType::ReinitializeServices:
  81. {
  82. reinitializeServices();
  83. break;
  84. }
  85. // Остановка всего набора приложений. Вызывается из сервисного меню.
  86. case PPSDK::EEventType::StopSoftware:
  87. {
  88. mReturnCode = aEvent.getData().toMap().take("returnCode").toInt();
  89. auto wsClient = TerminalService::instance(mApplication)->getClient();
  90. if (wsClient && wsClient->isConnected())
  91. {
  92. wsClient->stopService();
  93. }
  94. else
  95. {
  96. EventService::instance(mApplication)->sendEvent(PPSDK::EEventType::CloseApplication, QVariant());
  97. }
  98. break;
  99. }
  100. }
  101. }
  102. //---------------------------------------------------------------------------
  103. bool ServiceController::initializeServices()
  104. {
  105. // Создаем EventService.
  106. EventService * eventService = new EventService();
  107. eventService->initialize();
  108. eventService->subscribe(this, SLOT(onEvent(const SDK::PaymentProcessor::Event &)));
  109. // Создаем необходимые сервисы.
  110. registerService(eventService);
  111. registerService(new PrintingService(mApplication));
  112. registerService(new FundsService(mApplication));
  113. registerService(new HIDService(mApplication));
  114. registerService(new SettingsService(mApplication));
  115. registerService(new DeviceService(mApplication));
  116. registerService(new DatabaseService(mApplication));
  117. registerService(new CryptService(mApplication));
  118. registerService(new PluginService(mApplication));
  119. registerService(new NetworkService(mApplication));
  120. registerService(new GUIService(mApplication));
  121. registerService(new PaymentService(mApplication));
  122. registerService(new TerminalService(mApplication));
  123. registerService(new RemoteService(mApplication));
  124. registerService(new HookService(mApplication));
  125. registerService(new SchedulerService(mApplication));
  126. mInitializedServices.clear();
  127. mFailedServices.clear();
  128. mShutdownOrder.clear();
  129. // Запуск процесса инициализации сервисов.
  130. mInitializedServices.insert(eventService->getName());
  131. mShutdownOrder.prepend(eventService);
  132. for (int pass = 0; pass < mRegisteredServices.size(); pass++)
  133. {
  134. foreach (PP::IService * service, mRegisteredServices)
  135. {
  136. // Если сервис не был инициализирован и инициализированы все зависимости, то инициализируем его.
  137. if (!mInitializedServices.contains(service->getName()) && !mFailedServices.contains(service->getName())
  138. && mInitializedServices.contains(service->getRequiredServices()))
  139. {
  140. LOG(mApplication->getLog(), LogLevel::Normal, QString("Initializing %1.").arg(service->getName()));
  141. if (service->initialize())
  142. {
  143. LOG(mApplication->getLog(), LogLevel::Normal, QString("Service %1 was initialized successfully.").arg(service->getName()));
  144. mInitializedServices.insert(service->getName());
  145. mShutdownOrder.prepend(service);
  146. }
  147. else
  148. {
  149. mFailedServices.insert(service->getName());
  150. }
  151. }
  152. }
  153. }
  154. if (mRegisteredServices.size() == mInitializedServices.size())
  155. {
  156. foreach (PP::IService * service, mRegisteredServices)
  157. {
  158. service->finishInitialize();
  159. }
  160. auto watchServiceClient = TerminalService::instance(mApplication)->getClient();
  161. watchServiceClient->subscribeOnDisconnected(this);
  162. watchServiceClient->subscribeOnCloseCommandReceived(this);
  163. initializeCoreItems();
  164. return true;
  165. }
  166. return false;
  167. }
  168. //---------------------------------------------------------------------------
  169. void ServiceController::initializeCoreItems()
  170. {
  171. auto pluginLoader = PluginService::instance(mApplication)->getPluginLoader();
  172. QStringList corePlugins = pluginLoader->getPluginList(QRegExp(QString("PaymentProcessor\\.%1\\..*").arg(PPSDK::CComponents::CoreItem)));
  173. foreach(const QString & pluginName, corePlugins)
  174. {
  175. LOG(mApplication->getLog(), LogLevel::Normal, QString("Create core item: %1.").arg(pluginName));
  176. auto plugin = pluginLoader->createPlugin(pluginName);
  177. if (plugin)
  178. {
  179. mCorePluginList << plugin;
  180. }
  181. }
  182. }
  183. //---------------------------------------------------------------------------
  184. void ServiceController::onDisconnected()
  185. {
  186. try
  187. {
  188. getEventService()->sendEvent(PPSDK::Event(PPSDK::EEventType::CloseApplication));
  189. }
  190. catch (std::bad_cast)
  191. {
  192. LOG(mApplication->getLog(), LogLevel::Fatal, "Event service was destroyed. Unable to send event 'CloseApplication' by Disconnected.");
  193. }
  194. }
  195. //---------------------------------------------------------------------------
  196. void ServiceController::onCloseCommandReceived()
  197. {
  198. try
  199. {
  200. getEventService()->sendEvent(PPSDK::Event(PPSDK::EEventType::CloseApplication));
  201. }
  202. catch (std::bad_cast)
  203. {
  204. LOG(mApplication->getLog(), LogLevel::Fatal, "Event service was destroyed. Unable to send event 'CloseApplication' by CloseCommand.");
  205. }
  206. }
  207. //---------------------------------------------------------------------------
  208. bool ServiceController::finalizeServices(const char * aRetrySlot)
  209. {
  210. auto delayFinalize = [&](const PP::IService * aService) -> bool
  211. {
  212. if (aService)
  213. {
  214. LOG(mApplication->getLog(), LogLevel::Warning, QString("Service %1 cannot be shutdown now, will try later.").arg(aService->getName()));
  215. }
  216. // Если не получилось, повторяем попытку через некоторое время.
  217. mFinalizeTimer = new QTimer(this);
  218. mFinalizeTimer->setSingleShot(true);
  219. QObject::connect(mFinalizeTimer, SIGNAL(timeout()), this, aRetrySlot);
  220. mFinalizeTimer->start(CServiceController::ShutdownRetryInterval);
  221. return false;
  222. };
  223. if (mFinalizeTimer)
  224. {
  225. delete mFinalizeTimer;
  226. mFinalizeTimer = nullptr;
  227. }
  228. if (!canShutdown())
  229. {
  230. return delayFinalize(nullptr);
  231. }
  232. finalizeCoreItems();
  233. // Пробуем остановить сервис.
  234. while (!mShutdownOrder.empty())
  235. {
  236. PP::IService * service = mShutdownOrder.front();
  237. QString serviceName = service->getName();
  238. LOG(mApplication->getLog(), LogLevel::Normal, QString("Trying to shutdown service %1...").arg(serviceName));
  239. if (service->shutdown())
  240. {
  241. mRegisteredServices.remove(service->getName());
  242. mShutdownOrder.pop_front();
  243. delete service;
  244. service = nullptr;
  245. LOG(mApplication->getLog(), LogLevel::Debug, QString("Service %1 shutdown OK...").arg(serviceName));
  246. }
  247. else
  248. {
  249. return delayFinalize(service);
  250. }
  251. }
  252. return true;
  253. }
  254. //---------------------------------------------------------------------------
  255. void ServiceController::finalizeCoreItems()
  256. {
  257. PluginService * ps = PluginService::instance(mApplication);
  258. if (ps)
  259. {
  260. auto pluginLoader = ps->getPluginLoader();
  261. foreach(auto coreItem, mCorePluginList)
  262. {
  263. LOG(mApplication->getLog(), LogLevel::Normal, QString("Destroy core item: %1.").arg(coreItem->getPluginName()));
  264. pluginLoader->destroyPlugin(coreItem);
  265. }
  266. }
  267. mCorePluginList.clear();
  268. }
  269. //---------------------------------------------------------------------------
  270. bool ServiceController::canShutdown()
  271. {
  272. foreach(auto service, mShutdownOrder)
  273. {
  274. if (!service->canShutdown())
  275. {
  276. LOG(mApplication->getLog(), LogLevel::Warning, QString("Service %1 cannot be shutdown now, will try later.").arg(service->getName()));
  277. return false;
  278. }
  279. }
  280. return true;
  281. }
  282. //---------------------------------------------------------------------------
  283. void ServiceController::shutdownServices()
  284. {
  285. if (finalizeServices(SLOT(shutdownServices())))
  286. {
  287. LOG(mApplication->getLog(), LogLevel::Normal, "Exit from ServiceController.");
  288. emit exit(mReturnCode);
  289. }
  290. }
  291. //---------------------------------------------------------------------------
  292. void ServiceController::reinitializeServices()
  293. {
  294. if (finalizeServices(SLOT(reinitializeServices())))
  295. {
  296. initializeServices();
  297. }
  298. }
  299. //---------------------------------------------------------------------------
  300. void ServiceController::rebootMachine()
  301. {
  302. if (canShutdown())
  303. {
  304. TerminalService::instance(mApplication)->getClient()->rebootMachine();
  305. }
  306. else
  307. {
  308. // Если не получилось, повторяем попытку через некоторое время.
  309. QTimer::singleShot(CServiceController::ShutdownRetryInterval, this, SLOT(rebootMachine()));
  310. }
  311. }
  312. //---------------------------------------------------------------------------
  313. void ServiceController::restartApplication()
  314. {
  315. if (canShutdown())
  316. {
  317. TerminalService::instance(mApplication)->getClient()->restartService(mUserProperties[CServiceController::RestartParameters].toStringList());
  318. }
  319. else
  320. {
  321. // Если не получилось, повторяем попытку через некоторое время.
  322. QTimer::singleShot(CServiceController::ShutdownRetryInterval, this, SLOT(restartApplication()));
  323. }
  324. }
  325. //---------------------------------------------------------------------------
  326. void ServiceController::shutdownMachine()
  327. {
  328. if (canShutdown())
  329. {
  330. TerminalService::instance(mApplication)->getClient()->shutdownMachine();
  331. }
  332. else
  333. {
  334. // Если не получилось, повторяем попытку через некоторое время.
  335. QTimer::singleShot(CServiceController::ShutdownRetryInterval, this, SLOT(shutdownMachine()));
  336. }
  337. }
  338. //---------------------------------------------------------------------------
  339. void ServiceController::dumpFailureReport()
  340. {
  341. QString failureInfo;
  342. foreach (const QString & serviceName, mFailedServices)
  343. {
  344. failureInfo += QString(" ") + serviceName;
  345. }
  346. // Выводим отчет о зависимостях.
  347. QString details;
  348. foreach (const PP::IService * service, mRegisteredServices.values())
  349. {
  350. QSet<QString> requiredSet = service->getRequiredServices();
  351. requiredSet.intersect(mFailedServices);
  352. if (!requiredSet.empty())
  353. {
  354. details += "\nService " + service->getName() + " requires service ";
  355. // Выводим список неинициализированных зависимостей.
  356. foreach (const QString & serviceName, requiredSet)
  357. {
  358. details += serviceName + ",";
  359. }
  360. details += " initialization skipped.";
  361. }
  362. }
  363. LOG(mApplication->getLog(), LogLevel::Fatal, QString("Services: %1 failed to initialize due to internal errors. %2").arg(failureInfo).arg(details));
  364. }
  365. //---------------------------------------------------------------------------
  366. QSet<SDK::PaymentProcessor::IService *> ServiceController::getServices() const
  367. {
  368. return mRegisteredServices.values().toSet();
  369. }
  370. //---------------------------------------------------------------------------
  371. SDK::PaymentProcessor::IRemoteService * ServiceController::getRemoteService() const
  372. {
  373. return boost::polymorphic_cast<PP::IRemoteService *>(mRegisteredServices.value(CServices::RemoteService));
  374. }
  375. //---------------------------------------------------------------------------
  376. SDK::PaymentProcessor::IPaymentService * ServiceController::getPaymentService() const
  377. {
  378. return boost::polymorphic_cast<PP::IPaymentService *>(mRegisteredServices.value(CServices::PaymentService));
  379. }
  380. //---------------------------------------------------------------------------
  381. SDK::PaymentProcessor::IFundsService * ServiceController::getFundsService() const
  382. {
  383. return boost::polymorphic_cast<PP::IFundsService *>(mRegisteredServices.value(CServices::FundsService));
  384. }
  385. //---------------------------------------------------------------------------
  386. SDK::PaymentProcessor::IPrinterService * ServiceController::getPrinterService() const
  387. {
  388. return boost::polymorphic_cast<PP::IPrinterService *>(mRegisteredServices.value(CServices::PrintingService));
  389. }
  390. //---------------------------------------------------------------------------
  391. SDK::PaymentProcessor::IHIDService * ServiceController::getHIDService() const
  392. {
  393. return boost::polymorphic_cast<PP::IHIDService *>(mRegisteredServices.value(CServices::HIDService));
  394. }
  395. //---------------------------------------------------------------------------
  396. SDK::PaymentProcessor::INetworkService * ServiceController::getNetworkService() const
  397. {
  398. return boost::polymorphic_cast<PP::INetworkService *>(mRegisteredServices.value(CServices::NetworkService));
  399. }
  400. //---------------------------------------------------------------------------
  401. SDK::PaymentProcessor::IEventService * ServiceController::getEventService() const
  402. {
  403. return boost::polymorphic_cast<PP::IEventService *>(mRegisteredServices.value(CServices::EventService));
  404. }
  405. //---------------------------------------------------------------------------
  406. SDK::PaymentProcessor::IGUIService * ServiceController::getGUIService() const
  407. {
  408. return boost::polymorphic_cast<PP::IGUIService *>(mRegisteredServices.value(CServices::GUIService));
  409. }
  410. //---------------------------------------------------------------------------
  411. SDK::PaymentProcessor::IDeviceService * ServiceController::getDeviceService() const
  412. {
  413. return boost::polymorphic_cast<PP::IDeviceService *>(mRegisteredServices.value(CServices::DeviceService));
  414. }
  415. //---------------------------------------------------------------------------
  416. SDK::PaymentProcessor::ICryptService * ServiceController::getCryptService() const
  417. {
  418. return boost::polymorphic_cast<PP::ICryptService *>(mRegisteredServices.value(CServices::CryptService));
  419. }
  420. //---------------------------------------------------------------------------
  421. SDK::PaymentProcessor::ISettingsService * ServiceController::getSettingsService() const
  422. {
  423. return boost::polymorphic_cast<PP::ISettingsService *>(mRegisteredServices.value(CServices::SettingsService));
  424. }
  425. //---------------------------------------------------------------------------
  426. SDK::PaymentProcessor::IDatabaseService * ServiceController::getDatabaseService() const
  427. {
  428. return boost::polymorphic_cast<PP::IDatabaseService *>(mRegisteredServices.value(CServices::DatabaseService));
  429. }
  430. //---------------------------------------------------------------------------
  431. SDK::PaymentProcessor::ITerminalService * ServiceController::getTerminalService() const
  432. {
  433. return boost::polymorphic_cast<PP::ITerminalService *>(mRegisteredServices.value(CServices::TerminalService));
  434. }
  435. //---------------------------------------------------------------------------
  436. SDK::PaymentProcessor::IService * ServiceController::getService(const QString & aServiceName) const
  437. {
  438. if (mRegisteredServices.isEmpty())
  439. {
  440. return nullptr;
  441. }
  442. if (mRegisteredServices.contains(aServiceName))
  443. {
  444. return mRegisteredServices.value(aServiceName);
  445. }
  446. throw PPSDK::ServiceIsNotImplemented(aServiceName);
  447. }
  448. //---------------------------------------------------------------------------
  449. QVariantMap & ServiceController::getUserProperties()
  450. {
  451. return mUserProperties;
  452. }
  453. //---------------------------------------------------------------------------