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,772 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
_WMBSHelper_
|
|
4
|
+
|
|
5
|
+
Use WMSpecParser to extract information for creating workflow, fileset, and subscription
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from builtins import next, str as newstr, bytes, zip, range
|
|
9
|
+
from future.utils import viewitems
|
|
10
|
+
|
|
11
|
+
import logging
|
|
12
|
+
import threading
|
|
13
|
+
from collections import defaultdict
|
|
14
|
+
|
|
15
|
+
from Utils.PythonVersion import PY3
|
|
16
|
+
from Utils.Utilities import encodeUnicodeToBytesConditional
|
|
17
|
+
from WMComponent.DBS3Buffer.DBSBufferDataset import DBSBufferDataset
|
|
18
|
+
from WMComponent.DBS3Buffer.DBSBufferFile import DBSBufferFile
|
|
19
|
+
from WMCore.BossAir.BossAirAPI import BossAirAPI, BossAirException
|
|
20
|
+
from WMCore.DAOFactory import DAOFactory
|
|
21
|
+
from WMCore.DataStructs.File import File as DatastructFile
|
|
22
|
+
from WMCore.DataStructs.LumiList import LumiList
|
|
23
|
+
from WMCore.DataStructs.Run import Run
|
|
24
|
+
from WMCore.JobStateMachine.ChangeState import ChangeState
|
|
25
|
+
from WMCore.ResourceControl.ResourceControl import ResourceControl
|
|
26
|
+
from WMCore.WMBS.File import File
|
|
27
|
+
from WMCore.WMBS.Fileset import Fileset
|
|
28
|
+
from WMCore.WMBS.Job import Job
|
|
29
|
+
from WMCore.WMBS.Subscription import Subscription
|
|
30
|
+
from WMCore.WMBS.Workflow import Workflow
|
|
31
|
+
from WMCore.WMConnectionBase import WMConnectionBase
|
|
32
|
+
from WMCore.WMException import WMException
|
|
33
|
+
from WMCore.WMRuntime.SandboxCreator import SandboxCreator
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def wmbsSubscriptionStatus(logger, dbi, conn, transaction):
|
|
37
|
+
"""
|
|
38
|
+
Function to return status of wmbs subscriptions
|
|
39
|
+
"""
|
|
40
|
+
daoFactory = DAOFactory(package='WMCore.WMBS', logger=logger, dbinterface=dbi)
|
|
41
|
+
action = daoFactory(classname='Monitoring.SubscriptionStatus')
|
|
42
|
+
return action.execute(conn=conn, transaction=transaction)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class WorkQueueWMBSException(WMException):
|
|
46
|
+
"""
|
|
47
|
+
Dummy exception class for exceptions raised
|
|
48
|
+
in WMBS Helper.
|
|
49
|
+
|
|
50
|
+
TODO: Do something useful
|
|
51
|
+
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
pass
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def killWorkflow(workflowName, jobCouchConfig, bossAirConfig=None):
|
|
58
|
+
"""
|
|
59
|
+
_killWorkflow_
|
|
60
|
+
|
|
61
|
+
Kill a workflow that is already executing inside the agent. This will
|
|
62
|
+
mark all incomplete jobs as failed and files that belong to all
|
|
63
|
+
non-cleanup and non-logcollect subscriptions as failed. The name of the
|
|
64
|
+
JSM couch database and the URL to the database must be passed in as well
|
|
65
|
+
so the state transitions are logged.
|
|
66
|
+
"""
|
|
67
|
+
myThread = threading.currentThread()
|
|
68
|
+
daoFactory = DAOFactory(package="WMCore.WMBS",
|
|
69
|
+
logger=myThread.logger,
|
|
70
|
+
dbinterface=myThread.dbi)
|
|
71
|
+
killFilesAction = daoFactory(classname="Subscriptions.KillWorkflow")
|
|
72
|
+
killJobsAction = daoFactory(classname="Jobs.KillWorkflow")
|
|
73
|
+
|
|
74
|
+
killFilesAction.execute(workflowName=workflowName,
|
|
75
|
+
conn=myThread.transaction.conn)
|
|
76
|
+
|
|
77
|
+
liveJobs = killJobsAction.execute(workflowName=workflowName,
|
|
78
|
+
conn=myThread.transaction.conn)
|
|
79
|
+
|
|
80
|
+
changeState = ChangeState(jobCouchConfig)
|
|
81
|
+
|
|
82
|
+
# Deal with any jobs that are running in the batch system
|
|
83
|
+
# only works if we can start the API
|
|
84
|
+
if bossAirConfig:
|
|
85
|
+
bossAir = BossAirAPI(config=bossAirConfig)
|
|
86
|
+
killableJobs = []
|
|
87
|
+
for liveJob in liveJobs:
|
|
88
|
+
if liveJob["state"].lower() == 'executing':
|
|
89
|
+
# Then we need to kill this on the batch system
|
|
90
|
+
liveWMBSJob = Job(id=liveJob["id"])
|
|
91
|
+
liveWMBSJob.update(liveJob)
|
|
92
|
+
killableJobs.append(liveJob)
|
|
93
|
+
# Now kill them
|
|
94
|
+
try:
|
|
95
|
+
logging.info("Killing %d jobs for workflow: %s", len(killableJobs), workflowName)
|
|
96
|
+
bossAir.kill(jobs=killableJobs, workflowName=workflowName)
|
|
97
|
+
except BossAirException as ex:
|
|
98
|
+
errMsg = "Error while trying to kill running jobs in workflow. Error: %s" % str(ex)
|
|
99
|
+
logging.exception(errMsg)
|
|
100
|
+
# But continue; we need to kill the jobs in the master
|
|
101
|
+
# the batch system will have to take care of itself.
|
|
102
|
+
|
|
103
|
+
liveWMBSJobs = defaultdict(list)
|
|
104
|
+
for liveJob in liveJobs:
|
|
105
|
+
if liveJob["state"] == "killed":
|
|
106
|
+
# Then we've killed it already
|
|
107
|
+
continue
|
|
108
|
+
liveWMBSJob = Job(id=liveJob["id"])
|
|
109
|
+
liveWMBSJob.update(liveJob)
|
|
110
|
+
liveWMBSJobs[liveJob["state"]].append(liveWMBSJob)
|
|
111
|
+
|
|
112
|
+
for state, jobsByState in viewitems(liveWMBSJobs):
|
|
113
|
+
if len(jobsByState) > 100 and state != "executing":
|
|
114
|
+
# if there are to many jobs skip the couch and dashboard update
|
|
115
|
+
# TODO: couch and dashboard need to be updated or parallel.
|
|
116
|
+
changeState.check("killed", state)
|
|
117
|
+
changeState.persist(jobsByState, "killed", state)
|
|
118
|
+
else:
|
|
119
|
+
changeState.propagate(jobsByState, "killed", state)
|
|
120
|
+
return
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def freeSlots(multiplier=1.0, minusRunning=False, allowedStates=None, knownCmsSites=None):
|
|
124
|
+
"""
|
|
125
|
+
Get free resources from wmbs.
|
|
126
|
+
|
|
127
|
+
Specify multiplier to apply a ratio to the actual numbers.
|
|
128
|
+
minusRunning control if running jobs should be counted
|
|
129
|
+
"""
|
|
130
|
+
allowedStates = allowedStates or ['Normal']
|
|
131
|
+
rc_sites = ResourceControl().listThresholdsForCreate()
|
|
132
|
+
thresholds = defaultdict(lambda: 0)
|
|
133
|
+
jobCounts = defaultdict(dict)
|
|
134
|
+
for name, site in viewitems(rc_sites):
|
|
135
|
+
if not site.get('cms_name'):
|
|
136
|
+
logging.warning("Not fetching work for %s, cms_name not defined", name)
|
|
137
|
+
continue
|
|
138
|
+
if knownCmsSites and site['cms_name'] not in knownCmsSites:
|
|
139
|
+
logging.warning(
|
|
140
|
+
"%s doesn't appear to be a known cms site, work may fail to be acquired for it", site['cms_name'])
|
|
141
|
+
if site['state'] not in allowedStates:
|
|
142
|
+
continue
|
|
143
|
+
slots = site['total_slots']
|
|
144
|
+
thresholds[site['cms_name']] += (slots * multiplier)
|
|
145
|
+
if minusRunning:
|
|
146
|
+
jobCounts[site['cms_name']] = dict(
|
|
147
|
+
(k, jobCounts[site['cms_name']].get(k, 0) + site['pending_jobs'].get(k, 0))
|
|
148
|
+
for k in site['pending_jobs'])
|
|
149
|
+
|
|
150
|
+
return dict(thresholds), dict(jobCounts)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class WMBSHelper(WMConnectionBase):
|
|
154
|
+
"""
|
|
155
|
+
_WMBSHelper_
|
|
156
|
+
|
|
157
|
+
Interface between the WorkQueue and WMBS.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
def __init__(self, wmSpec, taskName, blockName=None, mask=None,
|
|
161
|
+
cachepath='.', commonLocation=None):
|
|
162
|
+
"""
|
|
163
|
+
_init_
|
|
164
|
+
|
|
165
|
+
Initialize DAOs and other things needed.
|
|
166
|
+
"""
|
|
167
|
+
self.block = blockName
|
|
168
|
+
self.mask = mask
|
|
169
|
+
self.wmSpec = wmSpec
|
|
170
|
+
self.topLevelTask = wmSpec.getTask(taskName)
|
|
171
|
+
self.cachepath = cachepath
|
|
172
|
+
self.isDBS = True
|
|
173
|
+
|
|
174
|
+
self.topLevelFileset = None
|
|
175
|
+
self.topLevelSubscription = None
|
|
176
|
+
self.topLevelTaskDBSBufferId = None
|
|
177
|
+
self.commonLocation = commonLocation or []
|
|
178
|
+
|
|
179
|
+
self.mergeOutputMapping = {}
|
|
180
|
+
|
|
181
|
+
# Initiate the pieces you need to run your own DAOs
|
|
182
|
+
WMConnectionBase.__init__(self, "WMCore.WMBS")
|
|
183
|
+
myThread = threading.currentThread()
|
|
184
|
+
self.dbsDaoFactory = DAOFactory(package="WMComponent.DBS3Buffer",
|
|
185
|
+
logger=myThread.logger,
|
|
186
|
+
dbinterface=myThread.dbi)
|
|
187
|
+
|
|
188
|
+
# DAOs from WMBS for file commit
|
|
189
|
+
self.setParentage = self.daofactory(classname="Files.SetParentage")
|
|
190
|
+
self.setFileLocation = self.daofactory(classname="Files.SetLocationForWorkQueue")
|
|
191
|
+
self.setFileAddChecksum = self.daofactory(classname="Files.AddChecksumByLFN")
|
|
192
|
+
self.addFileAction = self.daofactory(classname="Files.Add")
|
|
193
|
+
self.addToFileset = self.daofactory(classname="Files.AddDupsToFileset")
|
|
194
|
+
self.getLocationInfo = self.daofactory(classname="Locations.GetSiteInfo")
|
|
195
|
+
|
|
196
|
+
# DAOs from DBSBuffer
|
|
197
|
+
self.dbsCreateFiles = self.dbsDaoFactory(classname="DBSBufferFiles.Add")
|
|
198
|
+
self.dbsSetLocation = self.dbsDaoFactory(classname="DBSBufferFiles.SetLocationByLFN")
|
|
199
|
+
self.dbsInsertLocation = self.dbsDaoFactory(classname="DBSBufferFiles.AddLocation")
|
|
200
|
+
self.dbsSetChecksum = self.dbsDaoFactory(classname="DBSBufferFiles.AddChecksumByLFN")
|
|
201
|
+
self.dbsInsertWorkflow = self.dbsDaoFactory(classname="InsertWorkflow")
|
|
202
|
+
|
|
203
|
+
# Added for file creation bookkeeping
|
|
204
|
+
self.dbsFilesToCreate = set()
|
|
205
|
+
self.wmbsFilesToCreate = set()
|
|
206
|
+
self.insertedBogusDataset = -1
|
|
207
|
+
|
|
208
|
+
return
|
|
209
|
+
|
|
210
|
+
def createSandbox(self):
|
|
211
|
+
"""Create the runtime sandbox"""
|
|
212
|
+
sandboxCreator = SandboxCreator()
|
|
213
|
+
sandboxCreator.makeSandbox(self.cachepath, self.wmSpec)
|
|
214
|
+
|
|
215
|
+
def createTopLevelFileset(self, topLevelFilesetName=None):
|
|
216
|
+
"""
|
|
217
|
+
_createTopLevelFileset_
|
|
218
|
+
|
|
219
|
+
Create the top level fileset for the workflow. If the name of the top
|
|
220
|
+
level fileset is not given create one.
|
|
221
|
+
"""
|
|
222
|
+
if topLevelFilesetName is None:
|
|
223
|
+
filesetName = ("%s-%s" % (self.wmSpec.name(),
|
|
224
|
+
self.wmSpec.getTopLevelTask()[0].name()))
|
|
225
|
+
if self.block:
|
|
226
|
+
filesetName += "-%s" % self.block
|
|
227
|
+
if self.mask:
|
|
228
|
+
from hashlib import md5
|
|
229
|
+
mask_string = ",".join(["%s=%s" % (x, self.mask[x]) for x in sorted(self.mask)])
|
|
230
|
+
mask_string = encodeUnicodeToBytesConditional(mask_string, condition=PY3)
|
|
231
|
+
filesetName += "-%s" % md5(mask_string).hexdigest()
|
|
232
|
+
else:
|
|
233
|
+
filesetName = topLevelFilesetName
|
|
234
|
+
|
|
235
|
+
self.topLevelFileset = Fileset(filesetName)
|
|
236
|
+
self.topLevelFileset.create()
|
|
237
|
+
return
|
|
238
|
+
|
|
239
|
+
def outputFilesetName(self, task, outputModuleName, dataTier=''):
|
|
240
|
+
"""
|
|
241
|
+
_outputFilesetName_
|
|
242
|
+
|
|
243
|
+
Generate an output fileset name for the given task, output module and data tier.
|
|
244
|
+
"""
|
|
245
|
+
if task.taskType() == "Merge":
|
|
246
|
+
outputFilesetName = "%s/merged-%s%s" % (task.getPathName(),
|
|
247
|
+
outputModuleName, dataTier)
|
|
248
|
+
else:
|
|
249
|
+
outputFilesetName = "%s/unmerged-%s%s" % (task.getPathName(),
|
|
250
|
+
outputModuleName, dataTier)
|
|
251
|
+
|
|
252
|
+
return outputFilesetName
|
|
253
|
+
|
|
254
|
+
def createSubscription(self, task, fileset, alternativeFilesetClose=False):
|
|
255
|
+
"""
|
|
256
|
+
_createSubscription_
|
|
257
|
+
|
|
258
|
+
Create subscriptions in the database.
|
|
259
|
+
This includes workflows in WMBS and DBSBuffer, output maps, datasets
|
|
260
|
+
and phedex subscriptions, and filesets for each task below and including
|
|
261
|
+
the given task.
|
|
262
|
+
"""
|
|
263
|
+
self._createSubscriptionsInWMBS(task, fileset, alternativeFilesetClose)
|
|
264
|
+
|
|
265
|
+
self._createWorkflowsInDBSBuffer()
|
|
266
|
+
self._createDatasetSubscriptionsInDBSBuffer()
|
|
267
|
+
|
|
268
|
+
return
|
|
269
|
+
|
|
270
|
+
def _createSubscriptionsInWMBS(self, task, fileset, alternativeFilesetClose=False,
|
|
271
|
+
createSandbox=True):
|
|
272
|
+
"""
|
|
273
|
+
__createSubscriptionsInWMBS_
|
|
274
|
+
|
|
275
|
+
Create subscriptions in WMBS for all the tasks in the spec. This
|
|
276
|
+
includes filesets, workflows and the output map for each task.
|
|
277
|
+
:param createSandbox: boolean flag to skip (re-)creation of the workload sandbox
|
|
278
|
+
"""
|
|
279
|
+
# create runtime sandbox for workflow
|
|
280
|
+
if createSandbox:
|
|
281
|
+
self.createSandbox()
|
|
282
|
+
|
|
283
|
+
# FIXME: Let workflow put in values if spec is missing them
|
|
284
|
+
workflow = Workflow(spec=self.wmSpec.specUrl(), owner=self.wmSpec.getOwner()["name"],
|
|
285
|
+
dn=self.wmSpec.getOwner().get("dn", "unknown"),
|
|
286
|
+
group=self.wmSpec.getOwner().get("group", "unknown"),
|
|
287
|
+
owner_vogroup=self.wmSpec.getOwner().get("vogroup", "DEFAULT"),
|
|
288
|
+
owner_vorole=self.wmSpec.getOwner().get("vorole", "DEFAULT"),
|
|
289
|
+
name=self.wmSpec.name(), task=task.getPathName(),
|
|
290
|
+
wfType=self.wmSpec.getDashboardActivity(),
|
|
291
|
+
alternativeFilesetClose=alternativeFilesetClose,
|
|
292
|
+
priority=self.wmSpec.priority())
|
|
293
|
+
workflow.create()
|
|
294
|
+
|
|
295
|
+
subscription = Subscription(fileset=fileset, workflow=workflow,
|
|
296
|
+
split_algo=task.jobSplittingAlgorithm(),
|
|
297
|
+
type=task.getPrimarySubType())
|
|
298
|
+
subscription.create()
|
|
299
|
+
|
|
300
|
+
### FIXME: I'm pretty sure we can improve how we handle this site white/black list
|
|
301
|
+
for site in task.siteWhitelist():
|
|
302
|
+
subscription.addWhiteBlackList([{"site_name": site, "valid": True}])
|
|
303
|
+
|
|
304
|
+
for site in task.siteBlacklist():
|
|
305
|
+
subscription.addWhiteBlackList([{"site_name": site, "valid": False}])
|
|
306
|
+
|
|
307
|
+
if self.topLevelSubscription is None:
|
|
308
|
+
self.topLevelSubscription = subscription
|
|
309
|
+
logging.info("Top level subscription %s created for %s", subscription["id"], self.wmSpec.name())
|
|
310
|
+
else:
|
|
311
|
+
logging.info("Child subscription %s created for %s", subscription["id"], self.wmSpec.name())
|
|
312
|
+
|
|
313
|
+
outputModules = task.getOutputModulesForTask()
|
|
314
|
+
ignoredOutputModules = task.getIgnoredOutputModulesForTask()
|
|
315
|
+
for outputModule in outputModules:
|
|
316
|
+
for outputModuleName in sorted(outputModule.listSections_()):
|
|
317
|
+
if outputModuleName in ignoredOutputModules:
|
|
318
|
+
msg = "%s has %s as IgnoredOutputModule, skipping fileset creation."
|
|
319
|
+
logging.info(msg, task.getPathName(), outputModuleName)
|
|
320
|
+
continue
|
|
321
|
+
dataTier = getattr(getattr(outputModule, outputModuleName), "dataTier", '')
|
|
322
|
+
filesetName = self.outputFilesetName(task, outputModuleName, dataTier)
|
|
323
|
+
outputFileset = Fileset(filesetName)
|
|
324
|
+
outputFileset.create()
|
|
325
|
+
outputFileset.markOpen(True)
|
|
326
|
+
mergedOutputFileset = None
|
|
327
|
+
|
|
328
|
+
for childTask in task.childTaskIterator():
|
|
329
|
+
if childTask.data.input.outputModule == outputModuleName:
|
|
330
|
+
childDatatier = getattr(childTask.data.input, 'dataTier', '')
|
|
331
|
+
if childTask.taskType() in ["Cleanup", "Merge"] and childDatatier != dataTier:
|
|
332
|
+
continue
|
|
333
|
+
elif childTask.taskType() == "Merge" and childDatatier == dataTier:
|
|
334
|
+
filesetName = self.outputFilesetName(childTask, "Merged", dataTier)
|
|
335
|
+
mergedOutputFileset = Fileset(filesetName)
|
|
336
|
+
mergedOutputFileset.create()
|
|
337
|
+
mergedOutputFileset.markOpen(True)
|
|
338
|
+
|
|
339
|
+
primaryDataset = getattr(getattr(outputModule, outputModuleName), "primaryDataset", None)
|
|
340
|
+
if primaryDataset is not None:
|
|
341
|
+
self.mergeOutputMapping[mergedOutputFileset.id] = primaryDataset
|
|
342
|
+
|
|
343
|
+
self._createSubscriptionsInWMBS(childTask, outputFileset,
|
|
344
|
+
alternativeFilesetClose, createSandbox=False)
|
|
345
|
+
|
|
346
|
+
if mergedOutputFileset is None:
|
|
347
|
+
workflow.addOutput(outputModuleName + dataTier, outputFileset,
|
|
348
|
+
outputFileset)
|
|
349
|
+
else:
|
|
350
|
+
workflow.addOutput(outputModuleName + dataTier, outputFileset,
|
|
351
|
+
mergedOutputFileset)
|
|
352
|
+
|
|
353
|
+
return
|
|
354
|
+
|
|
355
|
+
def addMCFakeFile(self):
|
|
356
|
+
"""Add a fake file for wmbs to run production over"""
|
|
357
|
+
needed = ['FirstEvent', 'FirstLumi', 'FirstRun', 'LastEvent', 'LastLumi', 'LastRun']
|
|
358
|
+
for key in needed:
|
|
359
|
+
if self.mask and self.mask.get(key) is None:
|
|
360
|
+
msg = 'Invalid value "%s" for %s' % (self.mask.get(key), key)
|
|
361
|
+
raise WorkQueueWMBSException(msg)
|
|
362
|
+
|
|
363
|
+
locations = set()
|
|
364
|
+
siteInfo = self.getLocationInfo.execute(conn=self.getDBConn(),
|
|
365
|
+
transaction=self.existingTransaction())
|
|
366
|
+
for site in siteInfo:
|
|
367
|
+
locations.update(set(site['pnn']) & set(self.commonLocation))
|
|
368
|
+
|
|
369
|
+
if not locations:
|
|
370
|
+
msg = 'No locations to inject Monte Carlo work to, unable to proceed'
|
|
371
|
+
raise WorkQueueWMBSException(msg)
|
|
372
|
+
mcFakeFileName = "MCFakeFile-%s" % self.topLevelFileset.name
|
|
373
|
+
wmbsFile = File(lfn=mcFakeFileName,
|
|
374
|
+
first_event=self.mask['FirstEvent'],
|
|
375
|
+
last_event=self.mask['LastEvent'],
|
|
376
|
+
events=self.mask['LastEvent'] - self.mask['FirstEvent'] + 1, # inclusive range
|
|
377
|
+
locations=locations,
|
|
378
|
+
merged=False, # merged causes dbs parentage relation
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
if self.mask:
|
|
382
|
+
lumis = list(range(self.mask['FirstLumi'], self.mask['LastLumi'] + 1)) # inclusive range
|
|
383
|
+
wmbsFile.addRun(Run(self.mask['FirstRun'], *lumis)) # assume run number static
|
|
384
|
+
else:
|
|
385
|
+
wmbsFile.addRun(Run(1, 1))
|
|
386
|
+
|
|
387
|
+
wmbsFile['inFileset'] = True # file is not a parent
|
|
388
|
+
|
|
389
|
+
logging.debug("WMBS MC Fake File: %s on Location: %s", wmbsFile['lfn'], wmbsFile['newlocations'])
|
|
390
|
+
|
|
391
|
+
self.wmbsFilesToCreate.add(wmbsFile)
|
|
392
|
+
|
|
393
|
+
totalFiles = self.topLevelFileset.addFilesToWMBSInBulk(self.wmbsFilesToCreate,
|
|
394
|
+
self.wmSpec.name(),
|
|
395
|
+
isDBS=self.isDBS)
|
|
396
|
+
|
|
397
|
+
self.topLevelFileset.markOpen(False)
|
|
398
|
+
return totalFiles
|
|
399
|
+
|
|
400
|
+
def createSubscriptionAndAddFiles(self, block):
|
|
401
|
+
"""
|
|
402
|
+
_createSubscriptionAndAddFiles_
|
|
403
|
+
|
|
404
|
+
Create the subscription and add files at one time to
|
|
405
|
+
put everything in one transaction.
|
|
406
|
+
|
|
407
|
+
"""
|
|
408
|
+
existingTransaction = self.beginTransaction()
|
|
409
|
+
|
|
410
|
+
self.createTopLevelFileset()
|
|
411
|
+
try:
|
|
412
|
+
self.createSubscription(self.topLevelTask, self.topLevelFileset)
|
|
413
|
+
except Exception as ex:
|
|
414
|
+
myThread = threading.currentThread()
|
|
415
|
+
myThread.transaction.rollback()
|
|
416
|
+
logging.exception("Failed to create subscription. Error: %s", str(ex))
|
|
417
|
+
raise ex
|
|
418
|
+
|
|
419
|
+
if block:
|
|
420
|
+
logging.info('"%s" Injecting block %s (%d files) into wmbs.',
|
|
421
|
+
self.wmSpec.name(), self.block, len(block['Files']))
|
|
422
|
+
addedFiles = self.addFiles(block)
|
|
423
|
+
else:
|
|
424
|
+
# For MC case
|
|
425
|
+
logging.info('"%s" Injecting production %s:%s:%s - %s:%s:%s (run:lumi:event) into wmbs',
|
|
426
|
+
self.wmSpec.name(),
|
|
427
|
+
self.mask['FirstRun'], self.mask['FirstLumi'], self.mask['FirstEvent'],
|
|
428
|
+
self.mask['LastRun'], self.mask['LastLumi'], self.mask['LastEvent'])
|
|
429
|
+
addedFiles = self.addMCFakeFile()
|
|
430
|
+
|
|
431
|
+
self.commitTransaction(existingTransaction)
|
|
432
|
+
logging.info("Transaction committed: %s, for %s", not existingTransaction, self.wmSpec.name())
|
|
433
|
+
|
|
434
|
+
# Now that we've created those files, clear the list
|
|
435
|
+
self.dbsFilesToCreate = set()
|
|
436
|
+
self.wmbsFilesToCreate = set()
|
|
437
|
+
|
|
438
|
+
return self.topLevelSubscription, addedFiles
|
|
439
|
+
|
|
440
|
+
def addFiles(self, block):
|
|
441
|
+
"""
|
|
442
|
+
_addFiles_
|
|
443
|
+
|
|
444
|
+
create wmbs files from given dbs block.
|
|
445
|
+
as well as run lumi update
|
|
446
|
+
"""
|
|
447
|
+
if self.topLevelTask.getInputACDC():
|
|
448
|
+
self.isDBS = False
|
|
449
|
+
logging.info('Adding ACDC files into WMBS for %s', self.wmSpec.name())
|
|
450
|
+
for acdcFile in self.validFiles(block['Files']):
|
|
451
|
+
self._addACDCFileToWMBSFile(acdcFile)
|
|
452
|
+
else:
|
|
453
|
+
self.isDBS = True
|
|
454
|
+
blockPNNs = block['PhEDExNodeNames']
|
|
455
|
+
logging.info('Adding files into WMBS for %s with PNNs: %s', self.wmSpec.name(), blockPNNs)
|
|
456
|
+
for dbsFile in self.validFiles(block['Files']):
|
|
457
|
+
self._addDBSFileToWMBSFile(dbsFile, blockPNNs)
|
|
458
|
+
|
|
459
|
+
# Add files to WMBS
|
|
460
|
+
logging.info('Inserting %d files in bulk into WMBS for %s', len(self.wmbsFilesToCreate),
|
|
461
|
+
self.wmSpec.name())
|
|
462
|
+
totalFiles = self.topLevelFileset.addFilesToWMBSInBulk(self.wmbsFilesToCreate,
|
|
463
|
+
self.wmSpec.name(),
|
|
464
|
+
isDBS=self.isDBS)
|
|
465
|
+
# Add files to DBSBuffer
|
|
466
|
+
logging.info('Inserting %d files in bulk into DBSBuffer for %s', len(self.dbsFilesToCreate),
|
|
467
|
+
self.wmSpec.name())
|
|
468
|
+
self._createFilesInDBSBuffer()
|
|
469
|
+
|
|
470
|
+
# DBS blocks are always closed, so mark fileset as closed as well
|
|
471
|
+
self.topLevelFileset.markOpen(False)
|
|
472
|
+
return totalFiles
|
|
473
|
+
|
|
474
|
+
def getMergeOutputMapping(self):
|
|
475
|
+
"""
|
|
476
|
+
_getMergeOutputMapping_
|
|
477
|
+
|
|
478
|
+
retrieves the relationship between primary
|
|
479
|
+
dataset and merge output fileset ids for
|
|
480
|
+
all merge tasks created
|
|
481
|
+
"""
|
|
482
|
+
return self.mergeOutputMapping
|
|
483
|
+
|
|
484
|
+
def _createWorkflowsInDBSBuffer(self):
|
|
485
|
+
"""
|
|
486
|
+
_createWorkflowsInDBSBuffer_
|
|
487
|
+
|
|
488
|
+
Register workflow information and settings in dbsbuffer for all
|
|
489
|
+
tasks that will potentially produce any output in this spec.
|
|
490
|
+
"""
|
|
491
|
+
existingTransaction = self.beginTransaction()
|
|
492
|
+
|
|
493
|
+
for task in self.wmSpec.listOutputProducingTasks():
|
|
494
|
+
workflow_id = self.dbsInsertWorkflow.execute(self.wmSpec.name(), task,
|
|
495
|
+
self.wmSpec.getBlockCloseMaxWaitTime(),
|
|
496
|
+
self.wmSpec.getBlockCloseMaxFiles(),
|
|
497
|
+
self.wmSpec.getBlockCloseMaxEvents(),
|
|
498
|
+
self.wmSpec.getBlockCloseMaxSize(),
|
|
499
|
+
conn=self.getDBConn(), transaction=self.existingTransaction())
|
|
500
|
+
if task == self.topLevelTask.getPathName():
|
|
501
|
+
self.topLevelTaskDBSBufferId = workflow_id
|
|
502
|
+
|
|
503
|
+
self.commitTransaction(existingTransaction)
|
|
504
|
+
|
|
505
|
+
def _createDatasetSubscriptionsInDBSBuffer(self):
|
|
506
|
+
"""
|
|
507
|
+
_createDatasetSubscriptionsInDBSBuffer_
|
|
508
|
+
|
|
509
|
+
Insert the subscriptions defined in the workload for the output
|
|
510
|
+
datasets with the different options.
|
|
511
|
+
"""
|
|
512
|
+
existingTransaction = self.beginTransaction()
|
|
513
|
+
|
|
514
|
+
subInfo = self.wmSpec.getSubscriptionInformation()
|
|
515
|
+
for dataset in subInfo:
|
|
516
|
+
dbsDataset = DBSBufferDataset(path=dataset)
|
|
517
|
+
dbsDataset.create()
|
|
518
|
+
dbsDataset.addSubscription(subInfo[dataset])
|
|
519
|
+
self.commitTransaction(existingTransaction)
|
|
520
|
+
return
|
|
521
|
+
|
|
522
|
+
def _createFilesInDBSBuffer(self):
|
|
523
|
+
"""
|
|
524
|
+
_createFilesInDBSBuffer_
|
|
525
|
+
|
|
526
|
+
It does the actual job of creating things in DBSBuffer
|
|
527
|
+
|
|
528
|
+
"""
|
|
529
|
+
if not self.dbsFilesToCreate:
|
|
530
|
+
# Whoops, nothing to do!
|
|
531
|
+
return
|
|
532
|
+
|
|
533
|
+
dbsFileTuples = set()
|
|
534
|
+
dbsFileLoc = []
|
|
535
|
+
dbsCksumBinds = []
|
|
536
|
+
locationsToAdd = set()
|
|
537
|
+
|
|
538
|
+
# The first thing we need to do is add the datasetAlgo
|
|
539
|
+
# Assume all files in a pass come from one datasetAlgo?
|
|
540
|
+
if self.insertedBogusDataset == -1:
|
|
541
|
+
self.insertedBogusDataset = next(iter(self.dbsFilesToCreate)).insertDatasetAlgo()
|
|
542
|
+
|
|
543
|
+
for dbsFile in self.dbsFilesToCreate:
|
|
544
|
+
# Append a tuple in the format specified by DBSBufferFiles.Add
|
|
545
|
+
# Also run insertDatasetAlgo
|
|
546
|
+
|
|
547
|
+
lfn = dbsFile['lfn']
|
|
548
|
+
selfChecksums = dbsFile['checksums']
|
|
549
|
+
|
|
550
|
+
newTuple = (lfn, dbsFile['size'], dbsFile['events'],
|
|
551
|
+
self.insertedBogusDataset, dbsFile['status'],
|
|
552
|
+
self.topLevelTaskDBSBufferId, dbsFile['in_phedex'])
|
|
553
|
+
|
|
554
|
+
dbsFileTuples.add(newTuple)
|
|
555
|
+
|
|
556
|
+
if len(dbsFile['newlocations']) < 1:
|
|
557
|
+
msg = ''
|
|
558
|
+
msg += "File created without any locations!\n"
|
|
559
|
+
msg += "File lfn: %s\n" % (lfn)
|
|
560
|
+
msg += "Rejecting this group of files in DBS!\n"
|
|
561
|
+
logging.error(msg)
|
|
562
|
+
raise WorkQueueWMBSException(msg)
|
|
563
|
+
|
|
564
|
+
for jobLocation in dbsFile['newlocations']:
|
|
565
|
+
locationsToAdd.add(jobLocation)
|
|
566
|
+
dbsFileLoc.append({'lfn': lfn, 'pnn': jobLocation})
|
|
567
|
+
|
|
568
|
+
if selfChecksums:
|
|
569
|
+
# If we have checksums we have to create a bind
|
|
570
|
+
# For each different checksum
|
|
571
|
+
for entry in selfChecksums:
|
|
572
|
+
dbsCksumBinds.append({'lfn': lfn, 'cksum': selfChecksums[entry],
|
|
573
|
+
'cktype': entry})
|
|
574
|
+
|
|
575
|
+
self.dbsInsertLocation.execute(siteName=locationsToAdd,
|
|
576
|
+
conn=self.getDBConn(),
|
|
577
|
+
transaction=self.existingTransaction())
|
|
578
|
+
|
|
579
|
+
self.dbsCreateFiles.execute(files=dbsFileTuples,
|
|
580
|
+
conn=self.getDBConn(),
|
|
581
|
+
transaction=self.existingTransaction())
|
|
582
|
+
|
|
583
|
+
self.dbsSetLocation.execute(binds=dbsFileLoc,
|
|
584
|
+
conn=self.getDBConn(),
|
|
585
|
+
transaction=self.existingTransaction())
|
|
586
|
+
|
|
587
|
+
if len(dbsCksumBinds) > 0:
|
|
588
|
+
self.dbsSetChecksum.execute(bulkList=dbsCksumBinds,
|
|
589
|
+
conn=self.getDBConn(),
|
|
590
|
+
transaction=self.existingTransaction())
|
|
591
|
+
|
|
592
|
+
return
|
|
593
|
+
|
|
594
|
+
def _addToDBSBuffer(self, dbsFile, checksums, locations):
|
|
595
|
+
"""
|
|
596
|
+
This step is just for increase the performance for
|
|
597
|
+
Accountant doesn't neccessary to check the parentage
|
|
598
|
+
"""
|
|
599
|
+
dbsBuffer = DBSBufferFile(lfn=dbsFile["LogicalFileName"],
|
|
600
|
+
size=dbsFile["FileSize"],
|
|
601
|
+
events=dbsFile["NumberOfEvents"],
|
|
602
|
+
checksums=checksums,
|
|
603
|
+
locations=locations,
|
|
604
|
+
status="GLOBAL",
|
|
605
|
+
inPhedex=1)
|
|
606
|
+
dbsBuffer.setDatasetPath('bogus')
|
|
607
|
+
dbsBuffer.setAlgorithm(appName="cmsRun", appVer="Unknown",
|
|
608
|
+
appFam="Unknown", psetHash="Unknown",
|
|
609
|
+
configContent="Unknown")
|
|
610
|
+
|
|
611
|
+
self.dbsFilesToCreate.add(dbsBuffer)
|
|
612
|
+
return
|
|
613
|
+
|
|
614
|
+
def _addDBSFileToWMBSFile(self, dbsFile, storageElements, inFileset=True):
|
|
615
|
+
"""
|
|
616
|
+
There are two assumptions made to make this method behave properly,
|
|
617
|
+
1. DBS returns only one level of ParentList.
|
|
618
|
+
If DBS returns multiple level of parentage, it will be still get handled.
|
|
619
|
+
However that might not be what we wanted. In that case, restrict to one level.
|
|
620
|
+
2. Assumes parents files are in the same location as child files.
|
|
621
|
+
This is not True in general case, but workquue should only select work only
|
|
622
|
+
where child and parent files are in the same location
|
|
623
|
+
"""
|
|
624
|
+
# TODO get dbsFile with lumi event information
|
|
625
|
+
wmbsParents = []
|
|
626
|
+
dbsFile.setdefault("ParentList", [])
|
|
627
|
+
for parent in dbsFile["ParentList"]:
|
|
628
|
+
wmbsParents.append(self._addDBSFileToWMBSFile(parent,
|
|
629
|
+
storageElements, inFileset=False))
|
|
630
|
+
|
|
631
|
+
checksums = {}
|
|
632
|
+
if dbsFile.get('Checksum'):
|
|
633
|
+
checksums['cksum'] = dbsFile['Checksum']
|
|
634
|
+
if dbsFile.get('Adler32'):
|
|
635
|
+
checksums['adler32'] = dbsFile['Adler32']
|
|
636
|
+
|
|
637
|
+
wmbsFile = File(lfn=dbsFile["LogicalFileName"],
|
|
638
|
+
size=dbsFile["FileSize"],
|
|
639
|
+
events=dbsFile["NumberOfEvents"],
|
|
640
|
+
checksums=checksums,
|
|
641
|
+
# TODO: need to get list of parent lfn
|
|
642
|
+
parents=wmbsParents,
|
|
643
|
+
locations=set(storageElements))
|
|
644
|
+
|
|
645
|
+
for lumi in dbsFile['LumiList']:
|
|
646
|
+
if isinstance(lumi['LumiSectionNumber'], list):
|
|
647
|
+
lumiSecList = (list(zip(lumi['LumiSectionNumber'], lumi['EventCount']))
|
|
648
|
+
if 'EventCount' in lumi else lumi['LumiSectionNumber'])
|
|
649
|
+
run = Run(lumi['RunNumber'], lumiSecList)
|
|
650
|
+
else:
|
|
651
|
+
lumiSecTuple = ((lumi['LumiSectionNumber'], lumi['EventCount'])
|
|
652
|
+
if 'EventCount' in lumi else lumi['LumiSectionNumber'])
|
|
653
|
+
run = Run(lumi['RunNumber'], lumiSecTuple)
|
|
654
|
+
wmbsFile.addRun(run)
|
|
655
|
+
|
|
656
|
+
self._addToDBSBuffer(dbsFile, checksums, storageElements)
|
|
657
|
+
|
|
658
|
+
logging.debug("WMBS File: %s on Location: %s", wmbsFile['lfn'], wmbsFile['newlocations'])
|
|
659
|
+
|
|
660
|
+
wmbsFile['inFileset'] = bool(inFileset)
|
|
661
|
+
self.wmbsFilesToCreate.add(wmbsFile)
|
|
662
|
+
|
|
663
|
+
return wmbsFile
|
|
664
|
+
|
|
665
|
+
def _convertACDCFileToDBSFile(self, acdcFile):
|
|
666
|
+
"""
|
|
667
|
+
convert ACDCFiles to dbs file format
|
|
668
|
+
"""
|
|
669
|
+
dbsFile = {}
|
|
670
|
+
dbsFile["LogicalFileName"] = acdcFile["lfn"]
|
|
671
|
+
dbsFile["FileSize"] = acdcFile["size"]
|
|
672
|
+
dbsFile["NumberOfEvents"] = acdcFile["events"]
|
|
673
|
+
return dbsFile
|
|
674
|
+
|
|
675
|
+
def _addACDCFileToWMBSFile(self, acdcFile, inFileset=True):
|
|
676
|
+
"""
|
|
677
|
+
adds the ACDC files into WMBS database
|
|
678
|
+
"""
|
|
679
|
+
wmbsParents = []
|
|
680
|
+
# If file is merged, then it will be the parent of whatever output that
|
|
681
|
+
# process this job (it twists my mind!). Meaning, block below can be skipped
|
|
682
|
+
if int(acdcFile.get("merged", 0)) == 0 and acdcFile["parents"]:
|
|
683
|
+
# set the parentage for all the unmerged parents
|
|
684
|
+
for parent in acdcFile["parents"]:
|
|
685
|
+
if parent.startswith("/store/unmerged/") or parent.startswith("MCFakeFile"):
|
|
686
|
+
logging.warning("WMBS ACDC skipped parent invalid file: %s", parent)
|
|
687
|
+
continue
|
|
688
|
+
logging.debug("WMBS ACDC Parent File: %s", parent)
|
|
689
|
+
parent = self._addACDCFileToWMBSFile(DatastructFile(lfn=parent,
|
|
690
|
+
locations=acdcFile["locations"],
|
|
691
|
+
merged=True),
|
|
692
|
+
inFileset=False)
|
|
693
|
+
wmbsParents.append(parent)
|
|
694
|
+
|
|
695
|
+
# pass empty check sum since it won't be updated to dbs anyway
|
|
696
|
+
checksums = {}
|
|
697
|
+
wmbsFile = File(lfn=str(acdcFile["lfn"]),
|
|
698
|
+
size=acdcFile["size"],
|
|
699
|
+
events=acdcFile["events"],
|
|
700
|
+
first_event=acdcFile.get('first_event', 0),
|
|
701
|
+
last_event=acdcFile.get('last_event', 0),
|
|
702
|
+
checksums=checksums,
|
|
703
|
+
parents=wmbsParents,
|
|
704
|
+
locations=acdcFile["locations"],
|
|
705
|
+
merged=acdcFile.get('merged', True))
|
|
706
|
+
|
|
707
|
+
## TODO need to get the lumi lists
|
|
708
|
+
for run in acdcFile['runs']:
|
|
709
|
+
wmbsFile.addRun(run)
|
|
710
|
+
|
|
711
|
+
if not acdcFile["lfn"].startswith("/store/unmerged") or wmbsParents:
|
|
712
|
+
# only add to DBSBuffer if is not unmerged file or it has parents.
|
|
713
|
+
dbsFile = self._convertACDCFileToDBSFile(acdcFile)
|
|
714
|
+
self._addToDBSBuffer(dbsFile, checksums, acdcFile["locations"])
|
|
715
|
+
|
|
716
|
+
logging.debug("WMBS ACDC File: %s on Location: %s", wmbsFile['lfn'], wmbsFile['newlocations'])
|
|
717
|
+
|
|
718
|
+
wmbsFile['inFileset'] = bool(inFileset)
|
|
719
|
+
|
|
720
|
+
self.wmbsFilesToCreate.add(wmbsFile)
|
|
721
|
+
|
|
722
|
+
return wmbsFile
|
|
723
|
+
|
|
724
|
+
def validFiles(self, files):
|
|
725
|
+
"""
|
|
726
|
+
Apply lumi mask and or run white/black list and return files which have
|
|
727
|
+
one or more of the requested lumis
|
|
728
|
+
"""
|
|
729
|
+
runWhiteList = self.topLevelTask.inputRunWhitelist()
|
|
730
|
+
runBlackList = self.topLevelTask.inputRunBlacklist()
|
|
731
|
+
lumiMask = self.topLevelTask.getLumiMask()
|
|
732
|
+
|
|
733
|
+
blackMask = None
|
|
734
|
+
if lumiMask: # We have a lumiMask, so use it and modify with run white/black list
|
|
735
|
+
if runWhiteList:
|
|
736
|
+
lumiMask.selectRuns(runWhiteList)
|
|
737
|
+
if runBlackList:
|
|
738
|
+
lumiMask.removeRuns(runBlackList)
|
|
739
|
+
elif runWhiteList: # We have a run whitelist, subtract off blacklist
|
|
740
|
+
lumiMask = LumiList(runs=runWhiteList)
|
|
741
|
+
if runBlackList: # We only have a blacklist, so make a black mask out of it instead
|
|
742
|
+
lumiMask.removeRuns(runBlackList)
|
|
743
|
+
else:
|
|
744
|
+
lumiMask = None
|
|
745
|
+
if runBlackList:
|
|
746
|
+
blackMask = LumiList(runs=runBlackList)
|
|
747
|
+
|
|
748
|
+
results = []
|
|
749
|
+
for f in files:
|
|
750
|
+
if isinstance(f, (newstr, bytes)) or "LumiList" not in f:
|
|
751
|
+
results.append(f)
|
|
752
|
+
continue
|
|
753
|
+
|
|
754
|
+
# Create a LumiList from the WMBS info
|
|
755
|
+
runLumis = {}
|
|
756
|
+
for x in f['LumiList']:
|
|
757
|
+
if x['RunNumber'] in runLumis:
|
|
758
|
+
runLumis[x['RunNumber']].extend(x['LumiSectionNumber'])
|
|
759
|
+
else:
|
|
760
|
+
runLumis[x['RunNumber']] = x['LumiSectionNumber']
|
|
761
|
+
fileLumiList = LumiList(runsAndLumis=runLumis)
|
|
762
|
+
|
|
763
|
+
if lumiMask:
|
|
764
|
+
if fileLumiList & lumiMask: # At least one lumi from file is in lumiMask
|
|
765
|
+
results.append(f)
|
|
766
|
+
elif blackMask:
|
|
767
|
+
if fileLumiList - blackMask: # At least one lumi from file is not in blackMask
|
|
768
|
+
results.append(f)
|
|
769
|
+
else: # There is effectively no mask
|
|
770
|
+
results.append(f)
|
|
771
|
+
|
|
772
|
+
return results
|