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,198 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
_Core_
|
|
4
|
+
|
|
5
|
+
Core Database APIs
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
from copy import copy
|
|
10
|
+
|
|
11
|
+
from Utils.IteratorTools import grouper
|
|
12
|
+
import WMCore.WMLogging
|
|
13
|
+
from WMCore.DataStructs.WMObject import WMObject
|
|
14
|
+
from WMCore.Database.ResultSet import ResultSet
|
|
15
|
+
|
|
16
|
+
class DBInterface(WMObject):
|
|
17
|
+
"""
|
|
18
|
+
Base class for doing SQL operations using a SQLAlchemy engine, or
|
|
19
|
+
pre-exisitng connection.
|
|
20
|
+
|
|
21
|
+
processData will take a (list of) sql statements and a (list of)
|
|
22
|
+
bind variable dictionaries and run the statements on the DB. If
|
|
23
|
+
necessary it will substitute binds into the sql (MySQL).
|
|
24
|
+
|
|
25
|
+
TODO:
|
|
26
|
+
Add in some suitable exceptions in one or two places
|
|
27
|
+
Test the hell out of it
|
|
28
|
+
Support executemany()
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
logger = None
|
|
32
|
+
engine = None
|
|
33
|
+
|
|
34
|
+
def __init__(self, logger, engine):
|
|
35
|
+
self.logger = logger
|
|
36
|
+
self.logger.info ("Instantiating base WM DBInterface")
|
|
37
|
+
self.engine = engine
|
|
38
|
+
self.maxBindsPerQuery = 500
|
|
39
|
+
|
|
40
|
+
def buildbinds(self, sequence, thename, therest=[{}]):
|
|
41
|
+
"""
|
|
42
|
+
Build a list of binds. Can be used recursively, e.g.:
|
|
43
|
+
buildbinds(file, 'file', buildbinds(pnn, 'location'), {'lumi':123})
|
|
44
|
+
TODO: replace with an appropriate map function
|
|
45
|
+
"""
|
|
46
|
+
binds = []
|
|
47
|
+
for r in sequence:
|
|
48
|
+
for i in self.makelist(therest):
|
|
49
|
+
thebind = copy(i)
|
|
50
|
+
thebind[thename] = r
|
|
51
|
+
binds.append(thebind)
|
|
52
|
+
return binds
|
|
53
|
+
|
|
54
|
+
def executebinds(self, s=None, b=None, connection=None,
|
|
55
|
+
returnCursor=False):
|
|
56
|
+
"""
|
|
57
|
+
_executebinds_
|
|
58
|
+
|
|
59
|
+
returns a list of sqlalchemy.engine.base.ResultProxy objects
|
|
60
|
+
"""
|
|
61
|
+
if b == None:
|
|
62
|
+
resultProxy = connection.execute(s)
|
|
63
|
+
else:
|
|
64
|
+
resultProxy = connection.execute(s, b)
|
|
65
|
+
|
|
66
|
+
if returnCursor:
|
|
67
|
+
return resultProxy
|
|
68
|
+
|
|
69
|
+
result = ResultSet()
|
|
70
|
+
result.add(resultProxy)
|
|
71
|
+
resultProxy.close()
|
|
72
|
+
return result
|
|
73
|
+
|
|
74
|
+
def executemanybinds(self, s=None, b=None, connection=None,
|
|
75
|
+
returnCursor=False):
|
|
76
|
+
"""
|
|
77
|
+
_executemanybinds_
|
|
78
|
+
b is a list of dictionaries for the binds, e.g.:
|
|
79
|
+
|
|
80
|
+
b = [ {'bind1':'value1a', 'bind2': 'value2a'},
|
|
81
|
+
{'bind1':'value1b', 'bind2': 'value2b'} ]
|
|
82
|
+
|
|
83
|
+
see: http://www.gingerandjohn.com/archives/2004/02/26/cx_oracle-executemany-example/
|
|
84
|
+
|
|
85
|
+
Can't executemany() selects - so do each combination of binds here instead.
|
|
86
|
+
This will return a list of sqlalchemy.engine.base.ResultProxy object's
|
|
87
|
+
one for each set of binds.
|
|
88
|
+
|
|
89
|
+
returns a list of sqlalchemy.engine.base.ResultProxy objects
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
s = s.strip()
|
|
93
|
+
if s.lower().endswith('select', 0, 6):
|
|
94
|
+
"""
|
|
95
|
+
Trying to select many
|
|
96
|
+
"""
|
|
97
|
+
if returnCursor:
|
|
98
|
+
result = []
|
|
99
|
+
for bind in b:
|
|
100
|
+
result.append(connection.execute(s, bind))
|
|
101
|
+
else:
|
|
102
|
+
result = ResultSet()
|
|
103
|
+
for bind in b:
|
|
104
|
+
resultproxy = connection.execute(s, bind)
|
|
105
|
+
result.add(resultproxy)
|
|
106
|
+
resultproxy.close()
|
|
107
|
+
|
|
108
|
+
return self.makelist(result)
|
|
109
|
+
|
|
110
|
+
"""
|
|
111
|
+
Now inserting or updating many
|
|
112
|
+
"""
|
|
113
|
+
result = connection.execute(s, b)
|
|
114
|
+
return self.makelist(result)
|
|
115
|
+
|
|
116
|
+
def connection(self):
|
|
117
|
+
"""
|
|
118
|
+
Return a connection to the engine (from the connection pool)
|
|
119
|
+
"""
|
|
120
|
+
return self.engine.connect()
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def processData(self, sqlstmt, binds={}, conn=None,
|
|
124
|
+
transaction=False, returnCursor=False):
|
|
125
|
+
"""
|
|
126
|
+
set conn if you already have an active connection to reuse
|
|
127
|
+
set transaction = True if you already have an active transaction
|
|
128
|
+
|
|
129
|
+
"""
|
|
130
|
+
connection = None
|
|
131
|
+
try:
|
|
132
|
+
if not conn:
|
|
133
|
+
connection = self.connection()
|
|
134
|
+
else:
|
|
135
|
+
connection = conn
|
|
136
|
+
|
|
137
|
+
result = []
|
|
138
|
+
# Can take either a single statement or a list of statements and binds
|
|
139
|
+
sqlstmt = self.makelist(sqlstmt)
|
|
140
|
+
binds = self.makelist(binds)
|
|
141
|
+
if len(sqlstmt) > 0 and (len(binds) == 0 or (binds[0] == {} or binds[0] == None)):
|
|
142
|
+
# Should only be run by create statements
|
|
143
|
+
if not transaction:
|
|
144
|
+
#WMCore.WMLogging.sqldebug("transaction created in DBInterface")
|
|
145
|
+
trans = connection.begin()
|
|
146
|
+
|
|
147
|
+
for i in sqlstmt:
|
|
148
|
+
r = self.executebinds(i, connection=connection,
|
|
149
|
+
returnCursor=returnCursor)
|
|
150
|
+
result.append(r)
|
|
151
|
+
|
|
152
|
+
if not transaction:
|
|
153
|
+
trans.commit()
|
|
154
|
+
elif len(binds) > len(sqlstmt) and len(sqlstmt) == 1:
|
|
155
|
+
#Run single SQL statement for a list of binds - use execute_many()
|
|
156
|
+
if not transaction:
|
|
157
|
+
trans = connection.begin()
|
|
158
|
+
for subBinds in grouper(binds, self.maxBindsPerQuery):
|
|
159
|
+
result.extend(self.executemanybinds(sqlstmt[0], subBinds,
|
|
160
|
+
connection=connection, returnCursor=returnCursor))
|
|
161
|
+
|
|
162
|
+
if not transaction:
|
|
163
|
+
trans.commit()
|
|
164
|
+
elif len(binds) == len(sqlstmt):
|
|
165
|
+
# Run a list of SQL for a list of binds
|
|
166
|
+
if not transaction:
|
|
167
|
+
trans = connection.begin()
|
|
168
|
+
|
|
169
|
+
for i, s in enumerate(sqlstmt):
|
|
170
|
+
b = binds[i]
|
|
171
|
+
|
|
172
|
+
r = self.executebinds(s, b, connection=connection,
|
|
173
|
+
returnCursor=returnCursor)
|
|
174
|
+
result.append(r)
|
|
175
|
+
|
|
176
|
+
if not transaction:
|
|
177
|
+
trans.commit()
|
|
178
|
+
else:
|
|
179
|
+
self.logger.exception(
|
|
180
|
+
"DBInterface.processData Nothing executed, problem with your arguments")
|
|
181
|
+
self.logger.exception(
|
|
182
|
+
"DBInterface.processData SQL = %s" % sqlstmt)
|
|
183
|
+
WMCore.WMLogging.sqldebug('DBInterface.processData sql is %s items long' % len(sqlstmt))
|
|
184
|
+
WMCore.WMLogging.sqldebug('DBInterface.processData binds are %s items long' % len(binds))
|
|
185
|
+
assert_value = False
|
|
186
|
+
if len(binds) == len(sqlstmt):
|
|
187
|
+
assert_value = True
|
|
188
|
+
WMCore.WMLogging.sqldebug('DBInterface.processData are binds and sql same length? : %s' % (assert_value))
|
|
189
|
+
WMCore.WMLogging.sqldebug('sql: %s\n binds: %s\n, connection:%s\n, transaction:%s\n' %
|
|
190
|
+
(sqlstmt, binds, connection, transaction))
|
|
191
|
+
WMCore.WMLogging.sqldebug('type check:\nsql: %s\n binds: %s\n, connection:%s\n, transaction:%s\n' %
|
|
192
|
+
(type(sqlstmt), type(binds), type(connection), type(transaction)))
|
|
193
|
+
raise Exception("""DBInterface.processData Nothing executed, problem with your arguments
|
|
194
|
+
Probably mismatched sizes for sql (%i) and binds (%i)""" % (len(sqlstmt), len(binds)))
|
|
195
|
+
finally:
|
|
196
|
+
if not conn and connection != None:
|
|
197
|
+
connection.close() # Return connection to the pool
|
|
198
|
+
return result
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
_DBCreator_
|
|
5
|
+
|
|
6
|
+
Base class for formatters that create tables.
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from builtins import str
|
|
11
|
+
|
|
12
|
+
from WMCore.Database.DBFormatter import DBFormatter
|
|
13
|
+
from WMCore.WMException import WMException
|
|
14
|
+
from WMCore.WMExceptions import WMEXCEPTION
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class DBCreator(DBFormatter):
|
|
18
|
+
|
|
19
|
+
"""
|
|
20
|
+
_DBCreator_
|
|
21
|
+
|
|
22
|
+
Generic class for creating database tables.
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, logger, dbinterface):
|
|
27
|
+
"""
|
|
28
|
+
_init_
|
|
29
|
+
|
|
30
|
+
Call the constructor of the parent class and create empty dictionaries
|
|
31
|
+
to hold table create statements, constraint statements and insert
|
|
32
|
+
statements.
|
|
33
|
+
"""
|
|
34
|
+
DBFormatter.__init__(self, logger, dbinterface)
|
|
35
|
+
self.create = {}
|
|
36
|
+
self.constraints = {}
|
|
37
|
+
self.inserts = {}
|
|
38
|
+
self.indexes = {}
|
|
39
|
+
|
|
40
|
+
def execute(self, conn = None, transaction = False):
|
|
41
|
+
"""
|
|
42
|
+
_execute_
|
|
43
|
+
|
|
44
|
+
Generic method to create tables and constraints by execute
|
|
45
|
+
sql statements in the create, and constraints dictionaries.
|
|
46
|
+
|
|
47
|
+
Before execution the keys assigned to the tables in the self.create
|
|
48
|
+
dictionary are sorted, to offer the possibilitiy of executing
|
|
49
|
+
table creation in a certain order.
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
# create tables
|
|
53
|
+
for i in sorted(self.create.keys()):
|
|
54
|
+
try:
|
|
55
|
+
self.dbi.processData(self.create[i],
|
|
56
|
+
conn = conn,
|
|
57
|
+
transaction = transaction)
|
|
58
|
+
except Exception as e:
|
|
59
|
+
msg = WMEXCEPTION['WMCORE-2'] + '\n\n' +\
|
|
60
|
+
str(self.create[i]) +'\n\n' +str(e)
|
|
61
|
+
self.logger.debug( msg )
|
|
62
|
+
raise WMException(msg,'WMCORE-2')
|
|
63
|
+
|
|
64
|
+
# create indexes
|
|
65
|
+
for i in self.indexes:
|
|
66
|
+
try:
|
|
67
|
+
self.dbi.processData(self.indexes[i],
|
|
68
|
+
conn = conn,
|
|
69
|
+
transaction = transaction)
|
|
70
|
+
except Exception as e:
|
|
71
|
+
msg = WMEXCEPTION['WMCORE-2'] + '\n\n' +\
|
|
72
|
+
str(self.indexes[i]) +'\n\n' +str(e)
|
|
73
|
+
self.logger.debug( msg )
|
|
74
|
+
raise WMException(msg,'WMCORE-2')
|
|
75
|
+
|
|
76
|
+
# set constraints
|
|
77
|
+
for i in self.constraints:
|
|
78
|
+
try:
|
|
79
|
+
self.dbi.processData(self.constraints[i],
|
|
80
|
+
conn = conn,
|
|
81
|
+
transaction = transaction)
|
|
82
|
+
except Exception as e:
|
|
83
|
+
msg = WMEXCEPTION['WMCORE-2'] + '\n\n' +\
|
|
84
|
+
str(self.constraints[i]) +'\n\n' +str(e)
|
|
85
|
+
self.logger.debug( msg )
|
|
86
|
+
raise WMException(msg,'WMCORE-2')
|
|
87
|
+
|
|
88
|
+
# insert permanent data
|
|
89
|
+
for i in self.inserts:
|
|
90
|
+
try:
|
|
91
|
+
self.dbi.processData(self.inserts[i],
|
|
92
|
+
conn = conn,
|
|
93
|
+
transaction = transaction)
|
|
94
|
+
except Exception as e:
|
|
95
|
+
msg = WMEXCEPTION['WMCORE-2'] + '\n\n' +\
|
|
96
|
+
str(self.inserts[i]) +'\n\n' +str(e)
|
|
97
|
+
self.logger.debug( msg )
|
|
98
|
+
raise WMException(msg,'WMCORE-2')
|
|
99
|
+
|
|
100
|
+
return True
|
|
101
|
+
|
|
102
|
+
def __str__(self):
|
|
103
|
+
"""
|
|
104
|
+
_str_
|
|
105
|
+
|
|
106
|
+
Return a well formatted text representation of the schema held in the
|
|
107
|
+
self.create, self.constraints, self.inserts, self.indexes dictionaries.
|
|
108
|
+
"""
|
|
109
|
+
string = ''
|
|
110
|
+
for i in self.create, self.constraints, self.inserts, self.indexes:
|
|
111
|
+
for j in i:
|
|
112
|
+
string = string + i[j].lstrip() + '\n'
|
|
113
|
+
return string
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from __future__ import division, print_function
|
|
2
|
+
|
|
3
|
+
from builtins import str
|
|
4
|
+
from functools import wraps
|
|
5
|
+
import logging
|
|
6
|
+
import threading
|
|
7
|
+
|
|
8
|
+
### Don't crash the components on the following database exceptions
|
|
9
|
+
# ORA-03113: end-of-file on communication channel
|
|
10
|
+
# ORA-03114: Not Connected to Oracle
|
|
11
|
+
# ORA-03135: connection lost contact
|
|
12
|
+
# ORA-12545: Connect failed because target host or object does not exist
|
|
13
|
+
# ORA-00060: deadlock detected while waiting for resource
|
|
14
|
+
# ORA-01033: ORACLE initialization or shutdown in progress
|
|
15
|
+
# (cx_Oracle.InterfaceError) not connected # same as ORA-03114, in the new SQLAlchemy
|
|
16
|
+
# (cx_Oracle.DatabaseError) ORA-25408: can not safely replay call
|
|
17
|
+
# (cx_Oracle.DatabaseError) ORA-25401: can not continue fetches
|
|
18
|
+
# (cx_Oracle.DatabaseError) DPI-1080: connection was closed by ORA-3113
|
|
19
|
+
# and those two MySQL exceptions
|
|
20
|
+
DB_CONNECTION_ERROR_STR = ["ORA-03113", "ORA-03114", "ORA-03135", "ORA-12545", "ORA-00060", "ORA-01033",
|
|
21
|
+
"MySQL server has gone away", "Lock wait timeout exceeded",
|
|
22
|
+
"(cx_Oracle.InterfaceError) not connected", "ORA-25408", "ORA-25401",
|
|
23
|
+
"DPI-1080: connection was closed by ORA"]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def db_exception_handler(f):
|
|
27
|
+
"""
|
|
28
|
+
:param f: function
|
|
29
|
+
:return: wrapper fuction
|
|
30
|
+
|
|
31
|
+
Only need to handle DB connection problem other db problems which need to rollback the transaction,
|
|
32
|
+
shouldn't be included in this hanldler
|
|
33
|
+
|
|
34
|
+
Warning: This only used, when original function return values are not used, or wrapped around Utils.Timer.timeFunc
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
@wraps(f)
|
|
38
|
+
def wrapper(*args, **kwargs):
|
|
39
|
+
myThread = threading.currentThread()
|
|
40
|
+
if hasattr(myThread, "logdbClient") and myThread.logdbClient is not None:
|
|
41
|
+
myThread.logdbClient.delete("DBConnection_error_handler", "warning", this_thread=True)
|
|
42
|
+
try:
|
|
43
|
+
return f(*args, **kwargs)
|
|
44
|
+
except Exception as ex:
|
|
45
|
+
msg = str(ex)
|
|
46
|
+
for errStr in DB_CONNECTION_ERROR_STR:
|
|
47
|
+
if errStr in msg:
|
|
48
|
+
logging.error("%s: Temp error will try later", msg)
|
|
49
|
+
|
|
50
|
+
if hasattr(myThread, "logdbClient") and myThread.logdbClient is not None:
|
|
51
|
+
myThread.logdbClient.post("DBConnection_error_handler", "warning")
|
|
52
|
+
|
|
53
|
+
# returns tuples of 3 since timeFunc returns (time to spend, result, func.__name__)
|
|
54
|
+
return 0, None, f.__name__
|
|
55
|
+
|
|
56
|
+
# for other case raise the same exception
|
|
57
|
+
raise
|
|
58
|
+
|
|
59
|
+
return wrapper
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#pylint: disable=W0102
|
|
2
|
+
from builtins import object
|
|
3
|
+
import threading
|
|
4
|
+
import sys
|
|
5
|
+
import oracledb
|
|
6
|
+
|
|
7
|
+
# NOTE: We need to ensure SQLAlchemy would be able to find the oracledb python libraries.
|
|
8
|
+
# Further details at: https://cjones-oracle.medium.com/using-python-oracledb-1-0-with-sqlalchemy-pandas-django-and-flask-5d84e910cb19
|
|
9
|
+
oracledb.version = "8.3.0"
|
|
10
|
+
sys.modules["cx_Oracle"] = oracledb
|
|
11
|
+
oracledb.init_oracle_client()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
from sqlalchemy import create_engine
|
|
15
|
+
from sqlalchemy import __version__ as sqlalchemy_version
|
|
16
|
+
from WMCore.Database.Dialects import MySQLDialect
|
|
17
|
+
|
|
18
|
+
class DBFactory(object):
|
|
19
|
+
|
|
20
|
+
# class variable
|
|
21
|
+
_engineMap = {}
|
|
22
|
+
_defaultEngineParams = {"convert_unicode" : True,
|
|
23
|
+
"pool_recycle": 7200}
|
|
24
|
+
|
|
25
|
+
def __init__(self, logger, dburl=None, options={}):
|
|
26
|
+
self.logger = logger
|
|
27
|
+
# get the engine parameter from option
|
|
28
|
+
if 'engine_parameters' in options:
|
|
29
|
+
self._defaultEngineParams.update(options['engine_parameters'])
|
|
30
|
+
del options['engine_parameters']
|
|
31
|
+
|
|
32
|
+
if dburl:
|
|
33
|
+
self.dburl = dburl
|
|
34
|
+
else:
|
|
35
|
+
# NOTE: This will be deprecated.
|
|
36
|
+
#
|
|
37
|
+
# Need to make the dburl here. Possible formats are:
|
|
38
|
+
|
|
39
|
+
# mysql://host/database
|
|
40
|
+
# mysql://username@host/database
|
|
41
|
+
# mysql://username:password@host:port/database
|
|
42
|
+
|
|
43
|
+
# oracle://username:password@tnsName
|
|
44
|
+
# oracle://username:password@host:port/sidname
|
|
45
|
+
|
|
46
|
+
hostjoin = ''
|
|
47
|
+
if 'dialect' in options:
|
|
48
|
+
self.dburl = '%s://' % options['dialect']
|
|
49
|
+
del options['dialect']
|
|
50
|
+
if 'user' in options:
|
|
51
|
+
self.dburl = '%s%s' % (self.dburl, options['user'])
|
|
52
|
+
hostjoin='@'
|
|
53
|
+
del options['user']
|
|
54
|
+
if 'username' in options:
|
|
55
|
+
self.dburl = '%s%s' % (self.dburl, options['username'])
|
|
56
|
+
hostjoin='@'
|
|
57
|
+
del options['username']
|
|
58
|
+
if 'passwd' in options:
|
|
59
|
+
self.dburl = '%s:%s' % (self.dburl, options['passwd'])
|
|
60
|
+
del options['passwd']
|
|
61
|
+
if 'password' in options:
|
|
62
|
+
self.dburl = '%s:%s' % (self.dburl, options['password'])
|
|
63
|
+
del options['password']
|
|
64
|
+
if 'tnsName' in options:
|
|
65
|
+
self.dburl = '%s%s%s' % (self.dburl, hostjoin, options['tnsName'])
|
|
66
|
+
del options['tnsName']
|
|
67
|
+
elif 'host' in options:
|
|
68
|
+
self.dburl = '%s%s%s' % (self.dburl, hostjoin, options['host'])
|
|
69
|
+
del options['host']
|
|
70
|
+
if 'port' in options:
|
|
71
|
+
self.dburl = '%s:%s' % (self.dburl, options['port'])
|
|
72
|
+
del options['port']
|
|
73
|
+
if 'host' in options:
|
|
74
|
+
self.dburl = '%s/%s' % (self.dburl, options['host'])
|
|
75
|
+
del options['host']
|
|
76
|
+
if 'database' in options:
|
|
77
|
+
self.dburl = '%s/%s' % (self.dburl, options['database'])
|
|
78
|
+
del options['database']
|
|
79
|
+
elif 'sid' in options:
|
|
80
|
+
self.dburl = '%s/%s' % (self.dburl, options['sid'])
|
|
81
|
+
del options['sid']
|
|
82
|
+
|
|
83
|
+
if self.dburl.split(':')[0].lower() == "http":
|
|
84
|
+
|
|
85
|
+
self.engine = None
|
|
86
|
+
self.dia = None
|
|
87
|
+
|
|
88
|
+
else:
|
|
89
|
+
self.engine = self._engineMap.setdefault(self.dburl,
|
|
90
|
+
create_engine(self.dburl,
|
|
91
|
+
connect_args=options,
|
|
92
|
+
**self._defaultEngineParams)
|
|
93
|
+
)
|
|
94
|
+
self.dia = self.engine.dialect
|
|
95
|
+
|
|
96
|
+
self.lock = threading.Condition()
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def connect(self):
|
|
100
|
+
self.lock.acquire()
|
|
101
|
+
|
|
102
|
+
if self.engine:
|
|
103
|
+
|
|
104
|
+
self.logger.debug("Using SQLAlchemy v.%s" % sqlalchemy_version)
|
|
105
|
+
|
|
106
|
+
if isinstance(self.dia, MySQLDialect):
|
|
107
|
+
from WMCore.Database.MySQLCore import MySQLInterface as DBInterface
|
|
108
|
+
else:
|
|
109
|
+
from WMCore.Database.DBCore import DBInterface
|
|
110
|
+
# we instantiate within the lock so we can safely return the local instance.
|
|
111
|
+
dbInterface = DBInterface(self.logger, self.engine)
|
|
112
|
+
|
|
113
|
+
else:
|
|
114
|
+
dbInterface = None
|
|
115
|
+
|
|
116
|
+
self.lock.release()
|
|
117
|
+
return dbInterface
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"""
|
|
2
|
+
_DBFormatter_
|
|
3
|
+
|
|
4
|
+
A class to define the standardised formatting of database results.
|
|
5
|
+
Holds a bunch of helper methods to format input and output of sql
|
|
6
|
+
interactions.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from builtins import str, bytes, zip, range
|
|
10
|
+
|
|
11
|
+
import datetime
|
|
12
|
+
import time
|
|
13
|
+
import types
|
|
14
|
+
|
|
15
|
+
from Utils.Utilities import decodeBytesToUnicodeConditional
|
|
16
|
+
from WMCore.DataStructs.WMObject import WMObject
|
|
17
|
+
from Utils.PythonVersion import PY3
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class DBFormatter(WMObject):
|
|
21
|
+
def __init__(self, logger, dbinterface):
|
|
22
|
+
"""
|
|
23
|
+
The class holds a connection to the database in self.dbi. This is a
|
|
24
|
+
DBCore.DBInterface object.
|
|
25
|
+
"""
|
|
26
|
+
self.logger = logger
|
|
27
|
+
self.dbi = dbinterface
|
|
28
|
+
|
|
29
|
+
def truefalse(self, value):
|
|
30
|
+
if value in ('False', 'FALSE', 'n', 'N', 'NO', 'No'):
|
|
31
|
+
value = 0
|
|
32
|
+
return bool(value)
|
|
33
|
+
|
|
34
|
+
def convertdatetime(self, t):
|
|
35
|
+
return int(time.mktime(t.timetuple()))
|
|
36
|
+
|
|
37
|
+
def timestamp(self):
|
|
38
|
+
"""
|
|
39
|
+
generate a timestamp
|
|
40
|
+
"""
|
|
41
|
+
t = datetime.datetime.now()
|
|
42
|
+
return self.convertdatetime(t)
|
|
43
|
+
|
|
44
|
+
def format(self, result):
|
|
45
|
+
"""
|
|
46
|
+
Some standard formatting, put all records into a list.
|
|
47
|
+
Returns a list of lists
|
|
48
|
+
"""
|
|
49
|
+
out = []
|
|
50
|
+
for r in result:
|
|
51
|
+
for i in r.fetchall():
|
|
52
|
+
row = []
|
|
53
|
+
for j in i:
|
|
54
|
+
row.append(j)
|
|
55
|
+
out.append(row)
|
|
56
|
+
r.close()
|
|
57
|
+
return out
|
|
58
|
+
|
|
59
|
+
def formatOne(self, result):
|
|
60
|
+
"""
|
|
61
|
+
Return one record
|
|
62
|
+
"""
|
|
63
|
+
out = []
|
|
64
|
+
for r in result:
|
|
65
|
+
for i in r.fetchone():
|
|
66
|
+
out.append(i)
|
|
67
|
+
return out
|
|
68
|
+
|
|
69
|
+
def formatDict(self, result):
|
|
70
|
+
"""
|
|
71
|
+
Returns an array of dictionaries representing the results
|
|
72
|
+
"""
|
|
73
|
+
dictOut = []
|
|
74
|
+
for r in result:
|
|
75
|
+
descriptions = r.keys
|
|
76
|
+
for i in r.fetchall():
|
|
77
|
+
# WARNING: this can generate errors for some stupid reason
|
|
78
|
+
# in both oracle and mysql.
|
|
79
|
+
entry = {}
|
|
80
|
+
for index in range(0, len(descriptions)):
|
|
81
|
+
# WARNING: Oracle returns table names in CAP!
|
|
82
|
+
if isinstance(descriptions[index], (str, bytes)):
|
|
83
|
+
keyName = decodeBytesToUnicodeConditional(descriptions[index], condition=PY3)
|
|
84
|
+
else:
|
|
85
|
+
keyName = descriptions[index]
|
|
86
|
+
if isinstance(i[index], (str, bytes)):
|
|
87
|
+
entry[keyName.lower()] = decodeBytesToUnicodeConditional(i[index], condition=PY3)
|
|
88
|
+
else:
|
|
89
|
+
entry[keyName.lower()] = i[index]
|
|
90
|
+
|
|
91
|
+
dictOut.append(entry)
|
|
92
|
+
|
|
93
|
+
r.close()
|
|
94
|
+
|
|
95
|
+
return dictOut
|
|
96
|
+
|
|
97
|
+
def formatList(self, result):
|
|
98
|
+
"""
|
|
99
|
+
Returns a flat array with the results.
|
|
100
|
+
Ideally used for single column queries
|
|
101
|
+
"""
|
|
102
|
+
listOut = []
|
|
103
|
+
for r in result:
|
|
104
|
+
descriptions = r.keys
|
|
105
|
+
for i in r.fetchall():
|
|
106
|
+
for index in range(0, len(descriptions)):
|
|
107
|
+
if isinstance(i[index], (str, bytes)):
|
|
108
|
+
listOut.append(decodeBytesToUnicodeConditional(i[index], condition=PY3))
|
|
109
|
+
else:
|
|
110
|
+
listOut.append(i[index])
|
|
111
|
+
r.close()
|
|
112
|
+
return listOut
|
|
113
|
+
|
|
114
|
+
def formatOneDict(self, result):
|
|
115
|
+
"""
|
|
116
|
+
Return a dictionary representing the first record
|
|
117
|
+
"""
|
|
118
|
+
if (len(result) == 0):
|
|
119
|
+
return {}
|
|
120
|
+
|
|
121
|
+
r = result[0]
|
|
122
|
+
description = [str(x).lower() for x in r.keys]
|
|
123
|
+
if len(r.data) < 1:
|
|
124
|
+
return {}
|
|
125
|
+
|
|
126
|
+
return dict(list(zip(description, r.fetchone())))
|
|
127
|
+
|
|
128
|
+
def formatCursor(self, cursor, size=10):
|
|
129
|
+
"""
|
|
130
|
+
Fetch the driver cursor directly.
|
|
131
|
+
Tested only with cx_Oracle.
|
|
132
|
+
Cursor must be already executed.
|
|
133
|
+
Use fetchmany(size = default arraysize = 50)
|
|
134
|
+
|
|
135
|
+
"""
|
|
136
|
+
if isinstance(cursor.keys, types.MethodType):
|
|
137
|
+
keys = [x.lower() for x in cursor.keys()] # warning: do not modernize this line.
|
|
138
|
+
else:
|
|
139
|
+
keys = [x.lower() for x in cursor.keys]
|
|
140
|
+
result = []
|
|
141
|
+
while True:
|
|
142
|
+
if not cursor.closed:
|
|
143
|
+
rows = cursor.fetchmany(size=size)
|
|
144
|
+
if not rows:
|
|
145
|
+
cursor.close()
|
|
146
|
+
break
|
|
147
|
+
for r in rows:
|
|
148
|
+
result.append(dict(list(zip(keys, r))))
|
|
149
|
+
else:
|
|
150
|
+
break
|
|
151
|
+
if not cursor.closed:
|
|
152
|
+
cursor.close()
|
|
153
|
+
return result
|
|
154
|
+
|
|
155
|
+
def getBinds(self, **kwargs):
|
|
156
|
+
binds = {}
|
|
157
|
+
for i in kwargs:
|
|
158
|
+
binds = self.dbi.buildbinds(self.dbi.makelist(kwargs[i]), i, binds)
|
|
159
|
+
return binds
|
|
160
|
+
|
|
161
|
+
def execute(self, conn=None, transaction=False, returnCursor=False):
|
|
162
|
+
"""
|
|
163
|
+
A simple select with no binds/arguments is the default
|
|
164
|
+
"""
|
|
165
|
+
result = self.dbi.processData(self.sql, self.getBinds(),
|
|
166
|
+
conn=conn, transaction=transaction,
|
|
167
|
+
returnCursor=returnCursor)
|
|
168
|
+
return self.format(result)
|
|
169
|
+
|
|
170
|
+
def executeOne(self, conn=None, transaction=False, returnCursor=False):
|
|
171
|
+
"""
|
|
172
|
+
A simple select with no binds/arguments is the default
|
|
173
|
+
"""
|
|
174
|
+
result = self.dbi.processData(self.sql, self.getBinds(),
|
|
175
|
+
conn=conn, transaction=transaction,
|
|
176
|
+
returnCursor=returnCursor)
|
|
177
|
+
return self.formatOne(result)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
"""
|
|
3
|
+
sqlalchemy breaks this because they reorganized things. Fail.
|
|
4
|
+
see: http://www.mail-archive.com/sqlalchemy@googlegroups.com/msg18392.html
|
|
5
|
+
-AMM 6/15/10
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from sqlalchemy.databases.mysql import MySQLDialect
|
|
10
|
+
from sqlalchemy.databases.oracle import OracleDialect
|
|
11
|
+
except:
|
|
12
|
+
from sqlalchemy.dialects.mysql.base import MySQLDialect
|
|
13
|
+
from sqlalchemy.dialects.oracle.base import OracleDialect
|