panda-server-source 0.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (375) hide show
  1. panda_server_source-0.8.0.dist-info/METADATA +55 -0
  2. panda_server_source-0.8.0.dist-info/RECORD +375 -0
  3. panda_server_source-0.8.0.dist-info/WHEEL +4 -0
  4. panda_server_source-0.8.0.dist-info/licenses/LICENSE.txt +202 -0
  5. pandajedi/__init__.py +0 -0
  6. pandajedi/jedibrokerage/AtlasAnalJobBroker.py +2343 -0
  7. pandajedi/jedibrokerage/AtlasBrokerUtils.py +1292 -0
  8. pandajedi/jedibrokerage/AtlasProdJobBroker.py +2064 -0
  9. pandajedi/jedibrokerage/AtlasProdTaskBroker.py +629 -0
  10. pandajedi/jedibrokerage/GenJobBroker.py +381 -0
  11. pandajedi/jedibrokerage/JobBrokerBase.py +133 -0
  12. pandajedi/jedibrokerage/TaskBrokerBase.py +15 -0
  13. pandajedi/jedibrokerage/__init__.py +0 -0
  14. pandajedi/jediconfig/__init__.py +0 -0
  15. pandajedi/jediconfig/jedi_config.py +40 -0
  16. pandajedi/jedicore/FactoryBase.py +182 -0
  17. pandajedi/jedicore/Interaction.py +433 -0
  18. pandajedi/jedicore/JediDBProxy.py +56 -0
  19. pandajedi/jedicore/JediDBProxyPool.py +37 -0
  20. pandajedi/jedicore/JediDBSchemaInfo.py +17 -0
  21. pandajedi/jedicore/JediException.py +13 -0
  22. pandajedi/jedicore/JediTaskBuffer.py +984 -0
  23. pandajedi/jedicore/JediTaskBufferInterface.py +50 -0
  24. pandajedi/jedicore/MsgWrapper.py +124 -0
  25. pandajedi/jedicore/ProcessUtils.py +34 -0
  26. pandajedi/jedicore/SiteCandidate.py +90 -0
  27. pandajedi/jedicore/ThreadUtils.py +205 -0
  28. pandajedi/jedicore/__init__.py +0 -0
  29. pandajedi/jediddm/AtlasDDMClient.py +1708 -0
  30. pandajedi/jediddm/DDMClientBase.py +16 -0
  31. pandajedi/jediddm/DDMInterface.py +83 -0
  32. pandajedi/jediddm/GenDDMClient.py +17 -0
  33. pandajedi/jediddm/__init__.py +0 -0
  34. pandajedi/jedidog/AtlasAnalWatchDog.py +648 -0
  35. pandajedi/jedidog/AtlasDataCarouselWatchDog.py +189 -0
  36. pandajedi/jedidog/AtlasDataLocalityUpdaterWatchDog.py +215 -0
  37. pandajedi/jedidog/AtlasProdWatchDog.py +443 -0
  38. pandajedi/jedidog/AtlasQueueFillerWatchDog.py +800 -0
  39. pandajedi/jedidog/AtlasTaskWithholderWatchDog.py +245 -0
  40. pandajedi/jedidog/AtlasWorkflowManagerWatchDog.py +63 -0
  41. pandajedi/jedidog/GenWatchDog.py +21 -0
  42. pandajedi/jedidog/JumboWatchDog.py +147 -0
  43. pandajedi/jedidog/TypicalWatchDogBase.py +122 -0
  44. pandajedi/jedidog/WatchDogBase.py +53 -0
  45. pandajedi/jedidog/__init__.py +0 -0
  46. pandajedi/jediexec/reniceJEDI.py +25 -0
  47. pandajedi/jedigen/AtlasTaskGenerator.py +110 -0
  48. pandajedi/jedigen/TaskGeneratorBase.py +15 -0
  49. pandajedi/jedigen/__init__.py +0 -0
  50. pandajedi/jedimsgprocessor/__init__.py +0 -0
  51. pandajedi/jedimsgprocessor/ai_parameter_adjuster_msg_processor +71 -0
  52. pandajedi/jedimsgprocessor/atlas_idds_msg_processor.py +66 -0
  53. pandajedi/jedimsgprocessor/base_msg_processor.py +33 -0
  54. pandajedi/jedimsgprocessor/forwarding_msg_processor.py +29 -0
  55. pandajedi/jedimsgprocessor/hpo_msg_processor.py +93 -0
  56. pandajedi/jedimsgprocessor/jedi_contents_feeder_msg_processor.py +63 -0
  57. pandajedi/jedimsgprocessor/jedi_job_generator_msg_processor.py +185 -0
  58. pandajedi/jedimsgprocessor/jedi_post_processor_msg_processor.py +82 -0
  59. pandajedi/jedimsgprocessor/kafka_msg_processor.py +44 -0
  60. pandajedi/jedimsgprocessor/panda_callback_msg_processor.py +182 -0
  61. pandajedi/jedimsgprocessor/panda_to_jedi_msg_processor.py +74 -0
  62. pandajedi/jedimsgprocessor/processing_msg_processor.py +134 -0
  63. pandajedi/jedimsgprocessor/status_report_msg_processor.py +129 -0
  64. pandajedi/jedimsgprocessor/tape_carousel_msg_processor.py +118 -0
  65. pandajedi/jedimsgprocessor/workflow_manager_msg_processor.py +89 -0
  66. pandajedi/jediorder/ContentsFeeder.py +785 -0
  67. pandajedi/jediorder/JediDaemon.py +27 -0
  68. pandajedi/jediorder/JediKnight.py +55 -0
  69. pandajedi/jediorder/JediMaster.py +238 -0
  70. pandajedi/jediorder/JediMsgProcessor.py +32 -0
  71. pandajedi/jediorder/JobBroker.py +33 -0
  72. pandajedi/jediorder/JobGenerator.py +2763 -0
  73. pandajedi/jediorder/JobSplitter.py +308 -0
  74. pandajedi/jediorder/JobThrottler.py +28 -0
  75. pandajedi/jediorder/PostProcessor.py +166 -0
  76. pandajedi/jediorder/TaskBroker.py +268 -0
  77. pandajedi/jediorder/TaskCommando.py +334 -0
  78. pandajedi/jediorder/TaskGenerator.py +17 -0
  79. pandajedi/jediorder/TaskRefiner.py +611 -0
  80. pandajedi/jediorder/TaskSetupper.py +17 -0
  81. pandajedi/jediorder/WatchDog.py +79 -0
  82. pandajedi/jediorder/__init__.py +0 -0
  83. pandajedi/jedipprocess/AtlasAnalPostProcessor.py +404 -0
  84. pandajedi/jedipprocess/AtlasPostProcessorUtils.py +50 -0
  85. pandajedi/jedipprocess/AtlasProdPostProcessor.py +178 -0
  86. pandajedi/jedipprocess/GenPostProcessor.py +35 -0
  87. pandajedi/jedipprocess/MailTemplates.py +185 -0
  88. pandajedi/jedipprocess/PostProcessorBase.py +269 -0
  89. pandajedi/jedipprocess/__init__.py +0 -0
  90. pandajedi/jedirefine/AtlasAnalTaskRefiner.py +259 -0
  91. pandajedi/jedirefine/AtlasProdTaskRefiner.py +162 -0
  92. pandajedi/jedirefine/GenTaskRefiner.py +61 -0
  93. pandajedi/jedirefine/RefinerUtils.py +154 -0
  94. pandajedi/jedirefine/TaskRefinerBase.py +996 -0
  95. pandajedi/jedirefine/__init__.py +0 -0
  96. pandajedi/jedisetup/AtlasTaskSetupper.py +309 -0
  97. pandajedi/jedisetup/GenTaskSetupper.py +16 -0
  98. pandajedi/jedisetup/SimpleTaskSetupper.py +152 -0
  99. pandajedi/jedisetup/TaskSetupperBase.py +15 -0
  100. pandajedi/jedisetup/__init__.py +0 -0
  101. pandajedi/jeditest/SchemaChecker.py +41 -0
  102. pandajedi/jeditest/addContWoSoTask.py +54 -0
  103. pandajedi/jeditest/addDataCarouselRequest.py +47 -0
  104. pandajedi/jeditest/addEventServiceTask.py +101 -0
  105. pandajedi/jeditest/addHpoTask.py +81 -0
  106. pandajedi/jeditest/addIDDSStageInRequest.py +56 -0
  107. pandajedi/jeditest/addNonAtlasTask.py +71 -0
  108. pandajedi/jeditest/addNonAtlasTaskEnc.py +64 -0
  109. pandajedi/jeditest/addTestTask.py +124 -0
  110. pandajedi/jeditest/addTestTaskParamToDEFT.py +70 -0
  111. pandajedi/jeditest/addTestTaskWithMerger.py +97 -0
  112. pandajedi/jeditest/brokerTest.py +78 -0
  113. pandajedi/jeditest/cancelDataCarouselRequest.py +35 -0
  114. pandajedi/jeditest/contentsFeederTest.py +28 -0
  115. pandajedi/jeditest/contentsFeederTestWithTask.py +18 -0
  116. pandajedi/jeditest/ddmTest.py +4 -0
  117. pandajedi/jeditest/jobGenForOneTask.py +38 -0
  118. pandajedi/jeditest/jobGeneratorTest.py +43 -0
  119. pandajedi/jeditest/jobSplitterTest.py +104 -0
  120. pandajedi/jeditest/jobThrottlerTest.py +22 -0
  121. pandajedi/jeditest/msgProcessorTest.py +9 -0
  122. pandajedi/jeditest/postProcessorTest.py +18 -0
  123. pandajedi/jeditest/resubmitDataCarouselRequest.py +35 -0
  124. pandajedi/jeditest/resubmitTaskParam.py +20 -0
  125. pandajedi/jeditest/taskBrokerTest.py +22 -0
  126. pandajedi/jeditest/taskBrokerTestWithTask.py +38 -0
  127. pandajedi/jeditest/taskBufferTest.py +5 -0
  128. pandajedi/jeditest/taskCommandoTest.py +28 -0
  129. pandajedi/jeditest/taskRefinerTest.py +30 -0
  130. pandajedi/jeditest/testOneTaskToRefine.py +49 -0
  131. pandajedi/jeditest/testOneTaskToTaskBroker.py +42 -0
  132. pandajedi/jeditest/testPandaDDMMap.py +62 -0
  133. pandajedi/jeditest/updateDataCarouselRequestParams.py +50 -0
  134. pandajedi/jeditest/watchDogTest.py +25 -0
  135. pandajedi/jeditest/workQueueTest.py +22 -0
  136. pandajedi/jedithrottle/AtlasAnalJobThrottler.py +19 -0
  137. pandajedi/jedithrottle/AtlasProdJobThrottler.py +18 -0
  138. pandajedi/jedithrottle/GenJobThrottler.py +26 -0
  139. pandajedi/jedithrottle/JobThrottlerBase.py +496 -0
  140. pandajedi/jedithrottle/__init__.py +0 -0
  141. pandaserver/__init__.py +0 -0
  142. pandaserver/api/__init__.py +0 -0
  143. pandaserver/api/v1/__init__.py +0 -0
  144. pandaserver/api/v1/common.py +339 -0
  145. pandaserver/api/v1/credential_management_api.py +372 -0
  146. pandaserver/api/v1/data_carousel_api.py +264 -0
  147. pandaserver/api/v1/event_api.py +269 -0
  148. pandaserver/api/v1/file_server_api.py +942 -0
  149. pandaserver/api/v1/harvester_api.py +445 -0
  150. pandaserver/api/v1/http_client.py +166 -0
  151. pandaserver/api/v1/idds_api.py +180 -0
  152. pandaserver/api/v1/job_api.py +463 -0
  153. pandaserver/api/v1/metaconfig_api.py +122 -0
  154. pandaserver/api/v1/pilot_api.py +895 -0
  155. pandaserver/api/v1/statistics_api.py +207 -0
  156. pandaserver/api/v1/system_api.py +186 -0
  157. pandaserver/api/v1/task_api.py +1520 -0
  158. pandaserver/api/v1/tests/__init__.py +0 -0
  159. pandaserver/api/v1/tests/credential_management_api_tests.py +116 -0
  160. pandaserver/api/v1/tests/data_carousel_api_tests.py +82 -0
  161. pandaserver/api/v1/tests/harvester_api_tests.py +188 -0
  162. pandaserver/api/v1/tests/idds_api_tests.py +45 -0
  163. pandaserver/api/v1/tests/job_api_tests.py +112 -0
  164. pandaserver/api/v1/tests/pilot_api_tests.py +154 -0
  165. pandaserver/api/v1/tests/statistics_api_tests.py +104 -0
  166. pandaserver/api/v1/tests/system_api_tests.py +58 -0
  167. pandaserver/api/v1/tests/task_api_tests.py +590 -0
  168. pandaserver/api/v1/version.py +2 -0
  169. pandaserver/api/v1/workflow_api.py +136 -0
  170. pandaserver/brokerage/SiteMapper.py +406 -0
  171. pandaserver/brokerage/__init__.py +0 -0
  172. pandaserver/brokerage/broker.py +272 -0
  173. pandaserver/config/__init__.py +0 -0
  174. pandaserver/config/config_utils.py +15 -0
  175. pandaserver/config/daemon_config.py +29 -0
  176. pandaserver/config/mcp_config.py +38 -0
  177. pandaserver/config/panda_config.py +233 -0
  178. pandaserver/configurator/Carbon.py +65 -0
  179. pandaserver/configurator/Configurator.py +908 -0
  180. pandaserver/configurator/__init__.py +0 -0
  181. pandaserver/configurator/aux.py +73 -0
  182. pandaserver/daemons/__init__.py +0 -0
  183. pandaserver/daemons/master.py +110 -0
  184. pandaserver/daemons/master_systemd.py +79 -0
  185. pandaserver/daemons/scripts/__init__.py +0 -0
  186. pandaserver/daemons/scripts/add_main.py +264 -0
  187. pandaserver/daemons/scripts/add_sub.py +221 -0
  188. pandaserver/daemons/scripts/cache_pilots.py +47 -0
  189. pandaserver/daemons/scripts/cache_schedconfig.py +286 -0
  190. pandaserver/daemons/scripts/carbon.py +50 -0
  191. pandaserver/daemons/scripts/configurator.py +94 -0
  192. pandaserver/daemons/scripts/copyArchive.py +1387 -0
  193. pandaserver/daemons/scripts/datasetManager.py +1154 -0
  194. pandaserver/daemons/scripts/dummy_test.py +25 -0
  195. pandaserver/daemons/scripts/evpPD2P.py +144 -0
  196. pandaserver/daemons/scripts/hs_scrapers.py +264 -0
  197. pandaserver/daemons/scripts/metric_collector.py +927 -0
  198. pandaserver/daemons/scripts/panda_activeusers_query.py +80 -0
  199. pandaserver/daemons/scripts/pilotStreaming.py +109 -0
  200. pandaserver/daemons/scripts/process_workflow_files_daemon.py +166 -0
  201. pandaserver/daemons/scripts/recover_lost_files_daemon.py +177 -0
  202. pandaserver/daemons/scripts/task_evaluator.py +405 -0
  203. pandaserver/daemons/scripts/tmpwatch.py +70 -0
  204. pandaserver/daemons/scripts/worker_synchronization.py +97 -0
  205. pandaserver/daemons/utils.py +753 -0
  206. pandaserver/dataservice/DataServiceUtils.py +323 -0
  207. pandaserver/dataservice/ErrorCode.py +25 -0
  208. pandaserver/dataservice/RecoverLostFilesCore.py +322 -0
  209. pandaserver/dataservice/__init__.py +0 -0
  210. pandaserver/dataservice/activator.py +79 -0
  211. pandaserver/dataservice/adder_atlas_plugin.py +1106 -0
  212. pandaserver/dataservice/adder_dummy_plugin.py +31 -0
  213. pandaserver/dataservice/adder_gen.py +954 -0
  214. pandaserver/dataservice/adder_plugin_base.py +27 -0
  215. pandaserver/dataservice/adder_result.py +75 -0
  216. pandaserver/dataservice/adder_simple_plugin.py +160 -0
  217. pandaserver/dataservice/closer.py +247 -0
  218. pandaserver/dataservice/closer_atlas_plugin.py +90 -0
  219. pandaserver/dataservice/ddm.py +1381 -0
  220. pandaserver/dataservice/ddm_handler.py +95 -0
  221. pandaserver/dataservice/dyn_data_distributer.py +824 -0
  222. pandaserver/dataservice/event_lookup_client_ei.py +77 -0
  223. pandaserver/dataservice/event_picker.py +268 -0
  224. pandaserver/dataservice/finisher.py +194 -0
  225. pandaserver/dataservice/setupper.py +225 -0
  226. pandaserver/dataservice/setupper_atlas_plugin.py +1851 -0
  227. pandaserver/dataservice/setupper_dummy_plugin.py +47 -0
  228. pandaserver/dataservice/setupper_plugin_base.py +67 -0
  229. pandaserver/jobdispatcher/DispatcherUtils.py +35 -0
  230. pandaserver/jobdispatcher/ErrorCode.py +19 -0
  231. pandaserver/jobdispatcher/JobDispatcher.py +1625 -0
  232. pandaserver/jobdispatcher/Protocol.py +443 -0
  233. pandaserver/jobdispatcher/Watcher.py +186 -0
  234. pandaserver/jobdispatcher/__init__.py +0 -0
  235. pandaserver/pandamcp/__init__.py +0 -0
  236. pandaserver/pandamcp/mcp_main.py +56 -0
  237. pandaserver/pandamcp/mcp_test_client.py +95 -0
  238. pandaserver/pandamcp/mcp_utils.py +74 -0
  239. pandaserver/proxycache/__init__.py +0 -0
  240. pandaserver/proxycache/panda_proxy_cache.py +240 -0
  241. pandaserver/proxycache/token_cache.py +141 -0
  242. pandaserver/server/.gacl +6 -0
  243. pandaserver/server/panda.py +539 -0
  244. pandaserver/srvcore/CoreUtils.py +572 -0
  245. pandaserver/srvcore/MailUtils.py +106 -0
  246. pandaserver/srvcore/__init__.py +0 -0
  247. pandaserver/srvcore/allowed_methods.py +100 -0
  248. pandaserver/srvcore/oidc_utils.py +152 -0
  249. pandaserver/srvcore/panda_request.py +196 -0
  250. pandaserver/srvcore/srv_msg_utils.py +42 -0
  251. pandaserver/taskbuffer/ConBridge.py +513 -0
  252. pandaserver/taskbuffer/DBProxyPool.py +95 -0
  253. pandaserver/taskbuffer/DataCarousel.py +3053 -0
  254. pandaserver/taskbuffer/DatasetSpec.py +137 -0
  255. pandaserver/taskbuffer/DdmSpec.py +201 -0
  256. pandaserver/taskbuffer/ErrorCode.py +87 -0
  257. pandaserver/taskbuffer/EventServiceUtils.py +396 -0
  258. pandaserver/taskbuffer/FileSpec.py +290 -0
  259. pandaserver/taskbuffer/GlobalShares.py +244 -0
  260. pandaserver/taskbuffer/HarvesterMetricsSpec.py +92 -0
  261. pandaserver/taskbuffer/Initializer.py +82 -0
  262. pandaserver/taskbuffer/InputChunk.py +1080 -0
  263. pandaserver/taskbuffer/JediCacheSpec.py +57 -0
  264. pandaserver/taskbuffer/JediDatasetSpec.py +588 -0
  265. pandaserver/taskbuffer/JediFileSpec.py +242 -0
  266. pandaserver/taskbuffer/JediTaskSpec.py +1687 -0
  267. pandaserver/taskbuffer/JobSpec.py +1006 -0
  268. pandaserver/taskbuffer/JobUtils.py +232 -0
  269. pandaserver/taskbuffer/NucleusSpec.py +116 -0
  270. pandaserver/taskbuffer/OraDBProxy.py +174 -0
  271. pandaserver/taskbuffer/PanDAMsgProcessor.py +8 -0
  272. pandaserver/taskbuffer/PandaDBSchemaInfo.py +18 -0
  273. pandaserver/taskbuffer/ParseJobXML.py +350 -0
  274. pandaserver/taskbuffer/PickleFileSpec.py +18 -0
  275. pandaserver/taskbuffer/PickleJobSpec.py +25 -0
  276. pandaserver/taskbuffer/PrioUtil.py +40 -0
  277. pandaserver/taskbuffer/ProcessGroups.py +111 -0
  278. pandaserver/taskbuffer/ResourceSpec.py +175 -0
  279. pandaserver/taskbuffer/SQLDumper.py +37 -0
  280. pandaserver/taskbuffer/SQLManager.py +60 -0
  281. pandaserver/taskbuffer/SiteSpec.py +304 -0
  282. pandaserver/taskbuffer/SupErrors.py +10 -0
  283. pandaserver/taskbuffer/TaskBuffer.py +2882 -0
  284. pandaserver/taskbuffer/TaskBufferInterface.py +163 -0
  285. pandaserver/taskbuffer/Utils.py +848 -0
  286. pandaserver/taskbuffer/WorkQueue.py +227 -0
  287. pandaserver/taskbuffer/WorkQueueMapper.py +203 -0
  288. pandaserver/taskbuffer/WorkerSpec.py +143 -0
  289. pandaserver/taskbuffer/WrappedCursor.py +487 -0
  290. pandaserver/taskbuffer/WrappedPickle.py +88 -0
  291. pandaserver/taskbuffer/WrappedPostgresConn.py +24 -0
  292. pandaserver/taskbuffer/__init__.py +0 -0
  293. pandaserver/taskbuffer/db_proxy_mods/OraDBProxy_structure.png +0 -0
  294. pandaserver/taskbuffer/db_proxy_mods/__init__.py +7 -0
  295. pandaserver/taskbuffer/db_proxy_mods/base_module.py +841 -0
  296. pandaserver/taskbuffer/db_proxy_mods/data_carousel_module.py +772 -0
  297. pandaserver/taskbuffer/db_proxy_mods/entity_module.py +3804 -0
  298. pandaserver/taskbuffer/db_proxy_mods/job_complex_module.py +5661 -0
  299. pandaserver/taskbuffer/db_proxy_mods/job_standalone_module.py +2640 -0
  300. pandaserver/taskbuffer/db_proxy_mods/metrics_module.py +874 -0
  301. pandaserver/taskbuffer/db_proxy_mods/misc_standalone_module.py +4272 -0
  302. pandaserver/taskbuffer/db_proxy_mods/task_complex_module.py +6172 -0
  303. pandaserver/taskbuffer/db_proxy_mods/task_event_module.py +4953 -0
  304. pandaserver/taskbuffer/db_proxy_mods/task_standalone_module.py +4999 -0
  305. pandaserver/taskbuffer/db_proxy_mods/task_utils_module.py +2063 -0
  306. pandaserver/taskbuffer/db_proxy_mods/worker_module.py +1944 -0
  307. pandaserver/taskbuffer/db_proxy_mods/workflow_module.py +832 -0
  308. pandaserver/taskbuffer/retryModule.py +552 -0
  309. pandaserver/taskbuffer/task_split_rules.py +308 -0
  310. pandaserver/taskbuffer/workflow_processor.py +249 -0
  311. pandaserver/taskbuffer/wrapped_oracle_conn.py +18 -0
  312. pandaserver/test/SchemaChecker.py +40 -0
  313. pandaserver/test/__init__.py +0 -0
  314. pandaserver/test/banUser.py +43 -0
  315. pandaserver/test/boostPrio.py +19 -0
  316. pandaserver/test/boostUser.py +35 -0
  317. pandaserver/test/callbackDDM.py +11 -0
  318. pandaserver/test/daod_on_demand.py +95 -0
  319. pandaserver/test/finishJob.py +184 -0
  320. pandaserver/test/finishTaskJEDI.py +11 -0
  321. pandaserver/test/getJobs.py +53 -0
  322. pandaserver/test/killJob.py +79 -0
  323. pandaserver/test/killJobLowPrio.py +99 -0
  324. pandaserver/test/killJobsInTask.py +56 -0
  325. pandaserver/test/killTask.py +80 -0
  326. pandaserver/test/killTaskJEDI.py +11 -0
  327. pandaserver/test/killUser.py +83 -0
  328. pandaserver/test/lsst/README.txt +7 -0
  329. pandaserver/test/lsst/lsstSubmit.py +139 -0
  330. pandaserver/test/lsst/lsstSubmitMERGEtest.py +141 -0
  331. pandaserver/test/lsst/lsstSubmitPhosim332.py +53 -0
  332. pandaserver/test/lsst/prepare-client-tarball-from-bigpanda-server.sh +41 -0
  333. pandaserver/test/reassignJobs.py +17 -0
  334. pandaserver/test/reassignSite.py +82 -0
  335. pandaserver/test/reassignTask.py +117 -0
  336. pandaserver/test/reassignWaiting.py +39 -0
  337. pandaserver/test/recoverLostFiles.py +7 -0
  338. pandaserver/test/reloadInputDS.py +51 -0
  339. pandaserver/test/sendCommandToJob.py +26 -0
  340. pandaserver/test/setDebugMode.py +38 -0
  341. pandaserver/test/setPriority.py +28 -0
  342. pandaserver/test/testEvgen.py +60 -0
  343. pandaserver/test/testEvgen17.py +58 -0
  344. pandaserver/test/testG4sim.py +81 -0
  345. pandaserver/test/testG4sim17.py +90 -0
  346. pandaserver/test/testGlobalShares.py +131 -0
  347. pandaserver/test/testReco.py +103 -0
  348. pandaserver/test/testSimulReco14.py +98 -0
  349. pandaserver/test/testSiteMap.py +26 -0
  350. pandaserver/test/testUpdateWorkerPilotStatus.py +9 -0
  351. pandaserver/userinterface/Client.py +1686 -0
  352. pandaserver/userinterface/UserIF.py +1799 -0
  353. pandaserver/userinterface/__init__.py +0 -0
  354. pandaserver/workflow/__init__.py +0 -0
  355. pandaserver/workflow/data_handler_plugins/base_data_handler.py +48 -0
  356. pandaserver/workflow/data_handler_plugins/ddm_collection_data_handler.py +100 -0
  357. pandaserver/workflow/data_handler_plugins/panda_task_data_handler.py +140 -0
  358. pandaserver/workflow/pcwl_test.py +122 -0
  359. pandaserver/workflow/pcwl_utils.py +384 -0
  360. pandaserver/workflow/psnakemake_container.json +68 -0
  361. pandaserver/workflow/psnakemake_task.json +62 -0
  362. pandaserver/workflow/psnakemake_test.py +60 -0
  363. pandaserver/workflow/snakeparser/__init__.py +3 -0
  364. pandaserver/workflow/snakeparser/extensions.py +74 -0
  365. pandaserver/workflow/snakeparser/log.py +53 -0
  366. pandaserver/workflow/snakeparser/names.py +3 -0
  367. pandaserver/workflow/snakeparser/parser.py +332 -0
  368. pandaserver/workflow/snakeparser/utils.py +29 -0
  369. pandaserver/workflow/step_handler_plugins/base_step_handler.py +85 -0
  370. pandaserver/workflow/step_handler_plugins/panda_task_step_handler.py +280 -0
  371. pandaserver/workflow/workflow_base.py +531 -0
  372. pandaserver/workflow/workflow_core.py +1974 -0
  373. pandaserver/workflow/workflow_core_smoketest.py +388 -0
  374. pandaserver/workflow/workflow_parser.py +222 -0
  375. pandaserver/workflow/workflow_utils.py +1047 -0
