wmglobalqueue 2.4.5.1__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.
- Utils/CPMetrics.py +270 -0
- Utils/CertTools.py +100 -0
- Utils/EmailAlert.py +50 -0
- Utils/ExtendedUnitTestCase.py +62 -0
- Utils/FileTools.py +182 -0
- Utils/IteratorTools.py +80 -0
- Utils/MathUtils.py +31 -0
- Utils/MemoryCache.py +119 -0
- Utils/Patterns.py +24 -0
- Utils/Pipeline.py +137 -0
- Utils/PortForward.py +97 -0
- Utils/ProcFS.py +112 -0
- Utils/ProcessStats.py +194 -0
- Utils/PythonVersion.py +17 -0
- Utils/Signals.py +36 -0
- Utils/TemporaryEnvironment.py +27 -0
- Utils/Throttled.py +227 -0
- Utils/Timers.py +130 -0
- Utils/Timestamps.py +86 -0
- Utils/TokenManager.py +143 -0
- Utils/Tracing.py +60 -0
- Utils/TwPrint.py +98 -0
- Utils/Utilities.py +318 -0
- Utils/__init__.py +11 -0
- Utils/wmcoreDTools.py +707 -0
- WMCore/ACDC/Collection.py +57 -0
- WMCore/ACDC/CollectionTypes.py +12 -0
- WMCore/ACDC/CouchCollection.py +67 -0
- WMCore/ACDC/CouchFileset.py +238 -0
- WMCore/ACDC/CouchService.py +73 -0
- WMCore/ACDC/DataCollectionService.py +485 -0
- WMCore/ACDC/Fileset.py +94 -0
- WMCore/ACDC/__init__.py +11 -0
- WMCore/Algorithms/Alarm.py +39 -0
- WMCore/Algorithms/MathAlgos.py +274 -0
- WMCore/Algorithms/MiscAlgos.py +67 -0
- WMCore/Algorithms/ParseXMLFile.py +115 -0
- WMCore/Algorithms/Permissions.py +27 -0
- WMCore/Algorithms/Singleton.py +58 -0
- WMCore/Algorithms/SubprocessAlgos.py +129 -0
- WMCore/Algorithms/__init__.py +7 -0
- WMCore/Cache/GenericDataCache.py +98 -0
- WMCore/Cache/WMConfigCache.py +572 -0
- WMCore/Cache/__init__.py +0 -0
- WMCore/Configuration.py +659 -0
- WMCore/DAOFactory.py +47 -0
- WMCore/DataStructs/File.py +177 -0
- WMCore/DataStructs/Fileset.py +140 -0
- WMCore/DataStructs/Job.py +182 -0
- WMCore/DataStructs/JobGroup.py +142 -0
- WMCore/DataStructs/JobPackage.py +49 -0
- WMCore/DataStructs/LumiList.py +734 -0
- WMCore/DataStructs/Mask.py +219 -0
- WMCore/DataStructs/MathStructs/ContinuousSummaryHistogram.py +197 -0
- WMCore/DataStructs/MathStructs/DiscreteSummaryHistogram.py +92 -0
- WMCore/DataStructs/MathStructs/SummaryHistogram.py +117 -0
- WMCore/DataStructs/MathStructs/__init__.py +0 -0
- WMCore/DataStructs/Pickleable.py +24 -0
- WMCore/DataStructs/Run.py +256 -0
- WMCore/DataStructs/Subscription.py +175 -0
- WMCore/DataStructs/WMObject.py +47 -0
- WMCore/DataStructs/WorkUnit.py +112 -0
- WMCore/DataStructs/Workflow.py +60 -0
- WMCore/DataStructs/__init__.py +8 -0
- WMCore/Database/CMSCouch.py +1430 -0
- WMCore/Database/ConfigDBMap.py +29 -0
- WMCore/Database/CouchMonitoring.py +450 -0
- WMCore/Database/CouchUtils.py +118 -0
- WMCore/Database/DBCore.py +198 -0
- WMCore/Database/DBCreator.py +113 -0
- WMCore/Database/DBExceptionHandler.py +59 -0
- WMCore/Database/DBFactory.py +117 -0
- WMCore/Database/DBFormatter.py +177 -0
- WMCore/Database/Dialects.py +13 -0
- WMCore/Database/ExecuteDAO.py +327 -0
- WMCore/Database/MongoDB.py +241 -0
- WMCore/Database/MySQL/Destroy.py +42 -0
- WMCore/Database/MySQL/ListUserContent.py +20 -0
- WMCore/Database/MySQL/__init__.py +9 -0
- WMCore/Database/MySQLCore.py +132 -0
- WMCore/Database/Oracle/Destroy.py +56 -0
- WMCore/Database/Oracle/ListUserContent.py +19 -0
- WMCore/Database/Oracle/__init__.py +9 -0
- WMCore/Database/ResultSet.py +44 -0
- WMCore/Database/Transaction.py +91 -0
- WMCore/Database/__init__.py +9 -0
- WMCore/Database/ipy_profile_couch.py +438 -0
- WMCore/GlobalWorkQueue/CherryPyThreads/CleanUpTask.py +29 -0
- WMCore/GlobalWorkQueue/CherryPyThreads/HeartbeatMonitor.py +105 -0
- WMCore/GlobalWorkQueue/CherryPyThreads/LocationUpdateTask.py +28 -0
- WMCore/GlobalWorkQueue/CherryPyThreads/ReqMgrInteractionTask.py +35 -0
- WMCore/GlobalWorkQueue/CherryPyThreads/__init__.py +0 -0
- WMCore/GlobalWorkQueue/__init__.py +0 -0
- WMCore/GroupUser/CouchObject.py +127 -0
- WMCore/GroupUser/Decorators.py +51 -0
- WMCore/GroupUser/Group.py +33 -0
- WMCore/GroupUser/Interface.py +73 -0
- WMCore/GroupUser/User.py +96 -0
- WMCore/GroupUser/__init__.py +11 -0
- WMCore/Lexicon.py +836 -0
- WMCore/REST/Auth.py +202 -0
- WMCore/REST/CherryPyPeriodicTask.py +166 -0
- WMCore/REST/Error.py +333 -0
- WMCore/REST/Format.py +642 -0
- WMCore/REST/HeartbeatMonitorBase.py +90 -0
- WMCore/REST/Main.py +636 -0
- WMCore/REST/Server.py +2435 -0
- WMCore/REST/Services.py +24 -0
- WMCore/REST/Test.py +120 -0
- WMCore/REST/Tools.py +38 -0
- WMCore/REST/Validation.py +250 -0
- WMCore/REST/__init__.py +1 -0
- WMCore/ReqMgr/DataStructs/RequestStatus.py +209 -0
- WMCore/ReqMgr/DataStructs/RequestType.py +13 -0
- WMCore/ReqMgr/DataStructs/__init__.py +0 -0
- WMCore/ReqMgr/__init__.py +1 -0
- WMCore/Services/AlertManager/AlertManagerAPI.py +111 -0
- WMCore/Services/AlertManager/__init__.py +0 -0
- WMCore/Services/CRIC/CRIC.py +238 -0
- WMCore/Services/CRIC/__init__.py +0 -0
- WMCore/Services/DBS/DBS3Reader.py +1044 -0
- WMCore/Services/DBS/DBSConcurrency.py +44 -0
- WMCore/Services/DBS/DBSErrors.py +112 -0
- WMCore/Services/DBS/DBSReader.py +23 -0
- WMCore/Services/DBS/DBSUtils.py +166 -0
- WMCore/Services/DBS/DBSWriterObjects.py +381 -0
- WMCore/Services/DBS/ProdException.py +133 -0
- WMCore/Services/DBS/__init__.py +8 -0
- WMCore/Services/FWJRDB/FWJRDBAPI.py +118 -0
- WMCore/Services/FWJRDB/__init__.py +0 -0
- WMCore/Services/HTTPS/HTTPSAuthHandler.py +66 -0
- WMCore/Services/HTTPS/__init__.py +0 -0
- WMCore/Services/LogDB/LogDB.py +201 -0
- WMCore/Services/LogDB/LogDBBackend.py +191 -0
- WMCore/Services/LogDB/LogDBExceptions.py +11 -0
- WMCore/Services/LogDB/LogDBReport.py +85 -0
- WMCore/Services/LogDB/__init__.py +0 -0
- WMCore/Services/MSPileup/__init__.py +0 -0
- WMCore/Services/MSUtils/MSUtils.py +54 -0
- WMCore/Services/MSUtils/__init__.py +0 -0
- WMCore/Services/McM/McM.py +173 -0
- WMCore/Services/McM/__init__.py +8 -0
- WMCore/Services/MonIT/Grafana.py +133 -0
- WMCore/Services/MonIT/__init__.py +0 -0
- WMCore/Services/PyCondor/PyCondorAPI.py +154 -0
- WMCore/Services/PyCondor/__init__.py +0 -0
- WMCore/Services/ReqMgr/ReqMgr.py +261 -0
- WMCore/Services/ReqMgr/__init__.py +0 -0
- WMCore/Services/ReqMgrAux/ReqMgrAux.py +419 -0
- WMCore/Services/ReqMgrAux/__init__.py +0 -0
- WMCore/Services/RequestDB/RequestDBReader.py +267 -0
- WMCore/Services/RequestDB/RequestDBWriter.py +39 -0
- WMCore/Services/RequestDB/__init__.py +0 -0
- WMCore/Services/Requests.py +624 -0
- WMCore/Services/Rucio/Rucio.py +1290 -0
- WMCore/Services/Rucio/RucioUtils.py +74 -0
- WMCore/Services/Rucio/__init__.py +0 -0
- WMCore/Services/RucioConMon/RucioConMon.py +121 -0
- WMCore/Services/RucioConMon/__init__.py +0 -0
- WMCore/Services/Service.py +400 -0
- WMCore/Services/StompAMQ/__init__.py +0 -0
- WMCore/Services/TagCollector/TagCollector.py +155 -0
- WMCore/Services/TagCollector/XMLUtils.py +98 -0
- WMCore/Services/TagCollector/__init__.py +0 -0
- WMCore/Services/UUIDLib.py +13 -0
- WMCore/Services/UserFileCache/UserFileCache.py +160 -0
- WMCore/Services/UserFileCache/__init__.py +8 -0
- WMCore/Services/WMAgent/WMAgent.py +63 -0
- WMCore/Services/WMAgent/__init__.py +0 -0
- WMCore/Services/WMArchive/CMSSWMetrics.py +526 -0
- WMCore/Services/WMArchive/DataMap.py +463 -0
- WMCore/Services/WMArchive/WMArchive.py +33 -0
- WMCore/Services/WMArchive/__init__.py +0 -0
- WMCore/Services/WMBS/WMBS.py +97 -0
- WMCore/Services/WMBS/__init__.py +0 -0
- WMCore/Services/WMStats/DataStruct/RequestInfoCollection.py +300 -0
- WMCore/Services/WMStats/DataStruct/__init__.py +0 -0
- WMCore/Services/WMStats/WMStatsPycurl.py +145 -0
- WMCore/Services/WMStats/WMStatsReader.py +445 -0
- WMCore/Services/WMStats/WMStatsWriter.py +273 -0
- WMCore/Services/WMStats/__init__.py +0 -0
- WMCore/Services/WMStatsServer/WMStatsServer.py +134 -0
- WMCore/Services/WMStatsServer/__init__.py +0 -0
- WMCore/Services/WorkQueue/WorkQueue.py +492 -0
- WMCore/Services/WorkQueue/__init__.py +0 -0
- WMCore/Services/__init__.py +8 -0
- WMCore/Services/pycurl_manager.py +574 -0
- WMCore/WMBase.py +50 -0
- WMCore/WMConnectionBase.py +164 -0
- WMCore/WMException.py +183 -0
- WMCore/WMExceptions.py +269 -0
- WMCore/WMFactory.py +76 -0
- WMCore/WMInit.py +377 -0
- WMCore/WMLogging.py +104 -0
- WMCore/WMSpec/ConfigSectionTree.py +442 -0
- WMCore/WMSpec/Persistency.py +135 -0
- WMCore/WMSpec/Steps/BuildMaster.py +87 -0
- WMCore/WMSpec/Steps/BuildTools.py +201 -0
- WMCore/WMSpec/Steps/Builder.py +97 -0
- WMCore/WMSpec/Steps/Diagnostic.py +89 -0
- WMCore/WMSpec/Steps/Emulator.py +62 -0
- WMCore/WMSpec/Steps/ExecuteMaster.py +208 -0
- WMCore/WMSpec/Steps/Executor.py +210 -0
- WMCore/WMSpec/Steps/StepFactory.py +213 -0
- WMCore/WMSpec/Steps/TaskEmulator.py +75 -0
- WMCore/WMSpec/Steps/Template.py +204 -0
- WMCore/WMSpec/Steps/Templates/AlcaHarvest.py +76 -0
- WMCore/WMSpec/Steps/Templates/CMSSW.py +613 -0
- WMCore/WMSpec/Steps/Templates/DQMUpload.py +59 -0
- WMCore/WMSpec/Steps/Templates/DeleteFiles.py +70 -0
- WMCore/WMSpec/Steps/Templates/LogArchive.py +84 -0
- WMCore/WMSpec/Steps/Templates/LogCollect.py +105 -0
- WMCore/WMSpec/Steps/Templates/StageOut.py +105 -0
- WMCore/WMSpec/Steps/Templates/__init__.py +10 -0
- WMCore/WMSpec/Steps/WMExecutionFailure.py +21 -0
- WMCore/WMSpec/Steps/__init__.py +8 -0
- WMCore/WMSpec/Utilities.py +63 -0
- WMCore/WMSpec/WMSpecErrors.py +12 -0
- WMCore/WMSpec/WMStep.py +347 -0
- WMCore/WMSpec/WMTask.py +1997 -0
- WMCore/WMSpec/WMWorkload.py +2288 -0
- WMCore/WMSpec/WMWorkloadTools.py +382 -0
- WMCore/WMSpec/__init__.py +9 -0
- WMCore/WorkQueue/DataLocationMapper.py +273 -0
- WMCore/WorkQueue/DataStructs/ACDCBlock.py +47 -0
- WMCore/WorkQueue/DataStructs/Block.py +48 -0
- WMCore/WorkQueue/DataStructs/CouchWorkQueueElement.py +148 -0
- WMCore/WorkQueue/DataStructs/WorkQueueElement.py +274 -0
- WMCore/WorkQueue/DataStructs/WorkQueueElementResult.py +152 -0
- WMCore/WorkQueue/DataStructs/WorkQueueElementsSummary.py +185 -0
- WMCore/WorkQueue/DataStructs/__init__.py +0 -0
- WMCore/WorkQueue/Policy/End/EndPolicyInterface.py +44 -0
- WMCore/WorkQueue/Policy/End/SingleShot.py +22 -0
- WMCore/WorkQueue/Policy/End/__init__.py +32 -0
- WMCore/WorkQueue/Policy/PolicyInterface.py +17 -0
- WMCore/WorkQueue/Policy/Start/Block.py +258 -0
- WMCore/WorkQueue/Policy/Start/Dataset.py +180 -0
- WMCore/WorkQueue/Policy/Start/MonteCarlo.py +131 -0
- WMCore/WorkQueue/Policy/Start/ResubmitBlock.py +171 -0
- WMCore/WorkQueue/Policy/Start/StartPolicyInterface.py +316 -0
- WMCore/WorkQueue/Policy/Start/__init__.py +34 -0
- WMCore/WorkQueue/Policy/__init__.py +57 -0
- WMCore/WorkQueue/WMBSHelper.py +772 -0
- WMCore/WorkQueue/WorkQueue.py +1237 -0
- WMCore/WorkQueue/WorkQueueBackend.py +750 -0
- WMCore/WorkQueue/WorkQueueBase.py +39 -0
- WMCore/WorkQueue/WorkQueueExceptions.py +44 -0
- WMCore/WorkQueue/WorkQueueReqMgrInterface.py +278 -0
- WMCore/WorkQueue/WorkQueueUtils.py +130 -0
- WMCore/WorkQueue/__init__.py +13 -0
- WMCore/Wrappers/JsonWrapper/JSONThunker.py +342 -0
- WMCore/Wrappers/JsonWrapper/__init__.py +7 -0
- WMCore/Wrappers/__init__.py +6 -0
- WMCore/__init__.py +10 -0
- wmglobalqueue-2.4.5.1.data/data/bin/wmc-dist-patch +15 -0
- wmglobalqueue-2.4.5.1.data/data/bin/wmc-dist-unpatch +8 -0
- wmglobalqueue-2.4.5.1.data/data/bin/wmc-httpd +3 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/.couchapprc +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/README.md +40 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/index.html +264 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/ElementInfoByWorkflow.js +96 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/StuckElementInfo.js +57 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/WorkloadInfoTable.js +80 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/dataTable.js +70 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/namespace.js +23 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/style/main.css +75 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/couchapp.json +4 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/filters/childQueueFilter.js +13 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/filters/filterDeletedDocs.js +3 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/filters/queueFilter.js +11 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/language +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lib/mustache.js +333 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lib/validate.js +27 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lib/workqueue_utils.js +61 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/elementsDetail.js +28 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/filter.js +86 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/stuckElements.js +38 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/workRestrictions.js +153 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/workflowSummary.js +28 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/rewrites.json +73 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/shows/redirect.js +23 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/shows/status.js +40 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/ElementSummaryByWorkflow.html +27 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/StuckElementSummary.html +26 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/TaskStatus.html +23 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/WorkflowSummary.html +27 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/partials/workqueue-common-lib.html +2 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/partials/yui-lib-remote.html +16 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/partials/yui-lib.html +18 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/updates/in-place.js +50 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/validate_doc_update.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/vendor/couchapp/_attachments/jquery.couch.app.js +235 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/vendor/couchapp/_attachments/jquery.pathbinder.js +173 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activeData/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activeData/reduce.js +2 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activeParentData/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activeParentData/reduce.js +2 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activePileupData/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activePileupData/reduce.js +2 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/analyticsData/map.js +11 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/analyticsData/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/availableByPriority/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/conflicts/map.js +5 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elements/map.js +5 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByData/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByParent/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByParentData/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByPileupData/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByStatus/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsBySubscription/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByWorkflow/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByWorkflow/reduce.js +3 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsDetailByWorkflowAndStatus/map.js +26 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobInjectStatusByRequest/map.js +10 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobInjectStatusByRequest/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobStatusByRequest/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobStatusByRequest/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndPriority/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndPriority/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndStatus/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndStatus/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByRequest/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByRequest/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByStatus/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByStatus/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByStatusAndPriority/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByStatusAndPriority/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/openRequests/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/recent-items/map.js +5 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/siteWhitelistByRequest/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/siteWhitelistByRequest/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/specsByWorkflow/map.js +5 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/stuckElements/map.js +38 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsInjectStatusByRequest/map.js +12 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsInjectStatusByRequest/reduce.js +3 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsUrl/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsUrl/reduce.js +2 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsUrlByRequest/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsUrlByRequest/reduce.js +2 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/workflowSummary/map.js +9 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/workflowSummary/reduce.js +10 -0
- wmglobalqueue-2.4.5.1.dist-info/METADATA +26 -0
- wmglobalqueue-2.4.5.1.dist-info/RECORD +347 -0
- wmglobalqueue-2.4.5.1.dist-info/WHEEL +5 -0
- wmglobalqueue-2.4.5.1.dist-info/licenses/LICENSE +202 -0
- wmglobalqueue-2.4.5.1.dist-info/licenses/NOTICE +16 -0
- wmglobalqueue-2.4.5.1.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
WorkQueue splitting by dataset, it creates one single
|
|
4
|
+
workqueue element per dataset.
|
|
5
|
+
|
|
6
|
+
This policy is specifically used by DQMHarvest workflows, which requires
|
|
7
|
+
some special handling based on run information. Nonetheless, trying to
|
|
8
|
+
make it generic enough that could be used by other spec types.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import logging
|
|
12
|
+
from math import ceil
|
|
13
|
+
from WMCore import Lexicon
|
|
14
|
+
from WMCore.WorkQueue.Policy.Start.StartPolicyInterface import StartPolicyInterface
|
|
15
|
+
from WMCore.WorkQueue.WorkQueueExceptions import WorkQueueWMSpecError
|
|
16
|
+
from WMCore.WorkQueue.WorkQueueUtils import makeLocationsList
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Dataset(StartPolicyInterface):
|
|
20
|
+
"""Split elements into datasets"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, **args):
|
|
23
|
+
StartPolicyInterface.__init__(self, **args)
|
|
24
|
+
self.args.setdefault('SliceType', 'NumberOfRuns')
|
|
25
|
+
self.args.setdefault('SliceSize', 1)
|
|
26
|
+
self.lumiType = "NumberOfLumis"
|
|
27
|
+
self.sites = []
|
|
28
|
+
|
|
29
|
+
def split(self):
|
|
30
|
+
"""Apply policy to spec"""
|
|
31
|
+
work = set() if self.args['SliceType'] == 'NumberOfRuns' else 0
|
|
32
|
+
numFiles = 0
|
|
33
|
+
numEvents = 0
|
|
34
|
+
numLumis = 0
|
|
35
|
+
datasetPath = self.initialTask.getInputDatasetPath()
|
|
36
|
+
|
|
37
|
+
# dataset splitting can't have its data selection overridden
|
|
38
|
+
if self.data and list(self.data) != [datasetPath]:
|
|
39
|
+
raise RuntimeError("Can't provide different data to split with")
|
|
40
|
+
|
|
41
|
+
blocks = self.validBlocks(self.initialTask, self.dbs())
|
|
42
|
+
if not blocks:
|
|
43
|
+
return
|
|
44
|
+
|
|
45
|
+
for block in blocks:
|
|
46
|
+
if self.args['SliceType'] == 'NumberOfRuns':
|
|
47
|
+
work = work.union(block[self.args['SliceType']])
|
|
48
|
+
else:
|
|
49
|
+
work += float(block[self.args['SliceType']])
|
|
50
|
+
numLumis += int(block[self.lumiType])
|
|
51
|
+
numFiles += int(block['NumberOfFiles'])
|
|
52
|
+
numEvents += int(block['NumberOfEvents'])
|
|
53
|
+
|
|
54
|
+
if self.args['SliceType'] == 'NumberOfRuns':
|
|
55
|
+
numJobs = ceil(len(work) / float(self.args['SliceSize']))
|
|
56
|
+
else:
|
|
57
|
+
numJobs = ceil(float(work) / float(self.args['SliceSize']))
|
|
58
|
+
|
|
59
|
+
# parentage
|
|
60
|
+
parentFlag = True if self.initialTask.parentProcessingFlag() else False
|
|
61
|
+
|
|
62
|
+
self.newQueueElement(Inputs={datasetPath: self.data.get(datasetPath, [])},
|
|
63
|
+
ParentFlag=parentFlag,
|
|
64
|
+
NumberOfLumis=numLumis,
|
|
65
|
+
NumberOfFiles=numFiles,
|
|
66
|
+
NumberOfEvents=numEvents,
|
|
67
|
+
Jobs=numJobs,
|
|
68
|
+
NoInputUpdate=self.initialTask.getTrustSitelists().get('trustlists'),
|
|
69
|
+
NoPileupUpdate=self.initialTask.getTrustSitelists().get('trustPUlists')
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def validate(self):
|
|
73
|
+
"""Check args and spec work with block splitting"""
|
|
74
|
+
StartPolicyInterface.validateCommon(self)
|
|
75
|
+
if not self.initialTask.inputDataset():
|
|
76
|
+
raise WorkQueueWMSpecError(self.wmspec, 'No input dataset')
|
|
77
|
+
|
|
78
|
+
def validBlocks(self, task, dbs):
|
|
79
|
+
"""Return blocks that pass the input data restriction"""
|
|
80
|
+
datasetPath = task.getInputDatasetPath()
|
|
81
|
+
Lexicon.dataset(datasetPath) # check dataset name
|
|
82
|
+
validBlocks = []
|
|
83
|
+
|
|
84
|
+
blockWhiteList = task.inputBlockWhitelist()
|
|
85
|
+
blockBlackList = task.inputBlockBlacklist()
|
|
86
|
+
runWhiteList = task.inputRunWhitelist()
|
|
87
|
+
runBlackList = task.inputRunBlacklist()
|
|
88
|
+
lumiMask = task.getLumiMask()
|
|
89
|
+
if lumiMask:
|
|
90
|
+
maskedBlocks = self.getMaskedBlocks(task, dbs, datasetPath)
|
|
91
|
+
|
|
92
|
+
for blockName in dbs.listFileBlocks(datasetPath):
|
|
93
|
+
# check block restrictions
|
|
94
|
+
if blockWhiteList and blockName not in blockWhiteList:
|
|
95
|
+
continue
|
|
96
|
+
if blockName in blockBlackList:
|
|
97
|
+
continue
|
|
98
|
+
|
|
99
|
+
blockSummary = dbs.getDBSSummaryInfo(block=blockName)
|
|
100
|
+
if int(blockSummary.get('NumberOfFiles', 0)) == 0:
|
|
101
|
+
logging.warning("Block %s being rejected for lack of valid files to process", blockName)
|
|
102
|
+
self.badWork.append(blockName)
|
|
103
|
+
continue
|
|
104
|
+
|
|
105
|
+
if self.args['SliceType'] == 'NumberOfRuns':
|
|
106
|
+
blockSummary['NumberOfRuns'] = dbs.listRuns(block=blockName)
|
|
107
|
+
|
|
108
|
+
# check lumi restrictions
|
|
109
|
+
if lumiMask:
|
|
110
|
+
if blockName not in maskedBlocks:
|
|
111
|
+
logging.warning("Block %s doesn't pass the lumi mask constraints", blockName)
|
|
112
|
+
self.rejectedWork.append(blockName)
|
|
113
|
+
continue
|
|
114
|
+
|
|
115
|
+
acceptedLumiCount = sum([len(maskedBlocks[blockName][lfn].getLumis()) for lfn in maskedBlocks[blockName]])
|
|
116
|
+
ratioAccepted = 1. * acceptedLumiCount / float(blockSummary['NumberOfLumis'])
|
|
117
|
+
maskedRuns = [maskedBlocks[blockName][lfn].getRuns() for lfn in maskedBlocks[blockName]]
|
|
118
|
+
acceptedRuns = set(lumiMask.getRuns()).intersection(set().union(*maskedRuns))
|
|
119
|
+
|
|
120
|
+
blockSummary['NumberOfFiles'] = len(maskedBlocks[blockName])
|
|
121
|
+
blockSummary['NumberOfEvents'] = float(blockSummary['NumberOfEvents']) * ratioAccepted
|
|
122
|
+
blockSummary[self.lumiType] = acceptedLumiCount
|
|
123
|
+
blockSummary['NumberOfRuns'] = acceptedRuns
|
|
124
|
+
# check run restrictions
|
|
125
|
+
elif runWhiteList or runBlackList:
|
|
126
|
+
runs = set(dbs.listRuns(block=blockName))
|
|
127
|
+
# multi run blocks need special account, requires more DBS calls
|
|
128
|
+
recalculateLumiCounts = True if len(runs) > 1 else False
|
|
129
|
+
|
|
130
|
+
# apply blacklist and whitelist
|
|
131
|
+
runs = runs.difference(runBlackList)
|
|
132
|
+
if runWhiteList:
|
|
133
|
+
runs = runs.intersection(runWhiteList)
|
|
134
|
+
# any runs left are ones we will run on, if none ignore block
|
|
135
|
+
if not runs:
|
|
136
|
+
logging.warning("Block %s doesn't pass the runs constraints", blockName)
|
|
137
|
+
self.rejectedWork.append(blockName)
|
|
138
|
+
continue
|
|
139
|
+
|
|
140
|
+
if recalculateLumiCounts:
|
|
141
|
+
# Recalculate the number of files, lumis and ~events accepted
|
|
142
|
+
acceptedLumiCount = 0
|
|
143
|
+
acceptedEventCount = 0
|
|
144
|
+
acceptedFileCount = 0
|
|
145
|
+
fileInfo = dbs.listFilesInBlock(fileBlockName=blockName)
|
|
146
|
+
|
|
147
|
+
for fileEntry in fileInfo:
|
|
148
|
+
acceptedFile = False
|
|
149
|
+
for lumiInfo in fileEntry['LumiList']:
|
|
150
|
+
if lumiInfo['RunNumber'] in runs:
|
|
151
|
+
acceptedFile = True
|
|
152
|
+
acceptedLumiCount += len(lumiInfo['LumiSectionNumber'])
|
|
153
|
+
if acceptedFile:
|
|
154
|
+
acceptedFileCount += 1
|
|
155
|
+
acceptedEventCount += fileEntry['NumberOfEvents']
|
|
156
|
+
|
|
157
|
+
else:
|
|
158
|
+
acceptedLumiCount = blockSummary["NumberOfLumis"]
|
|
159
|
+
acceptedFileCount = blockSummary['NumberOfFiles']
|
|
160
|
+
acceptedEventCount = blockSummary['NumberOfEvents']
|
|
161
|
+
|
|
162
|
+
blockSummary[self.lumiType] = acceptedLumiCount
|
|
163
|
+
blockSummary['NumberOfFiles'] = acceptedFileCount
|
|
164
|
+
blockSummary['NumberOfEvents'] = acceptedEventCount
|
|
165
|
+
blockSummary['NumberOfRuns'] = runs
|
|
166
|
+
|
|
167
|
+
validBlocks.append(blockSummary)
|
|
168
|
+
|
|
169
|
+
# all needed blocks present at these sites
|
|
170
|
+
if task.getTrustSitelists().get('trustlists'):
|
|
171
|
+
siteWhitelist = task.siteWhitelist()
|
|
172
|
+
siteBlacklist = task.siteBlacklist()
|
|
173
|
+
self.sites = makeLocationsList(siteWhitelist, siteBlacklist)
|
|
174
|
+
self.data[datasetPath] = self.sites
|
|
175
|
+
else:
|
|
176
|
+
# as the container is dealt as a whole, resolve the container location
|
|
177
|
+
locations = set(self.blockLocationRucioPhedex(datasetPath))
|
|
178
|
+
self.data[datasetPath] = list(set(self.cric.PNNstoPSNs(locations)))
|
|
179
|
+
|
|
180
|
+
return validBlocks
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
WorkQueue splitting by block
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import division
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
from WMCore.WorkQueue.Policy.Start.StartPolicyInterface import StartPolicyInterface
|
|
10
|
+
from WMCore.WorkQueue.WorkQueueExceptions import WorkQueueWMSpecError, WorkQueueNoWorkError
|
|
11
|
+
from WMCore.DataStructs.Mask import Mask
|
|
12
|
+
from copy import copy
|
|
13
|
+
from math import ceil, floor
|
|
14
|
+
|
|
15
|
+
__all__ = []
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class MonteCarlo(StartPolicyInterface):
|
|
19
|
+
"""Split elements into blocks"""
|
|
20
|
+
def __init__(self, **args):
|
|
21
|
+
StartPolicyInterface.__init__(self, **args)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def split(self):
|
|
25
|
+
"""Apply policy to spec"""
|
|
26
|
+
# if not specified take standard defaults
|
|
27
|
+
self.args.setdefault('SliceType', 'NumberOfEvents')
|
|
28
|
+
self.args.setdefault('SliceSize', 1000) # events per job
|
|
29
|
+
self.args.setdefault('SubSliceType', 'NumberOfEventsPerLumi')
|
|
30
|
+
self.args.setdefault('SubSliceSize', self.args['SliceSize']) # events per lumi
|
|
31
|
+
self.args.setdefault('MaxJobsPerElement', 1000) # jobs per WQE
|
|
32
|
+
self.args.setdefault('MaxLumisPerElement', os.environ.get('MAX_LUMIS_PER_WQE'))
|
|
33
|
+
self.args.setdefault('blowupFactor', 1.0) # Estimate of additional jobs following tasks.
|
|
34
|
+
# Total WQE tasks will be Jobs*(1+blowupFactor)
|
|
35
|
+
noInputUpdate = self.initialTask.getTrustSitelists().get('trustlists')
|
|
36
|
+
noPileupUpdate = self.initialTask.getTrustSitelists().get('trustPUlists')
|
|
37
|
+
|
|
38
|
+
if not self.mask:
|
|
39
|
+
self.mask = Mask(FirstRun=1,
|
|
40
|
+
FirstLumi=self.initialTask.getFirstLumi(),
|
|
41
|
+
FirstEvent=self.initialTask.getFirstEvent(),
|
|
42
|
+
LastRun=1,
|
|
43
|
+
LastEvent=self.initialTask.getFirstEvent() +
|
|
44
|
+
self.initialTask.totalEvents() - 1)
|
|
45
|
+
mask = Mask(**self.mask)
|
|
46
|
+
|
|
47
|
+
# First let's initialize some parameters
|
|
48
|
+
lumis_per_job = ceil(self.args['SliceSize'] / self.args['SubSliceSize'])
|
|
49
|
+
totalLumisPerElement = int(self.args['MaxJobsPerElement']) * lumis_per_job
|
|
50
|
+
|
|
51
|
+
if self.args['MaxLumisPerElement'] and totalLumisPerElement > int(self.args['MaxLumisPerElement']):
|
|
52
|
+
# If there are too many lumis in the WQ element. reduce the number of jobs per element
|
|
53
|
+
self.args['MaxJobsPerElement'] = floor(int(self.args['MaxLumisPerElement']) / lumis_per_job)
|
|
54
|
+
if self.args['MaxJobsPerElement'] == 0:
|
|
55
|
+
raise WorkQueueWMSpecError(self.wmspec, """Too many lumis (%s) in a job:
|
|
56
|
+
Change 'SliceSize' / 'SubSliceSize'""" % lumis_per_job)
|
|
57
|
+
|
|
58
|
+
stepSize = int(self.args['SliceSize']) * int(self.args['MaxJobsPerElement'])
|
|
59
|
+
total = mask['LastEvent'] - mask['FirstEvent'] + 1
|
|
60
|
+
lastAllowedEvent = mask['LastEvent']
|
|
61
|
+
eventsAccounted = 0
|
|
62
|
+
|
|
63
|
+
while eventsAccounted < total:
|
|
64
|
+
current = mask['FirstEvent'] + stepSize - 1 # inclusive range
|
|
65
|
+
if current > lastAllowedEvent:
|
|
66
|
+
current = lastAllowedEvent
|
|
67
|
+
mask['LastEvent'] = current
|
|
68
|
+
|
|
69
|
+
# Calculate the job splitting without actually doing it
|
|
70
|
+
# number of lumis is calculated by events number and SubSliceSize which is events per lumi
|
|
71
|
+
# So if there no exact division between events per job and events per lumi
|
|
72
|
+
# it takes the ceiling of the value.
|
|
73
|
+
# Therefore total lumis can't be calculated from total events / SubSliceSize
|
|
74
|
+
# It has to be caluated by adding the lumis_per_job * number of jobs
|
|
75
|
+
nEvents = mask['LastEvent'] - mask['FirstEvent'] + 1
|
|
76
|
+
nLumis = floor(nEvents / self.args['SliceSize']) * lumis_per_job
|
|
77
|
+
remainingLumis = ceil(nEvents % self.args['SliceSize'] / self.args['SubSliceSize'])
|
|
78
|
+
nLumis += remainingLumis
|
|
79
|
+
jobs = ceil(nEvents / self.args['SliceSize'])
|
|
80
|
+
|
|
81
|
+
mask['LastLumi'] = mask['FirstLumi'] + int(nLumis) - 1 # inclusive range
|
|
82
|
+
self.newQueueElement(WMSpec=self.wmspec,
|
|
83
|
+
NumberOfLumis=nLumis,
|
|
84
|
+
NumberOfEvents=nEvents,
|
|
85
|
+
Jobs=jobs,
|
|
86
|
+
Mask=copy(mask),
|
|
87
|
+
NoInputUpdate=noInputUpdate,
|
|
88
|
+
NoPileupUpdate=noPileupUpdate,
|
|
89
|
+
blowupFactor=self.args['blowupFactor'])
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
if mask['LastEvent'] > (2 ** 32 - 1):
|
|
93
|
+
# This is getting tricky, to ensure consecutive
|
|
94
|
+
# events numbers we must calculate where the jobSplitter
|
|
95
|
+
# will restart the firstEvent to 1 for the last time
|
|
96
|
+
# in the newly created unit
|
|
97
|
+
internalEvents = mask['FirstEvent']
|
|
98
|
+
accumulatedEvents = internalEvents
|
|
99
|
+
breakPoint = internalEvents
|
|
100
|
+
|
|
101
|
+
while accumulatedEvents < mask['LastEvent']:
|
|
102
|
+
if (internalEvents + self.args['SliceSize'] - 1) > (2 ** 32 - 1):
|
|
103
|
+
internalEvents = 1
|
|
104
|
+
breakPoint = accumulatedEvents
|
|
105
|
+
else:
|
|
106
|
+
internalEvents += self.args['SliceSize']
|
|
107
|
+
accumulatedEvents += self.args['SliceSize']
|
|
108
|
+
|
|
109
|
+
leftoverEvents = mask['LastEvent'] - breakPoint + 1
|
|
110
|
+
mask['FirstEvent'] = leftoverEvents + 1
|
|
111
|
+
|
|
112
|
+
else:
|
|
113
|
+
mask['FirstEvent'] = mask['LastEvent'] + 1
|
|
114
|
+
|
|
115
|
+
mask['FirstLumi'] = mask['LastLumi'] + 1
|
|
116
|
+
eventsAccounted += stepSize
|
|
117
|
+
lastAllowedEvent = (total - eventsAccounted) + mask['FirstEvent'] - 1
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def validate(self):
|
|
121
|
+
"""Check args and spec work with block splitting"""
|
|
122
|
+
StartPolicyInterface.validateCommon(self)
|
|
123
|
+
|
|
124
|
+
if self.initialTask.totalEvents() < 1:
|
|
125
|
+
raise WorkQueueNoWorkError(self.wmspec, 'Invalid total events selection: %s' % str(self.initialTask.totalEvents()))
|
|
126
|
+
|
|
127
|
+
if self.mask and self.mask['LastEvent'] < self.mask['FirstEvent']:
|
|
128
|
+
raise WorkQueueWMSpecError(self.wmspec, "Invalid start & end events")
|
|
129
|
+
|
|
130
|
+
if self.mask and self.mask['LastLumi'] < self.mask['FirstLumi']:
|
|
131
|
+
raise WorkQueueWMSpecError(self.wmspec, "Invalid start & end lumis")
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
WorkQueue splitting for Resubmission workflows
|
|
4
|
+
|
|
5
|
+
In this case we can't be agnostic of the specific splitting algorithm
|
|
6
|
+
for the top level task. Each algorithm may require a different way of generating
|
|
7
|
+
ACDC blocks.
|
|
8
|
+
|
|
9
|
+
Current implementations:
|
|
10
|
+
|
|
11
|
+
- SingleChunk: Harvest, ParentlessMergeBySize, MinFileBased, EventAwareLumiBased, LumiBased
|
|
12
|
+
- FixedSizeChunks: FileBased, FixedDelay, MergeBySize, RunBased, SizeBased, SplitFileBased, TwoFileAndEventBased, TwoFileBased
|
|
13
|
+
|
|
14
|
+
ACDC unsupported:
|
|
15
|
+
|
|
16
|
+
- WMBSMergeBySize
|
|
17
|
+
- SiblingProcessingBased
|
|
18
|
+
|
|
19
|
+
"""
|
|
20
|
+
import json
|
|
21
|
+
from math import ceil
|
|
22
|
+
from WMCore.WorkQueue.Policy.Start.StartPolicyInterface import StartPolicyInterface
|
|
23
|
+
from WMCore.WorkQueue.WorkQueueExceptions import WorkQueueWMSpecError
|
|
24
|
+
from WMCore.WorkQueue.WorkQueueUtils import makeLocationsList
|
|
25
|
+
from WMCore.WorkQueue.DataStructs.ACDCBlock import ACDCBlock
|
|
26
|
+
from WMCore.ACDC.DataCollectionService import DataCollectionService
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ResubmitBlock(StartPolicyInterface):
|
|
30
|
+
"""Split elements into blocks"""
|
|
31
|
+
|
|
32
|
+
def __init__(self, **args):
|
|
33
|
+
StartPolicyInterface.__init__(self, **args)
|
|
34
|
+
self.args.setdefault('SliceType', 'NumberOfFiles')
|
|
35
|
+
self.args.setdefault('SliceSize', 1)
|
|
36
|
+
self.args.setdefault('SplittingAlgo', 'LumiBased')
|
|
37
|
+
self.lumiType = "NumberOfLumis"
|
|
38
|
+
|
|
39
|
+
# Define how to handle the different splitting algorithms
|
|
40
|
+
self.algoMapping = {'Harvest': self.singleChunk,
|
|
41
|
+
'ParentlessMergeBySize': self.singleChunk,
|
|
42
|
+
'MinFileBased': self.singleChunk,
|
|
43
|
+
'LumiBased': self.singleChunk,
|
|
44
|
+
'EventAwareLumiBased': self.singleChunk,
|
|
45
|
+
'EventBased': self.singleChunk}
|
|
46
|
+
self.unsupportedAlgos = ['WMBSMergeBySize', 'SiblingProcessingBased']
|
|
47
|
+
self.defaultAlgo = self.fixedSizeChunk
|
|
48
|
+
self.sites = []
|
|
49
|
+
|
|
50
|
+
def split(self):
|
|
51
|
+
"""Apply policy to spec"""
|
|
52
|
+
# Prepare a site list in case we need it
|
|
53
|
+
siteWhitelist = self.initialTask.siteWhitelist()
|
|
54
|
+
siteBlacklist = self.initialTask.siteBlacklist()
|
|
55
|
+
self.sites = makeLocationsList(siteWhitelist, siteBlacklist)
|
|
56
|
+
|
|
57
|
+
for block in self.validBlocks(self.initialTask):
|
|
58
|
+
parentList = {}
|
|
59
|
+
parentFlag = False
|
|
60
|
+
if self.initialTask.parentProcessingFlag():
|
|
61
|
+
parentFlag = True
|
|
62
|
+
parentList[block["Name"]] = block['Sites']
|
|
63
|
+
|
|
64
|
+
self.newQueueElement(Inputs={block['Name']: block['Sites']},
|
|
65
|
+
ParentFlag=parentFlag,
|
|
66
|
+
ParentData=parentList,
|
|
67
|
+
NumberOfLumis=block[self.lumiType],
|
|
68
|
+
NumberOfFiles=block['NumberOfFiles'],
|
|
69
|
+
NumberOfEvents=block['NumberOfEvents'],
|
|
70
|
+
Jobs=ceil(float(block[self.args['SliceType']]) /
|
|
71
|
+
float(self.args['SliceSize'])),
|
|
72
|
+
ACDC=block['ACDC'],
|
|
73
|
+
NoInputUpdate=self.initialTask.getTrustSitelists().get('trustlists'),
|
|
74
|
+
NoPileupUpdate=self.initialTask.getTrustSitelists().get('trustPUlists')
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
def validate(self):
|
|
78
|
+
"""Check args and spec work with block splitting"""
|
|
79
|
+
StartPolicyInterface.validateCommon(self)
|
|
80
|
+
|
|
81
|
+
def validBlocks(self, task):
|
|
82
|
+
"""Return blocks that pass the input data restriction according
|
|
83
|
+
to the splitting algorithm"""
|
|
84
|
+
validBlocks = []
|
|
85
|
+
|
|
86
|
+
acdcInfo = task.getInputACDC()
|
|
87
|
+
if not acdcInfo:
|
|
88
|
+
raise WorkQueueWMSpecError(self.wmspec, 'No acdc section for %s' % task.getPathName())
|
|
89
|
+
acdc = DataCollectionService(acdcInfo["server"], acdcInfo["database"])
|
|
90
|
+
|
|
91
|
+
self.logger.info("Policy self.data variable content: %s", self.data)
|
|
92
|
+
if self.data:
|
|
93
|
+
acdcBlockSplit = ACDCBlock.splitBlockName(next(iter(self.data)))
|
|
94
|
+
else:
|
|
95
|
+
# if self.data is not passed, assume the data is input dataset from the spec
|
|
96
|
+
acdcBlockSplit = False
|
|
97
|
+
|
|
98
|
+
self.logger.info("Using ACDC blockSplit:\n%s", json.dumps(acdcBlockSplit, indent=2))
|
|
99
|
+
if acdcBlockSplit:
|
|
100
|
+
block = acdc.getChunkInfo(acdcInfo['collection'],
|
|
101
|
+
acdcBlockSplit['TaskName'],
|
|
102
|
+
acdcBlockSplit['Offset'],
|
|
103
|
+
acdcBlockSplit['NumOfFiles'])
|
|
104
|
+
dbsBlock = {}
|
|
105
|
+
dbsBlock['Name'] = next(iter(self.data))
|
|
106
|
+
|
|
107
|
+
dbsBlock['NumberOfFiles'] = block['files']
|
|
108
|
+
dbsBlock['NumberOfEvents'] = block['events']
|
|
109
|
+
dbsBlock['NumberOfLumis'] = block['lumis']
|
|
110
|
+
dbsBlock['ACDC'] = acdcInfo
|
|
111
|
+
if task.getTrustSitelists().get('trustlists'):
|
|
112
|
+
dbsBlock["Sites"] = self.sites
|
|
113
|
+
else:
|
|
114
|
+
dbsBlock["Sites"] = self.cric.PNNstoPSNs(block["locations"])
|
|
115
|
+
validBlocks.append(dbsBlock)
|
|
116
|
+
else:
|
|
117
|
+
if self.args['SplittingAlgo'] in self.unsupportedAlgos:
|
|
118
|
+
raise WorkQueueWMSpecError(self.wmspec, 'ACDC is not supported for %s' % self.args['SplittingAlgo'])
|
|
119
|
+
splittingFunc = self.defaultAlgo
|
|
120
|
+
if self.args['SplittingAlgo'] in self.algoMapping:
|
|
121
|
+
splittingFunc = self.algoMapping[self.args['SplittingAlgo']]
|
|
122
|
+
validBlocks = splittingFunc(acdc, acdcInfo, task)
|
|
123
|
+
self.logger.info("ACDC with the following validBlocks summary:\n%s", json.dumps(validBlocks, indent=2))
|
|
124
|
+
|
|
125
|
+
return validBlocks
|
|
126
|
+
|
|
127
|
+
def fixedSizeChunk(self, acdc, acdcInfo, task):
|
|
128
|
+
"""Return a set of blocks with a fixed number of ACDC records"""
|
|
129
|
+
fixedSizeBlocks = []
|
|
130
|
+
chunkSize = 250
|
|
131
|
+
acdcBlocks = acdc.chunkFileset(acdcInfo['collection'],
|
|
132
|
+
acdcInfo['fileset'],
|
|
133
|
+
chunkSize)
|
|
134
|
+
for block in acdcBlocks:
|
|
135
|
+
dbsBlock = {}
|
|
136
|
+
dbsBlock['Name'] = ACDCBlock.name(self.wmspec.name(),
|
|
137
|
+
acdcInfo["fileset"],
|
|
138
|
+
block['offset'], block['files'])
|
|
139
|
+
dbsBlock['NumberOfFiles'] = block['files']
|
|
140
|
+
dbsBlock['NumberOfEvents'] = block['events']
|
|
141
|
+
dbsBlock['NumberOfLumis'] = block['lumis']
|
|
142
|
+
if task.getTrustSitelists().get('trustlists'):
|
|
143
|
+
dbsBlock["Sites"] = self.sites
|
|
144
|
+
else:
|
|
145
|
+
dbsBlock["Sites"] = self.cric.PNNstoPSNs(block["locations"])
|
|
146
|
+
dbsBlock['ACDC'] = acdcInfo
|
|
147
|
+
if dbsBlock['NumberOfFiles']:
|
|
148
|
+
fixedSizeBlocks.append(dbsBlock)
|
|
149
|
+
return fixedSizeBlocks
|
|
150
|
+
|
|
151
|
+
def singleChunk(self, acdc, acdcInfo, task):
|
|
152
|
+
"""Return a single block (inside a list) with all associated ACDC records"""
|
|
153
|
+
result = []
|
|
154
|
+
acdcBlock = acdc.singleChunkFileset(acdcInfo['collection'],
|
|
155
|
+
acdcInfo['fileset'])
|
|
156
|
+
dbsBlock = {}
|
|
157
|
+
dbsBlock['Name'] = ACDCBlock.name(self.wmspec.name(),
|
|
158
|
+
acdcInfo["fileset"],
|
|
159
|
+
acdcBlock['offset'], acdcBlock['files'])
|
|
160
|
+
dbsBlock['NumberOfFiles'] = acdcBlock['files']
|
|
161
|
+
dbsBlock['NumberOfEvents'] = acdcBlock['events']
|
|
162
|
+
dbsBlock['NumberOfLumis'] = acdcBlock['lumis']
|
|
163
|
+
if task.getTrustSitelists().get('trustlists'):
|
|
164
|
+
dbsBlock["Sites"] = self.sites
|
|
165
|
+
else:
|
|
166
|
+
dbsBlock["Sites"] = self.cric.PNNstoPSNs(acdcBlock["locations"])
|
|
167
|
+
dbsBlock['ACDC'] = acdcInfo
|
|
168
|
+
if dbsBlock['NumberOfFiles']:
|
|
169
|
+
result.append(dbsBlock)
|
|
170
|
+
|
|
171
|
+
return result
|