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,256 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
_Run_
|
|
5
|
+
|
|
6
|
+
container representing a run, and its constituent lumi sections and event counts
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import print_function
|
|
10
|
+
from future.utils import viewitems, listitems
|
|
11
|
+
|
|
12
|
+
import hashlib
|
|
13
|
+
from builtins import str as newstr, bytes as newbytes
|
|
14
|
+
from Utils.PythonVersion import PY3
|
|
15
|
+
from Utils.Utilities import encodeUnicodeToBytesConditional, encodeUnicodeToBytes
|
|
16
|
+
from WMCore.DataStructs.WMObject import WMObject
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Run(WMObject):
|
|
20
|
+
"""
|
|
21
|
+
_Run_
|
|
22
|
+
|
|
23
|
+
Run container, is a list of lumi sections with associate event counts
|
|
24
|
+
|
|
25
|
+
TODO
|
|
26
|
+
- use the decorator `from functools import total_ordering` after
|
|
27
|
+
dropping support for python 2.6
|
|
28
|
+
- then, drop __ne__, __le__, __gt__, __ge__
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(self, runNumber=None, *newLumis):
|
|
32
|
+
WMObject.__init__(self)
|
|
33
|
+
self.run = runNumber
|
|
34
|
+
self.eventsPerLumi = {}
|
|
35
|
+
self.extendLumis(newLumis)
|
|
36
|
+
|
|
37
|
+
def __str__(self):
|
|
38
|
+
return "Run%s:%s" % (self.run, self.eventsPerLumi)
|
|
39
|
+
|
|
40
|
+
def __eq__(self, rhs):
|
|
41
|
+
"""
|
|
42
|
+
Check equality of run numbers and then underlying lumi/event dicts
|
|
43
|
+
"""
|
|
44
|
+
if not isinstance(rhs, Run):
|
|
45
|
+
return False
|
|
46
|
+
if self.run != rhs.run:
|
|
47
|
+
return False
|
|
48
|
+
return self.eventsPerLumi == rhs.eventsPerLumi
|
|
49
|
+
|
|
50
|
+
def __ne__(self, rhs):
|
|
51
|
+
return not self.__eq__(rhs)
|
|
52
|
+
|
|
53
|
+
def __lt__(self, rhs):
|
|
54
|
+
"""
|
|
55
|
+
Compare on run # first, then by lumis as a list, then by events in each lumi
|
|
56
|
+
"""
|
|
57
|
+
# check run number
|
|
58
|
+
if self.run != rhs.run:
|
|
59
|
+
return self.run < rhs.run
|
|
60
|
+
# if same run number, check list of lumi sections
|
|
61
|
+
if sorted(self.eventsPerLumi.keys()) != sorted(rhs.eventsPerLumi.keys()):
|
|
62
|
+
return sorted(self.eventsPerLumi.keys()) < sorted(rhs.eventsPerLumi.keys())
|
|
63
|
+
# if same list of lumis, check events in each lumi section
|
|
64
|
+
for lumiNumber in sorted(self.eventsPerLumi):
|
|
65
|
+
if self.eventsPerLumi[lumiNumber] == rhs.eventsPerLumi.get(lumiNumber):
|
|
66
|
+
continue
|
|
67
|
+
else:
|
|
68
|
+
return self.eventsPerLumi[lumiNumber] < rhs.eventsPerLumi.get(lumiNumber)
|
|
69
|
+
# if same run number, same lumi sections list,
|
|
70
|
+
# same events in each lumi section:
|
|
71
|
+
# then the runs are equal and __lt__ should return false
|
|
72
|
+
return False
|
|
73
|
+
|
|
74
|
+
def __le__(self, other):
|
|
75
|
+
return self.__lt__(other) or self.__eq__(other)
|
|
76
|
+
|
|
77
|
+
def __gt__(self, other):
|
|
78
|
+
return not self.__le__(other)
|
|
79
|
+
|
|
80
|
+
def __ge__(self, other):
|
|
81
|
+
return not self.__lt__(other)
|
|
82
|
+
|
|
83
|
+
def extend(self, items):
|
|
84
|
+
"""
|
|
85
|
+
Redirect to the function that already does this
|
|
86
|
+
"""
|
|
87
|
+
self.extendLumis(items)
|
|
88
|
+
return
|
|
89
|
+
|
|
90
|
+
def __add__(self, rhs):
|
|
91
|
+
"""
|
|
92
|
+
Combine two runs
|
|
93
|
+
"""
|
|
94
|
+
if self.run != rhs.run:
|
|
95
|
+
msg = "Adding together two different runs"
|
|
96
|
+
msg += "Run %s does not equal Run %s" % (self.run, rhs.run)
|
|
97
|
+
raise RuntimeError(msg)
|
|
98
|
+
|
|
99
|
+
for lumi, events in viewitems(rhs.eventsPerLumi):
|
|
100
|
+
if lumi not in self.eventsPerLumi or not self.eventsPerLumi[lumi]: # Either doesn't exist, 0, or None
|
|
101
|
+
self.eventsPerLumi[lumi] = events
|
|
102
|
+
else:
|
|
103
|
+
self.eventsPerLumi[lumi] += events
|
|
104
|
+
return self
|
|
105
|
+
|
|
106
|
+
def __iter__(self):
|
|
107
|
+
return self.eventsPerLumi.__iter__()
|
|
108
|
+
|
|
109
|
+
def __next__(self):
|
|
110
|
+
"""
|
|
111
|
+
__next__ no longer needed
|
|
112
|
+
"""
|
|
113
|
+
raise NotImplementedError
|
|
114
|
+
|
|
115
|
+
def __len__(self):
|
|
116
|
+
"""
|
|
117
|
+
Number of lumis
|
|
118
|
+
"""
|
|
119
|
+
return self.eventsPerLumi.__len__()
|
|
120
|
+
|
|
121
|
+
def __getitem__(self, key):
|
|
122
|
+
"""
|
|
123
|
+
Get the nth lumi from the list (no event count)
|
|
124
|
+
"""
|
|
125
|
+
return sorted(self.eventsPerLumi.keys()).__getitem__(key)
|
|
126
|
+
|
|
127
|
+
def __setitem__(self, key, lumi):
|
|
128
|
+
"""
|
|
129
|
+
Replace the nth lumi from the list (no event count)
|
|
130
|
+
"""
|
|
131
|
+
try:
|
|
132
|
+
oldLumi = sorted(self.eventsPerLumi.keys())[key] # Extract the lumi from the sorted list
|
|
133
|
+
del self.eventsPerLumi[oldLumi] # Delete it and add the new one
|
|
134
|
+
except IndexError:
|
|
135
|
+
pass
|
|
136
|
+
self.appendLumi(lumi)
|
|
137
|
+
|
|
138
|
+
def __delitem__(self, key):
|
|
139
|
+
try:
|
|
140
|
+
oldLumi = sorted(self.eventsPerLumi.keys())[key] # Extract the lumi from the sorted list
|
|
141
|
+
del self.eventsPerLumi[oldLumi] # Delete it
|
|
142
|
+
except IndexError:
|
|
143
|
+
pass
|
|
144
|
+
|
|
145
|
+
def __hash__(self):
|
|
146
|
+
"""
|
|
147
|
+
Calculate the value of the hash
|
|
148
|
+
|
|
149
|
+
NOTE: Python2 maxint is:
|
|
150
|
+
> python -c 'import sys; print(sys.maxint)'
|
|
151
|
+
9223372036854775807
|
|
152
|
+
so we cannot use the full range of the hexadecimal hash code because
|
|
153
|
+
it could cause an integer overflow. This is the maximum slice/value we
|
|
154
|
+
can safely use:
|
|
155
|
+
> int(15 * "f", base=16)
|
|
156
|
+
1152921504606846975
|
|
157
|
+
"""
|
|
158
|
+
if isinstance(self.run, (newstr, newbytes)):
|
|
159
|
+
value = encodeUnicodeToBytesConditional(self.run, condition=PY3)
|
|
160
|
+
else:
|
|
161
|
+
value = encodeUnicodeToBytesConditional(str(self.run), condition=PY3)
|
|
162
|
+
hashValue = hashlib.sha1(value)
|
|
163
|
+
# Generate immutable sorted list of lumis
|
|
164
|
+
frozenEvents = str(sorted(listitems(self.eventsPerLumi), key=lambda x: x[0]))
|
|
165
|
+
hashValue.update(encodeUnicodeToBytes(frozenEvents))
|
|
166
|
+
return int(hashValue.hexdigest()[:15], 16)
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def lumis(self):
|
|
170
|
+
"""
|
|
171
|
+
Property that makes existing uses of myRun.lumis function by returning a list
|
|
172
|
+
"""
|
|
173
|
+
return sorted(self.eventsPerLumi.keys())
|
|
174
|
+
|
|
175
|
+
@lumis.setter
|
|
176
|
+
def lumis(self, lumiList):
|
|
177
|
+
"""
|
|
178
|
+
Setter to allow for replacement of the lumis with a list or list of tuples
|
|
179
|
+
"""
|
|
180
|
+
self.eventsPerLumi = {} # Remove existing dictionary
|
|
181
|
+
for lumi in lumiList:
|
|
182
|
+
if isinstance(lumi, (list, tuple)):
|
|
183
|
+
self.eventsPerLumi[lumi[0]] = lumi[1]
|
|
184
|
+
else:
|
|
185
|
+
self.eventsPerLumi[lumi] = None
|
|
186
|
+
|
|
187
|
+
def extendLumis(self, lumiList):
|
|
188
|
+
"""
|
|
189
|
+
Method to replace myRun.lumis.extend() which does not work with the property
|
|
190
|
+
"""
|
|
191
|
+
for lumi in lumiList:
|
|
192
|
+
if not isinstance(lumi, (list, tuple)): # comma separated lumi numbers
|
|
193
|
+
self.eventsPerLumi[lumi] = None
|
|
194
|
+
else:
|
|
195
|
+
if isinstance(lumi, list) and not isinstance(lumi[0], tuple): # then it's a plain list
|
|
196
|
+
for l in lumi:
|
|
197
|
+
self.eventsPerLumi[l] = None
|
|
198
|
+
else:
|
|
199
|
+
if isinstance(lumi, tuple): # it's an unpacked list of tuples
|
|
200
|
+
lumi = [(lumi)]
|
|
201
|
+
# it's a list/tuple of tuples
|
|
202
|
+
for tp in lumi:
|
|
203
|
+
if tp[0] in self.eventsPerLumi and self.eventsPerLumi[tp[0]]:
|
|
204
|
+
self.eventsPerLumi[tp[0]] += tp[1] # Already exists, add events
|
|
205
|
+
else: # Doesn't exist or is 0 or None
|
|
206
|
+
self.eventsPerLumi[tp[0]] = tp[1]
|
|
207
|
+
|
|
208
|
+
def appendLumi(self, lumi):
|
|
209
|
+
"""
|
|
210
|
+
Method to replace myRun.lumis.append() which does not work with the property
|
|
211
|
+
"""
|
|
212
|
+
if isinstance(lumi, (list, tuple)) and self.eventsPerLumi[lumi[0]]: # Already exists, add events
|
|
213
|
+
self.eventsPerLumi[lumi[0]] += lumi[1]
|
|
214
|
+
elif isinstance(lumi, (list, tuple)): # Doesn't exist or is 0 or None
|
|
215
|
+
self.eventsPerLumi[lumi[0]] = lumi[1]
|
|
216
|
+
else: # Just given lumis, not events
|
|
217
|
+
if lumi not in self.eventsPerLumi: # Don't overwrite existing events
|
|
218
|
+
self.eventsPerLumi[lumi] = None
|
|
219
|
+
|
|
220
|
+
def getEventsByLumi(self, lumi):
|
|
221
|
+
"""
|
|
222
|
+
getter to select event counts by given lumi
|
|
223
|
+
"""
|
|
224
|
+
return self.eventsPerLumi.get(lumi)
|
|
225
|
+
|
|
226
|
+
def json(self):
|
|
227
|
+
"""
|
|
228
|
+
_json_
|
|
229
|
+
|
|
230
|
+
Convert to JSON friendly format. Include some information for the
|
|
231
|
+
thunker so that we can convert back.
|
|
232
|
+
"""
|
|
233
|
+
return {"Run": self.run, "Lumis": self.eventsPerLumi,
|
|
234
|
+
"thunker_encoded_json": True, "type": "WMCore.DataStructs.Run.Run"}
|
|
235
|
+
|
|
236
|
+
def __to_json__(self, thunker=None):
|
|
237
|
+
"""
|
|
238
|
+
__to_json__
|
|
239
|
+
|
|
240
|
+
This is the standard way we JSONize other objects.
|
|
241
|
+
Included here so we have a uniform method.
|
|
242
|
+
"""
|
|
243
|
+
return self.json()
|
|
244
|
+
|
|
245
|
+
def __from_json__(self, jsondata, thunker):
|
|
246
|
+
"""
|
|
247
|
+
__from_json__
|
|
248
|
+
|
|
249
|
+
Convert JSON data back into a Run object with integer lumi numbers
|
|
250
|
+
"""
|
|
251
|
+
self.run = jsondata["Run"]
|
|
252
|
+
self.eventsPerLumi = {}
|
|
253
|
+
for lumi, events in viewitems(jsondata["Lumis"]):
|
|
254
|
+
self.eventsPerLumi[int(lumi)] = events # Make the keys integers again
|
|
255
|
+
|
|
256
|
+
return self
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
_Subscription_
|
|
4
|
+
|
|
5
|
+
workflow + fileset = subscription
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from builtins import range
|
|
9
|
+
import copy
|
|
10
|
+
|
|
11
|
+
from WMCore.DataStructs.Pickleable import Pickleable
|
|
12
|
+
from WMCore.DataStructs.Fileset import Fileset
|
|
13
|
+
|
|
14
|
+
class Subscription(Pickleable, dict):
|
|
15
|
+
def __init__(self, fileset = None, workflow = None,
|
|
16
|
+
split_algo = "FileBased", type = "Processing"):
|
|
17
|
+
if fileset == None:
|
|
18
|
+
fileset = Fileset()
|
|
19
|
+
|
|
20
|
+
self.setdefault('fileset', fileset)
|
|
21
|
+
self.setdefault('workflow', workflow)
|
|
22
|
+
self.setdefault('type', type)
|
|
23
|
+
|
|
24
|
+
self.setdefault('split_algo', split_algo)
|
|
25
|
+
|
|
26
|
+
self.available = Fileset(name=fileset.name,
|
|
27
|
+
files = fileset.getFiles())
|
|
28
|
+
|
|
29
|
+
self.acquired = Fileset(name='acquired')
|
|
30
|
+
self.completed = Fileset(name='completed')
|
|
31
|
+
self.failed = Fileset(name='failed')
|
|
32
|
+
|
|
33
|
+
def name(self):
|
|
34
|
+
return self.getWorkflow().name.replace(' ', '') + '_' + \
|
|
35
|
+
self.getFileset().name.replace(' ', '')
|
|
36
|
+
|
|
37
|
+
def getWorkflow(self):
|
|
38
|
+
return self["workflow"]
|
|
39
|
+
|
|
40
|
+
def workflowName(self):
|
|
41
|
+
if self["workflow"] == None:
|
|
42
|
+
return "Unknown"
|
|
43
|
+
return self["workflow"].name
|
|
44
|
+
|
|
45
|
+
def workflowType(self):
|
|
46
|
+
if self["workflow"] == None:
|
|
47
|
+
return "Unknown"
|
|
48
|
+
return self["workflow"].wfType
|
|
49
|
+
|
|
50
|
+
def taskName(self):
|
|
51
|
+
if self['workflow'] == None:
|
|
52
|
+
return "Unknown"
|
|
53
|
+
return self['workflow'].task
|
|
54
|
+
|
|
55
|
+
def owner(self):
|
|
56
|
+
if self['workflow'] == None:
|
|
57
|
+
return 'Unknown'
|
|
58
|
+
return self['workflow'].owner
|
|
59
|
+
|
|
60
|
+
def getFileset(self):
|
|
61
|
+
return self['fileset']
|
|
62
|
+
|
|
63
|
+
def acquireFiles(self, files = [], size=1):
|
|
64
|
+
"""
|
|
65
|
+
Return the files acquired
|
|
66
|
+
"""
|
|
67
|
+
self.acquired.commit()
|
|
68
|
+
self.available.commit()
|
|
69
|
+
self.failed.commit()
|
|
70
|
+
self.completed.commit()
|
|
71
|
+
retval = []
|
|
72
|
+
if len(files):
|
|
73
|
+
for i in files:
|
|
74
|
+
# Check each set, instead of elif, just in case something has
|
|
75
|
+
# got out of synch
|
|
76
|
+
if i in self.available.files:
|
|
77
|
+
self.available.files.remove(i)
|
|
78
|
+
if i in self.failed.files:
|
|
79
|
+
self.failed.files.remove(i)
|
|
80
|
+
if i in self.completed.files:
|
|
81
|
+
self.completed.files.remove(i)
|
|
82
|
+
self.acquired.addFile(i)
|
|
83
|
+
else:
|
|
84
|
+
if len(self.available.files) < size or size == 0:
|
|
85
|
+
size = len(self.available.files)
|
|
86
|
+
for i in range(size):
|
|
87
|
+
self.acquired.addFile(self.available.files.pop())
|
|
88
|
+
|
|
89
|
+
return self.acquired.listNewFiles()
|
|
90
|
+
|
|
91
|
+
def completeFiles(self, files):
|
|
92
|
+
"""
|
|
93
|
+
Return the number of files complete
|
|
94
|
+
"""
|
|
95
|
+
self.acquired.commit()
|
|
96
|
+
self.available.commit()
|
|
97
|
+
self.failed.commit()
|
|
98
|
+
self.completed.commit()
|
|
99
|
+
for i in files:
|
|
100
|
+
# Check each set, instead of elif, just in case something has
|
|
101
|
+
# got out of synch
|
|
102
|
+
if i in self.available.files:
|
|
103
|
+
self.available.files.remove(i)
|
|
104
|
+
if i in self.failed.files:
|
|
105
|
+
self.failed.files.remove(i)
|
|
106
|
+
if i in self.acquired.files:
|
|
107
|
+
self.acquired.files.remove(i)
|
|
108
|
+
self.completed.addFile(i)
|
|
109
|
+
|
|
110
|
+
def failFiles(self, files):
|
|
111
|
+
"""
|
|
112
|
+
Return the number of files failed
|
|
113
|
+
"""
|
|
114
|
+
self.acquired.commit()
|
|
115
|
+
self.available.commit()
|
|
116
|
+
self.failed.commit()
|
|
117
|
+
self.completed.commit()
|
|
118
|
+
for i in files:
|
|
119
|
+
# Check each set, instead of elif, just in case something has
|
|
120
|
+
# got out of synch
|
|
121
|
+
if i in self.available.files:
|
|
122
|
+
self.available.files.remove(i)
|
|
123
|
+
if i in self.completed.files:
|
|
124
|
+
self.completed.files.remove(i)
|
|
125
|
+
if i in self.acquired.files:
|
|
126
|
+
self.acquired.files.remove(i)
|
|
127
|
+
self.failed.addFile(i)
|
|
128
|
+
|
|
129
|
+
def filesOfStatus(self, status=None, doingJobSplitting = False):
|
|
130
|
+
"""
|
|
131
|
+
_filesOfStatus_
|
|
132
|
+
|
|
133
|
+
Return a Set of File objects that are associated with the subscription
|
|
134
|
+
and have a particular status.
|
|
135
|
+
"""
|
|
136
|
+
status = status.title()
|
|
137
|
+
if status == 'Available':
|
|
138
|
+
return self.available.getFiles(type='set') - \
|
|
139
|
+
(self.acquiredFiles() | self.completedFiles() | self.failedFiles())
|
|
140
|
+
elif status == 'Acquired':
|
|
141
|
+
return self.acquired.getFiles(type='set')
|
|
142
|
+
elif status == 'Completed':
|
|
143
|
+
return self.completed.getFiles(type='set')
|
|
144
|
+
elif status == 'Failed':
|
|
145
|
+
return self.failed.getFiles(type='set')
|
|
146
|
+
|
|
147
|
+
def availableFiles(self, limit = None, doingJobSplitting = False):
|
|
148
|
+
"""
|
|
149
|
+
_availableFiles_
|
|
150
|
+
|
|
151
|
+
Return a Set of files that are available for processing
|
|
152
|
+
(e.g. not already in use)
|
|
153
|
+
"""
|
|
154
|
+
if limit:
|
|
155
|
+
return list(self.filesOfStatus(status = "Available", doingJobSplitting = doingJobSplitting))[:limit]
|
|
156
|
+
else:
|
|
157
|
+
return self.filesOfStatus(status = "Available", doingJobSplitting = doingJobSplitting)
|
|
158
|
+
|
|
159
|
+
def acquiredFiles(self):
|
|
160
|
+
"""
|
|
161
|
+
Set of files marked as acquired.
|
|
162
|
+
"""
|
|
163
|
+
return self.filesOfStatus(status = "Acquired")
|
|
164
|
+
|
|
165
|
+
def completedFiles(self):
|
|
166
|
+
"""
|
|
167
|
+
Set of files marked as completed.
|
|
168
|
+
"""
|
|
169
|
+
return self.filesOfStatus(status = "Completed")
|
|
170
|
+
|
|
171
|
+
def failedFiles(self):
|
|
172
|
+
"""
|
|
173
|
+
Set of files marked as failed.
|
|
174
|
+
"""
|
|
175
|
+
return self.filesOfStatus(status = "Failed")
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
_WMObject_
|
|
4
|
+
|
|
5
|
+
Helper class that other objects should inherit from
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
from builtins import object
|
|
9
|
+
__all__ = []
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class WMObject(object):
|
|
15
|
+
"""
|
|
16
|
+
Helper class that other objects should inherit from
|
|
17
|
+
"""
|
|
18
|
+
def __init__(self, config = {}):
|
|
19
|
+
#Config is a WMCore.Configuration
|
|
20
|
+
self.config = config
|
|
21
|
+
|
|
22
|
+
def makelist(self, thelist):
|
|
23
|
+
"""
|
|
24
|
+
Simple method to ensure thelist is a list
|
|
25
|
+
"""
|
|
26
|
+
if isinstance(thelist, set):
|
|
27
|
+
thelist = list(thelist)
|
|
28
|
+
elif not isinstance(thelist, list):
|
|
29
|
+
thelist = [thelist]
|
|
30
|
+
return thelist
|
|
31
|
+
|
|
32
|
+
def makeset(self, theset):
|
|
33
|
+
"""
|
|
34
|
+
Simple method to ensure theset is a set
|
|
35
|
+
"""
|
|
36
|
+
if not isinstance(theset, set):
|
|
37
|
+
theset = set(self.makelist(theset))
|
|
38
|
+
return theset
|
|
39
|
+
|
|
40
|
+
def flatten(self, list):
|
|
41
|
+
"""
|
|
42
|
+
If a list has only one element return just that element, otherwise
|
|
43
|
+
return the original list
|
|
44
|
+
"""
|
|
45
|
+
if len(list) == 1:
|
|
46
|
+
return list[0]
|
|
47
|
+
return list
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
_WorkUnit_
|
|
4
|
+
|
|
5
|
+
Data object that contains details for a single work unit
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import absolute_import, division, print_function
|
|
10
|
+
|
|
11
|
+
from future.utils import listitems
|
|
12
|
+
|
|
13
|
+
import sys
|
|
14
|
+
import hashlib
|
|
15
|
+
import time
|
|
16
|
+
from functools import total_ordering
|
|
17
|
+
|
|
18
|
+
from Utils.Utilities import encodeUnicodeToBytes
|
|
19
|
+
from WMCore.DataStructs.WMObject import WMObject
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@total_ordering
|
|
23
|
+
class WorkUnit(WMObject, dict):
|
|
24
|
+
"""
|
|
25
|
+
_WorkUnit_
|
|
26
|
+
Data object that contains details for a single work unit
|
|
27
|
+
corresponding to tables workunit and frl_workunit_assoc
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
fieldsToCopy = ['taskid', 'retry_count', 'last_unit_count', 'last_submit_time', 'status', 'firstevent',
|
|
31
|
+
'lastevent', 'fileid']
|
|
32
|
+
fieldsForInfo = fieldsToCopy + ['run_lumi']
|
|
33
|
+
|
|
34
|
+
def __init__(self, taskID=None, retryCount=0, lastUnitCount=None, lastSubmitTime=int(time.time()),
|
|
35
|
+
status=0, firstEvent=1, lastEvent=sys.maxsize, fileid=None, runLumi=None):
|
|
36
|
+
super(WorkUnit, self).__init__(self)
|
|
37
|
+
self.setdefault('taskid', taskID)
|
|
38
|
+
self.setdefault('retry_count', retryCount)
|
|
39
|
+
self.setdefault('last_unit_count', lastUnitCount)
|
|
40
|
+
self.setdefault('last_submit_time', lastSubmitTime)
|
|
41
|
+
self.setdefault('status', status)
|
|
42
|
+
|
|
43
|
+
self.setdefault('firstevent', firstEvent)
|
|
44
|
+
self.setdefault('lastevent', lastEvent)
|
|
45
|
+
self.setdefault('fileid', fileid)
|
|
46
|
+
self.setdefault('run_lumi', runLumi)
|
|
47
|
+
|
|
48
|
+
def __lt__(self, rhs):
|
|
49
|
+
"""
|
|
50
|
+
Compare work units in task id, run, lumi, first event, last event
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
if self['taskid'] != rhs['taskid']:
|
|
54
|
+
return self['taskid'] < rhs['taskid']
|
|
55
|
+
if self['run_lumi'].run != rhs['run_lumi'].run:
|
|
56
|
+
return self['run_lumi'].run < rhs['run_lumi'].run
|
|
57
|
+
if self['run_lumi'].lumis != rhs['run_lumi'].lumis:
|
|
58
|
+
return self['run_lumi'].lumis < rhs['run_lumi'].lumis
|
|
59
|
+
if self['first_event'] != rhs['first_event']:
|
|
60
|
+
return self['first_event'] < rhs['first_event']
|
|
61
|
+
return self['last_event'] < rhs['last_event']
|
|
62
|
+
|
|
63
|
+
def __eq__(self, rhs):
|
|
64
|
+
"""
|
|
65
|
+
Work unit is equal if it has the same task, run, and lumi
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
return (self['taskid'] == rhs['taskid'] and self['run_lumi'].run == self['run_lumi'].run and
|
|
69
|
+
self['run_lumi'].lumis == self['run_lumi'].lumis and self['firstevent'] == rhs['firstevent'] and
|
|
70
|
+
self['lastevent'] == rhs['lastevent'])
|
|
71
|
+
|
|
72
|
+
def __hash__(self):
|
|
73
|
+
"""
|
|
74
|
+
Hash function for this dict.
|
|
75
|
+
"""
|
|
76
|
+
# Generate an immutable sorted string representing this object
|
|
77
|
+
# NOTE: the run object needs to be hashed
|
|
78
|
+
immutableSelf = []
|
|
79
|
+
for keyName in sorted(self):
|
|
80
|
+
if keyName == "run_lumi":
|
|
81
|
+
immutableSelf.append((keyName, hash(self[keyName])))
|
|
82
|
+
else:
|
|
83
|
+
immutableSelf.append((keyName, self[keyName]))
|
|
84
|
+
hashValue = hashlib.sha1(encodeUnicodeToBytes(str(immutableSelf)))
|
|
85
|
+
return int(hashValue.hexdigest()[:15], 16)
|
|
86
|
+
|
|
87
|
+
def json(self, thunker=None):
|
|
88
|
+
"""
|
|
89
|
+
_json_
|
|
90
|
+
|
|
91
|
+
Serialize the object. Only copy select fields and construct one new field.
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
jsonDict = {k: self[k] for k in WorkUnit.fieldsToCopy}
|
|
95
|
+
jsonDict["run_lumi"] = {"run_number": self['run_lumi'].run, "lumis": self['run_lumi'].lumis}
|
|
96
|
+
|
|
97
|
+
return jsonDict
|
|
98
|
+
|
|
99
|
+
def __to_json__(self, thunker=None):
|
|
100
|
+
"""
|
|
101
|
+
__to_json__
|
|
102
|
+
|
|
103
|
+
This is the standard way we jsonize other objects.
|
|
104
|
+
Included here so we have a uniform method.
|
|
105
|
+
"""
|
|
106
|
+
return self.json(thunker)
|
|
107
|
+
|
|
108
|
+
def getInfo(self):
|
|
109
|
+
"""
|
|
110
|
+
Returns: tuple of parameters for the work unit
|
|
111
|
+
"""
|
|
112
|
+
return tuple(self[x] for x in WorkUnit.fieldsForInfo)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
_Workflow_
|
|
4
|
+
|
|
5
|
+
A class that describes some work to be undertaken on some files
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from builtins import str
|
|
9
|
+
from WMCore.DataStructs.Pickleable import Pickleable
|
|
10
|
+
|
|
11
|
+
class Workflow(Pickleable):
|
|
12
|
+
def __init__(self, spec = None, owner = "unknown", dn = "unknown",
|
|
13
|
+
group = "unknown", owner_vogroup = "unknown",
|
|
14
|
+
owner_vorole = "unknown", name = None, task = None,
|
|
15
|
+
wfType = None, priority = None):
|
|
16
|
+
self.spec = spec
|
|
17
|
+
self.name = name
|
|
18
|
+
# person making the request
|
|
19
|
+
self.owner = owner
|
|
20
|
+
self.dn = dn
|
|
21
|
+
self.vogroup = owner_vogroup
|
|
22
|
+
self.vorole = owner_vorole
|
|
23
|
+
self.group = group
|
|
24
|
+
# task is the name of the task within the Workload
|
|
25
|
+
self.task = task
|
|
26
|
+
self.wfType = wfType
|
|
27
|
+
self.outputMap = {}
|
|
28
|
+
self.priority = priority or 0
|
|
29
|
+
|
|
30
|
+
def addOutput(self, outputIdentifier, outputFileset,
|
|
31
|
+
mergedOutputFileset = None):
|
|
32
|
+
"""
|
|
33
|
+
_addOutput_
|
|
34
|
+
|
|
35
|
+
Associate an output of this workflow with a particular fileset.
|
|
36
|
+
"""
|
|
37
|
+
mappingDict = {"output_fileset": outputFileset,
|
|
38
|
+
"merged_output_fileset": mergedOutputFileset}
|
|
39
|
+
|
|
40
|
+
if outputIdentifier in self.outputMap:
|
|
41
|
+
self.outputMap[outputIdentifier].append(mappingDict)
|
|
42
|
+
else:
|
|
43
|
+
self.outputMap[outputIdentifier] = [mappingDict]
|
|
44
|
+
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
def __str__(self):
|
|
48
|
+
"""
|
|
49
|
+
__str__
|
|
50
|
+
|
|
51
|
+
Print out some useful info just because
|
|
52
|
+
this does not inherit from dict.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
d = {'id': self.id, 'spec': self.spec, 'name': self.name,
|
|
56
|
+
'owner': self.owner, 'task': self.task,
|
|
57
|
+
'vogroup': self.vogroup, 'vorole': self.vorole,
|
|
58
|
+
'group': self.group, 'wfType': self.wfType}
|
|
59
|
+
|
|
60
|
+
return str(d)
|