@@ -0,0 +1,308 @@
1
+ import copy
2
+
3
+ from pandacommon.pandalogger.PandaLogger import PandaLogger
4
+
5
+ from pandajedi.jedicore import Interaction
6
+ from pandajedi.jedicore.MsgWrapper import MsgWrapper
7
+ from pandaserver.srvcore import CoreUtils
8
+ from pandaserver.taskbuffer.InputChunk import InputChunk
9
+
10
+ logger = PandaLogger().getLogger(__name__.split(".")[-1])
11
+
12
+
13
+ # class to split job
14
+ class JobSplitter:
15
+ # constructor
16
+ def __init__(self):
17
+ self.sizeGradientsPerInSizeForMerge = 1.2
18
+ self.interceptsMerginForMerge = 500 * 1024 * 1024
19
+
20
+ # split
21
+ def doSplit(self, taskSpec, inputChunk, siteMapper, allow_chunk_size_limit=False):
22
+ # return for failure
23
+ retFatal = self.SC_FATAL, []
24
+ retTmpError = self.SC_FAILED, []
25
+ # make logger
26
+ tmpLog = MsgWrapper(logger, f"< jediTaskID={taskSpec.jediTaskID} datasetID={inputChunk.masterIndexName} >")
27
+ tmpLog.debug(f"--- start chunk_size_limit={allow_chunk_size_limit}")
28
+ if not inputChunk.isMerging:
29
+ # set maxNumFiles using taskSpec if specified
30
+ maxNumFiles = taskSpec.getMaxNumFilesPerJob()
31
+ # set fsize gradients using taskSpec
32
+ sizeGradients = taskSpec.getOutDiskSize()
33
+ # set fsize intercepts using taskSpec
34
+ sizeIntercepts = taskSpec.getWorkDiskSize()
35
+ # walltime
36
+ if not taskSpec.useHS06():
37
+ walltimeGradient = taskSpec.walltime
38
+ else:
39
+ walltimeGradient = taskSpec.getCpuTime()
40
+ # number of events per job if defined
41
+ nEventsPerJob = taskSpec.getNumEventsPerJob()
42
+ # number of files per job if defined
43
+ nFilesPerJob = taskSpec.getNumFilesPerJob()
44
+ if nFilesPerJob is None and nEventsPerJob is None and inputChunk.useScout() and not taskSpec.useLoadXML() and not taskSpec.respectSplitRule():
45
+ nFilesPerJob = 1
46
+ # grouping with boundaryID
47
+ useBoundary = taskSpec.useGroupWithBoundaryID()
48
+ # fsize intercepts per input size
49
+ sizeGradientsPerInSize = None
50
+ # set max primay output size to avoid producing huge unmerged files
51
+ maxOutSize = 10 * 1024 * 1024 * 1024
52
+ # max size per job
53
+ maxSizePerJob = taskSpec.getMaxSizePerJob()
54
+ if maxSizePerJob is not None:
55
+ maxSizePerJob += InputChunk.defaultOutputSize
56
+ # multiplicity of jobs
57
+ if taskSpec.useJobCloning():
58
+ multiplicity = 1
59
+ else:
60
+ multiplicity = taskSpec.getNumEventServiceConsumer()
61
+ # split with fields
62
+ if taskSpec.getFieldNumToLFN() is not None and taskSpec.useFileAsSourceLFN():
63
+ splitByFields = taskSpec.getFieldNumToLFN()
64
+ else:
65
+ splitByFields = None
66
+ else:
67
+ # set parameters for merging
68
+ maxNumFiles = taskSpec.getMaxNumFilesPerMergeJob()
69
+ sizeGradients = 0
70
+ walltimeGradient = 0
71
+ nFilesPerJob = taskSpec.getNumFilesPerMergeJob()
72
+ nEventsPerJob = taskSpec.getNumEventsPerMergeJob()
73
+ maxSizePerJob = None
74
+ useBoundary = {"inSplit": 3}
75
+ multiplicity = None
76
+ # gradients per input size is 1 + margin
77
+ sizeGradientsPerInSize = self.sizeGradientsPerInSizeForMerge
78
+ # intercepts for libDS
79
+ sizeIntercepts = taskSpec.getWorkDiskSize()
80
+ # mergein of 500MB
81
+ interceptsMergin = self.interceptsMerginForMerge
82
+ if sizeIntercepts < interceptsMergin:
83
+ sizeIntercepts = interceptsMergin
84
+ maxOutSize = taskSpec.getMaxSizePerMergeJob()
85
+ if maxOutSize is None:
86
+ # max output size is 5GB for merging by default
87
+ maxOutSize = 5 * 1024 * 1024 * 1024
88
+ # split with fields
89
+ if taskSpec.getFieldNumToLFN() is not None and taskSpec.useFileAsSourceLFN():
90
+ splitByFields = list(range(4 + 1, 4 + 1 + len(taskSpec.getFieldNumToLFN())))
91
+ else:
92
+ splitByFields = None
93
+ # LB
94
+ respectLB = taskSpec.respectLumiblock()
95
+ # no split for on-site merging
96
+ if taskSpec.on_site_merging():
97
+ no_split = True
98
+ else:
99
+ no_split = False
100
+ # dump
101
+ tmpLog.debug(f"maxNumFiles={maxNumFiles} sizeGradients={sizeGradients} sizeIntercepts={sizeIntercepts} useBoundary={useBoundary}")
102
+ tmpLog.debug(f"walltimeGradient={walltimeGradient} nFilesPerJob={nFilesPerJob} nEventsPerJob={nEventsPerJob}")
103
+ tmpLog.debug(f"useScout={inputChunk.useScout()} isMerging={inputChunk.isMerging}")
104
+ tmpLog.debug(f"sizeGradientsPerInSize={sizeGradientsPerInSize} maxOutSize={maxOutSize} respectLB={respectLB}")
105
+ tmpLog.debug(
106
+ f"multiplicity={multiplicity} splitByFields={str(splitByFields)} "
107
+ f"nFiles={inputChunk.getNumFilesInMaster()} no_split={no_split} "
108
+ f"maxEventsPerJob={taskSpec.get_max_events_per_job()}"
109
+ )
110
+ tmpLog.debug("--- main loop")
111
+ # split
112
+ returnList = []
113
+ subChunks = []
114
+ iSubChunks = 0
115
+ if inputChunk.useScout() and not inputChunk.isMerging:
116
+ default_nSubChunks = 2
117
+ elif taskSpec.is_hpo_workflow():
118
+ default_nSubChunks = 2
119
+ else:
120
+ default_nSubChunks = 25
121
+ subChunk = None
122
+ nSubChunks = default_nSubChunks
123
+ strict_chunkSize = False
124
+ tmp_ng_list = []
125
+ change_site_for_dist_dataset = False
126
+ while True:
127
+ # change site
128
+ if iSubChunks % nSubChunks == 0 or subChunk == [] or change_site_for_dist_dataset:
129
+ change_site_for_dist_dataset = False
130
+ # append to return map
131
+ if subChunks != []:
132
+ # get site names for parallel execution
133
+ if taskSpec.getNumSitesPerJob() > 1 and not inputChunk.isMerging and inputChunk.useJumbo != "fake":
134
+ siteName = inputChunk.getParallelSites(taskSpec.getNumSitesPerJob(), nSubChunks, [siteName])
135
+ returnList.append(
136
+ {
137
+ "siteName": siteName,
138
+ "subChunks": subChunks,
139
+ "siteCandidate": siteCandidate,
140
+ }
141
+ )
142
+ try:
143
+ gshare = taskSpec.gshare.replace(" ", "_")
144
+ except Exception:
145
+ gshare = None
146
+ tmpLog.info(f"split to nJobs={len(subChunks)} at site={siteName} gshare={gshare}")
147
+ # checkpoint
148
+ inputChunk.checkpoint_file_usage()
149
+ # reset
150
+ subChunks = []
151
+ # skip PQs with chunk size limit
152
+ ngList = copy.copy(tmp_ng_list)
153
+ if not allow_chunk_size_limit:
154
+ for siteName in inputChunk.get_candidate_names():
155
+ siteSpec = siteMapper.getSite(siteName)
156
+ if siteSpec.get_job_chunk_size() is not None:
157
+ ngList.append(siteName)
158
+ # new candidate
159
+ siteCandidate, getCandidateMsg = inputChunk.getOneSiteCandidate(nSubChunks, ngSites=ngList, get_msg=True)
160
+ if siteCandidate is None:
161
+ tmpLog.debug(f"no candidate: {getCandidateMsg}")
162
+ break
163
+ tmp_ng_list = []
164
+ siteName = siteCandidate.siteName
165
+ siteSpec = siteMapper.getSite(siteName)
166
+ # set chunk size
167
+ nSubChunks = siteSpec.get_job_chunk_size()
168
+ if nSubChunks is None:
169
+ nSubChunks = default_nSubChunks
170
+ strict_chunkSize = False
171
+ else:
172
+ strict_chunkSize = True
173
+ # directIO
174
+ if not CoreUtils.use_direct_io_for_job(taskSpec, siteSpec, inputChunk):
175
+ useDirectIO = False
176
+ else:
177
+ useDirectIO = True
178
+ # get maxSize if it is set in taskSpec
179
+ maxSize = maxSizePerJob
180
+ if maxSize is None:
181
+ # use maxwdir as the default maxSize
182
+ if not useDirectIO:
183
+ maxSize = siteCandidate.get_overridden_attribute("maxwdir")
184
+ if maxSize is None:
185
+ maxSize = siteSpec.maxwdir
186
+ if maxSize:
187
+ maxSize *= 1024 * 1024
188
+ elif nEventsPerJob is not None or nFilesPerJob is not None:
189
+ maxSize = None
190
+ else:
191
+ maxSize = siteCandidate.get_overridden_attribute("maxwdir")
192
+ if maxSize is None:
193
+ maxSize = siteSpec.maxwdir
194
+ if inputChunk.useScout():
195
+ maxSize = max(inputChunk.maxInputSizeScouts, maxSize) * 1024 * 1024
196
+ else:
197
+ maxSize = max(inputChunk.maxInputSizeAvalanche, maxSize) * 1024 * 1024
198
+ else:
199
+ # add offset
200
+ maxSize += sizeIntercepts
201
+ # max disk size
202
+ maxDiskSize = siteCandidate.get_overridden_attribute("maxwdir")
203
+ if maxDiskSize is None:
204
+ maxDiskSize = siteSpec.maxwdir
205
+ if maxDiskSize:
206
+ maxDiskSize *= 1024 * 1024
207
+ # max walltime
208
+ maxWalltime = None
209
+ if not inputChunk.isMerging:
210
+ maxWalltime = taskSpec.getMaxWalltime()
211
+ if maxWalltime is None:
212
+ maxWalltime = siteSpec.maxtime
213
+ # core count
214
+ if siteSpec.coreCount:
215
+ coreCount = siteSpec.coreCount
216
+ else:
217
+ coreCount = 1
218
+ # core power
219
+ corePower = siteSpec.corepower
220
+ if taskSpec.dynamicNumEvents() and siteSpec.mintime:
221
+ dynNumEvents = True
222
+ else:
223
+ dynNumEvents = False
224
+ tmpLog.debug(f"chosen {siteName} : {getCandidateMsg} : nQueue={siteCandidate.nQueuedJobs} nRunCap={siteCandidate.nRunningJobsCap}")
225
+ tmpLog.debug(f"new weight {siteCandidate.weight}")
226
+ tmpLog.debug(
227
+ f"maxSize={maxSize} maxWalltime={maxWalltime} coreCount={coreCount} corePower={corePower} maxDisk={maxDiskSize} dynNumEvents={dynNumEvents}"
228
+ )
229
+ tmpLog.debug(f"useDirectIO={useDirectIO} label={taskSpec.prodSourceLabel}")
230
+ # get sub chunk
231
+ subChunk, _ = inputChunk.getSubChunk(
232
+ siteName,
233
+ maxSize=maxSize,
234
+ maxNumFiles=maxNumFiles,
235
+ sizeGradients=sizeGradients,
236
+ sizeIntercepts=sizeIntercepts,
237
+ nFilesPerJob=nFilesPerJob,
238
+ walltimeGradient=walltimeGradient,
239
+ maxWalltime=maxWalltime,
240
+ nEventsPerJob=nEventsPerJob,
241
+ useBoundary=useBoundary,
242
+ sizeGradientsPerInSize=sizeGradientsPerInSize,
243
+ maxOutSize=maxOutSize,
244
+ coreCount=coreCount,
245
+ respectLB=respectLB,
246
+ corePower=corePower,
247
+ dynNumEvents=dynNumEvents,
248
+ multiplicity=multiplicity,
249
+ splitByFields=splitByFields,
250
+ tmpLog=tmpLog,
251
+ useDirectIO=useDirectIO,
252
+ maxDiskSize=maxDiskSize,
253
+ enableLog=True,
254
+ no_split=no_split,
255
+ min_walltime=siteSpec.mintime,
256
+ max_events=taskSpec.get_max_events_per_job(),
257
+ )
258
+ if subChunk is None:
259
+ break
260
+ if subChunk != []:
261
+ # append
262
+ subChunks.append(subChunk)
263
+ # intermediate checkpoint
264
+ inputChunk.checkpoint_file_usage(intermediate=True)
265
+ # check if the last file in master dist dataset is locally available
266
+ for tmp_dataset, tmp_files in subChunk:
267
+ if tmp_dataset.isMaster():
268
+ if tmp_dataset.isDistributed() and not siteCandidate.isAvailableFile(tmp_files[-1]) and siteCandidate.isAvailableFile(tmp_files[0]):
269
+ change_site_for_dist_dataset = True
270
+ tmpLog.debug(
271
+ f"change site since the last file in distributed sub-dataset was unavailable at {siteName} while the first file was available"
272
+ )
273
+ break
274
+ else:
275
+ tmp_ng_list.append(siteName)
276
+ inputChunk.rollback_file_usage(intermediate=True)
277
+ tmpLog.debug("rollback to intermediate file usage")
278
+ iSubChunks += 1
279
+ # append to return map if remain
280
+ isSkipped = False
281
+ if subChunks != []:
282
+ # skip if chunk size is not enough
283
+ if allow_chunk_size_limit and strict_chunkSize and len(subChunks) < nSubChunks:
284
+ tmpLog.debug(f"skip splitting since chunk size {len(subChunks)} is less than chunk size limit {nSubChunks} at {siteName}")
285
+ inputChunk.rollback_file_usage()
286
+ isSkipped = True
287
+ else:
288
+ # get site names for parallel execution
289
+ if taskSpec.getNumSitesPerJob() > 1 and not inputChunk.isMerging:
290
+ siteName = inputChunk.getParallelSites(taskSpec.getNumSitesPerJob(), nSubChunks, [siteName])
291
+ returnList.append(
292
+ {
293
+ "siteName": siteName,
294
+ "subChunks": subChunks,
295
+ "siteCandidate": siteCandidate,
296
+ }
297
+ )
298
+ try:
299
+ gshare = taskSpec.gshare.replace(" ", "_")
300
+ except Exception:
301
+ gshare = None
302
+ tmpLog.info(f"split to nJobs={len(subChunks)} at site={siteName} gshare={gshare}")
303
+ # return
304
+ tmpLog.debug("--- done")
305
+ return self.SC_SUCCEEDED, returnList, isSkipped
306
+
307
+
308
+ Interaction.installSC(JobSplitter)
@@ -0,0 +1,28 @@
1
+ from pandacommon.pandalogger.PandaLogger import PandaLogger
2
+
3
+ from pandajedi.jediconfig import jedi_config
4
+ from pandajedi.jedicore.FactoryBase import FactoryBase
5
+
6
+ logger = PandaLogger().getLogger(__name__.split(".")[-1])
7
+
8
+
9
+ # factory class for throttling
10
+ class JobThrottler(FactoryBase):
11
+ # constructor
12
+ def __init__(self, vo, sourceLabel):
13
+ FactoryBase.__init__(self, vo, sourceLabel, logger, jedi_config.jobthrottle.modConfig)
14
+
15
+ # main
16
+ def toBeThrottled(self, vo, sourceLabel, cloudName, workQueue, resourceType):
17
+ impl = self.getImpl(vo, sourceLabel)
18
+ retVal = impl.toBeThrottled(vo, sourceLabel, cloudName, workQueue, resourceType)
19
+ # retrieve min priority and max number of jobs from concrete class
20
+ self.minPriority = impl.minPriority
21
+ self.maxNumJobs = impl.maxNumJobs
22
+ self.lackOfJobs = impl.underNqLimit
23
+ return retVal
24
+
25
+ # check throttle level
26
+ def mergeThrottled(self, vo, sourceLabel, thrLevel):
27
+ impl = self.getImpl(vo, sourceLabel)
28
+ return impl.mergeThrottled(thrLevel)
@@ -0,0 +1,166 @@
1
+ import datetime
2
+ import os
3
+ import socket
4
+ import sys
5
+ import time
6
+
7
+ from pandacommon.pandalogger.PandaLogger import PandaLogger
8
+ from pandacommon.pandautils.PandaUtils import naive_utcnow
9
+
10
+ from pandajedi.jediconfig import jedi_config
11
+ from pandajedi.jedicore import Interaction
12
+ from pandajedi.jedicore.FactoryBase import FactoryBase
13
+ from pandajedi.jedicore.MsgWrapper import MsgWrapper
14
+ from pandajedi.jedicore.ThreadUtils import ListWithLock, ThreadPool, WorkerThread
15
+
16
+ from .JediKnight import JediKnight
17
+
18
+ logger = PandaLogger().getLogger(__name__.split(".")[-1])
19
+
20
+
21
+ # worker class to do post-processing
22
+ class PostProcessor(JediKnight, FactoryBase):
23
+ # constructor
24
+ def __init__(self, commuChannel, taskBufferIF, ddmIF, vos, prodSourceLabels):
25
+ self.vos = self.parseInit(vos)
26
+ self.prodSourceLabels = self.parseInit(prodSourceLabels)
27
+ self.pid = f"{socket.getfqdn().split('.')[0]}-{os.getpid()}-post"
28
+ JediKnight.__init__(self, commuChannel, taskBufferIF, ddmIF, logger)
29
+ FactoryBase.__init__(self, self.vos, self.prodSourceLabels, logger, jedi_config.postprocessor.modConfig)
30
+
31
+ # main
32
+ def start(self):
33
+ # start base classes
34
+ JediKnight.start(self)
35
+ FactoryBase.initializeMods(self, self.taskBufferIF, self.ddmIF)
36
+ # go into main loop
37
+ while True:
38
+ startTime = naive_utcnow()
39
+ try:
40
+ # get logger
41
+ tmpLog = MsgWrapper(logger)
42
+ tmpLog.info("start")
43
+ # loop over all vos
44
+ for vo in self.vos:
45
+ # loop over all sourceLabels
46
+ for prodSourceLabel in self.prodSourceLabels:
47
+ # prepare tasks to be finished
48
+ tmpLog.info(f"preparing tasks to be finished for vo={vo} label={prodSourceLabel}")
49
+ tmp_ret_list = self.taskBufferIF.prepareTasksToBeFinished_JEDI(vo, prodSourceLabel, jedi_config.postprocessor.nTasks, pid=self.pid)
50
+ if tmp_ret_list is None:
51
+ # failed
52
+ tmpLog.error("failed to prepare tasks")
53
+ # get tasks to be finished
54
+ tmpLog.info("getting tasks to be finished")
55
+ tmpList = self.taskBufferIF.getTasksToBeFinished_JEDI(
56
+ vo, prodSourceLabel, self.pid, jedi_config.postprocessor.nTasks, target_tasks=tmp_ret_list
57
+ )
58
+ if tmpList is None:
59
+ # failed
60
+ tmpLog.error("failed to get tasks to be finished")
61
+ else:
62
+ tmpLog.info(f"got {len(tmpList)} tasks")
63
+ # put to a locked list
64
+ taskList = ListWithLock(tmpList)
65
+ # make thread pool
66
+ threadPool = ThreadPool()
67
+ # make workers
68
+ nWorker = jedi_config.postprocessor.nWorkers
69
+ for iWorker in range(nWorker):
70
+ thr = PostProcessorThread(taskList, threadPool, self.taskBufferIF, self.ddmIF, self)
71
+ thr.start()
72
+ # join
73
+ threadPool.join()
74
+ tmpLog.info("done")
75
+ except Exception:
76
+ errtype, errvalue = sys.exc_info()[:2]
77
+ tmpLog.error(f"failed in {self.__class__.__name__}.start() with {errtype.__name__} {errvalue}")
78
+ # sleep if needed
79
+ loopCycle = 60
80
+ timeDelta = naive_utcnow() - startTime
81
+ sleepPeriod = loopCycle - timeDelta.seconds
82
+ if sleepPeriod > 0:
83
+ time.sleep(sleepPeriod)
84
+
85
+
86
+ # thread for real worker
87
+ class PostProcessorThread(WorkerThread):
88
+ # constructor
89
+ def __init__(self, taskList, threadPool, taskbufferIF, ddmIF, implFactory):
90
+ # initialize woker with no semaphore
91
+ WorkerThread.__init__(self, None, threadPool, logger)
92
+ # attributres
93
+ self.taskList = taskList
94
+ self.taskBufferIF = taskbufferIF
95
+ self.ddmIF = ddmIF
96
+ self.implFactory = implFactory
97
+
98
+ # post process tasks
99
+ def post_process_tasks(self, task_list):
100
+ for taskSpec in task_list:
101
+ # make logger
102
+ tmpLog = MsgWrapper(self.logger, f"<jediTaskID={taskSpec.jediTaskID}>")
103
+ tmpLog.info("start")
104
+ tmpStat = Interaction.SC_SUCCEEDED
105
+ # get impl
106
+ impl = self.implFactory.instantiateImpl(taskSpec.vo, taskSpec.prodSourceLabel, None, self.taskBufferIF, self.ddmIF)
107
+ if impl is None:
108
+ # post processor is undefined
109
+ tmpLog.error(f"post-processor is undefined for vo={taskSpec.vo} sourceLabel={taskSpec.prodSourceLabel}")
110
+ tmpStat = Interaction.SC_FATAL
111
+ # execute
112
+ if tmpStat == Interaction.SC_SUCCEEDED:
113
+ tmpLog.info(f"post-process with {impl.__class__.__name__}")
114
+ try:
115
+ tmpStat = impl.doPostProcess(taskSpec, tmpLog)
116
+ except Exception as e:
117
+ tmpLog.error(f"post-process failed with {str(e)}")
118
+ tmpStat = Interaction.SC_FATAL
119
+ # done
120
+ if tmpStat == Interaction.SC_FATAL or (tmpStat == Interaction.SC_FAILED and taskSpec.status in ["toabort", "tobroken"]):
121
+ # task is broken
122
+ tmpErrStr = "post-process permanently failed"
123
+ tmpLog.error(tmpErrStr)
124
+ taskSpec.status = "broken"
125
+ taskSpec.setErrDiag(tmpErrStr)
126
+ taskSpec.lockedBy = None
127
+ self.taskBufferIF.updateTask_JEDI(taskSpec, {"jediTaskID": taskSpec.jediTaskID})
128
+ elif tmpStat == Interaction.SC_FAILED:
129
+ tmpErrStr = "post-processing temporarily failed"
130
+ taskSpec.setErrDiag(tmpErrStr, True)
131
+ self.taskBufferIF.updateTask_JEDI(taskSpec, {"jediTaskID": taskSpec.jediTaskID})
132
+ tmpLog.info(f"set task_status={taskSpec.status} since {taskSpec.errorDialog}")
133
+ tmpLog.info("done")
134
+ continue
135
+ # final procedure
136
+ try:
137
+ impl.doFinalProcedure(taskSpec, tmpLog)
138
+ except Exception as e:
139
+ tmpLog.error(f"final procedure failed with {str(e)}")
140
+ # done
141
+ tmpLog.info("done")
142
+
143
+ # main
144
+ def runImpl(self):
145
+ while True:
146
+ try:
147
+ # get a part of list
148
+ nTasks = 10
149
+ taskList = self.taskList.get(nTasks)
150
+ # no more datasets
151
+ if len(taskList) == 0:
152
+ self.logger.debug(f"{self.__class__.__name__} terminating since no more items")
153
+ return
154
+ # post process tasks
155
+ self.post_process_tasks(taskList)
156
+ except Exception:
157
+ errtype, errvalue = sys.exc_info()[:2]
158
+ logger.error(f"{self.__class__.__name__} failed in runImpl() with {errtype.__name__}:{errvalue}")
159
+
160
+
161
+ # launch
162
+
163
+
164
+ def launcher(commuChannel, taskBufferIF, ddmIF, vos=None, prodSourceLabels=None):
165
+ p = PostProcessor(commuChannel, taskBufferIF, ddmIF, vos, prodSourceLabels)
166
+ p.start()