rucio 35.7.0__py3-none-any.whl → 37.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rucio might be problematic. Click here for more details.
- rucio/alembicrevision.py +1 -1
- rucio/{daemons/c3po/collectors → cli}/__init__.py +1 -0
- rucio/cli/account.py +216 -0
- rucio-35.7.0.data/scripts/rucio → rucio/cli/bin_legacy/rucio.py +769 -486
- rucio-35.7.0.data/scripts/rucio-admin → rucio/cli/bin_legacy/rucio_admin.py +476 -423
- rucio/cli/command.py +272 -0
- rucio/cli/config.py +72 -0
- rucio/cli/did.py +191 -0
- rucio/cli/download.py +128 -0
- rucio/cli/lifetime_exception.py +33 -0
- rucio/cli/replica.py +162 -0
- rucio/cli/rse.py +293 -0
- rucio/cli/rule.py +158 -0
- rucio/cli/scope.py +40 -0
- rucio/cli/subscription.py +73 -0
- rucio/cli/upload.py +60 -0
- rucio/cli/utils.py +226 -0
- rucio/client/accountclient.py +0 -1
- rucio/client/baseclient.py +33 -24
- rucio/client/client.py +45 -1
- rucio/client/didclient.py +5 -3
- rucio/client/downloadclient.py +6 -8
- rucio/client/replicaclient.py +0 -2
- rucio/client/richclient.py +317 -0
- rucio/client/rseclient.py +4 -4
- rucio/client/uploadclient.py +26 -12
- rucio/common/bittorrent.py +234 -0
- rucio/common/cache.py +66 -29
- rucio/common/checksum.py +168 -0
- rucio/common/client.py +122 -0
- rucio/common/config.py +22 -35
- rucio/common/constants.py +61 -3
- rucio/common/didtype.py +72 -24
- rucio/common/dumper/__init__.py +45 -38
- rucio/common/dumper/consistency.py +75 -30
- rucio/common/dumper/data_models.py +63 -19
- rucio/common/dumper/path_parsing.py +19 -8
- rucio/common/exception.py +65 -8
- rucio/common/extra.py +5 -10
- rucio/common/logging.py +13 -13
- rucio/common/pcache.py +8 -7
- rucio/common/plugins.py +59 -27
- rucio/common/policy.py +12 -3
- rucio/common/schema/__init__.py +84 -34
- rucio/common/schema/generic.py +0 -17
- rucio/common/schema/generic_multi_vo.py +0 -17
- rucio/common/test_rucio_server.py +12 -6
- rucio/common/types.py +132 -52
- rucio/common/utils.py +93 -643
- rucio/core/account_limit.py +14 -12
- rucio/core/authentication.py +2 -2
- rucio/core/config.py +23 -42
- rucio/core/credential.py +14 -15
- rucio/core/did.py +5 -1
- rucio/core/did_meta_plugins/elasticsearch_meta.py +407 -0
- rucio/core/did_meta_plugins/filter_engine.py +62 -3
- rucio/core/did_meta_plugins/json_meta.py +2 -2
- rucio/core/did_meta_plugins/mongo_meta.py +43 -30
- rucio/core/did_meta_plugins/postgres_meta.py +75 -39
- rucio/core/identity.py +6 -5
- rucio/core/importer.py +4 -3
- rucio/core/lifetime_exception.py +2 -2
- rucio/core/lock.py +8 -7
- rucio/core/message.py +6 -0
- rucio/core/monitor.py +30 -29
- rucio/core/naming_convention.py +2 -2
- rucio/core/nongrid_trace.py +2 -2
- rucio/core/oidc.py +11 -9
- rucio/core/permission/__init__.py +79 -37
- rucio/core/permission/generic.py +1 -7
- rucio/core/permission/generic_multi_vo.py +1 -7
- rucio/core/quarantined_replica.py +4 -3
- rucio/core/replica.py +464 -139
- rucio/core/replica_sorter.py +55 -59
- rucio/core/request.py +34 -32
- rucio/core/rse.py +301 -97
- rucio/core/rse_counter.py +1 -2
- rucio/core/rse_expression_parser.py +7 -7
- rucio/core/rse_selector.py +9 -7
- rucio/core/rule.py +41 -40
- rucio/core/rule_grouping.py +42 -40
- rucio/core/scope.py +5 -4
- rucio/core/subscription.py +26 -28
- rucio/core/topology.py +11 -11
- rucio/core/trace.py +2 -2
- rucio/core/transfer.py +29 -15
- rucio/core/volatile_replica.py +4 -3
- rucio/daemons/atropos/atropos.py +1 -1
- rucio/daemons/auditor/__init__.py +2 -2
- rucio/daemons/auditor/srmdumps.py +6 -6
- rucio/daemons/automatix/automatix.py +32 -21
- rucio/daemons/badreplicas/necromancer.py +2 -2
- rucio/daemons/bb8/nuclei_background_rebalance.py +1 -1
- rucio/daemons/bb8/t2_background_rebalance.py +1 -1
- rucio/daemons/common.py +15 -25
- rucio/daemons/conveyor/finisher.py +2 -2
- rucio/daemons/conveyor/poller.py +18 -28
- rucio/daemons/conveyor/receiver.py +2 -2
- rucio/daemons/conveyor/stager.py +1 -0
- rucio/daemons/conveyor/submitter.py +3 -3
- rucio/daemons/hermes/hermes.py +91 -30
- rucio/daemons/judge/evaluator.py +2 -2
- rucio/daemons/oauthmanager/oauthmanager.py +3 -3
- rucio/daemons/reaper/dark_reaper.py +7 -3
- rucio/daemons/reaper/reaper.py +12 -16
- rucio/daemons/rsedecommissioner/config.py +1 -1
- rucio/daemons/rsedecommissioner/profiles/generic.py +5 -4
- rucio/daemons/rsedecommissioner/profiles/types.py +7 -6
- rucio/daemons/rsedecommissioner/rse_decommissioner.py +1 -1
- rucio/daemons/storage/consistency/actions.py +8 -6
- rucio/daemons/tracer/kronos.py +4 -4
- rucio/db/sqla/constants.py +5 -0
- rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +4 -4
- rucio/db/sqla/migrate_repo/versions/30d5206e9cad_increase_oauthrequest_redirect_msg_.py +37 -0
- rucio/db/sqla/models.py +157 -154
- rucio/db/sqla/session.py +58 -27
- rucio/db/sqla/types.py +2 -2
- rucio/db/sqla/util.py +2 -2
- rucio/gateway/account.py +18 -12
- rucio/gateway/account_limit.py +137 -60
- rucio/gateway/authentication.py +18 -12
- rucio/gateway/config.py +30 -20
- rucio/gateway/credential.py +9 -10
- rucio/gateway/did.py +70 -53
- rucio/gateway/dirac.py +6 -4
- rucio/gateway/exporter.py +3 -2
- rucio/gateway/heartbeat.py +6 -4
- rucio/gateway/identity.py +36 -51
- rucio/gateway/importer.py +3 -2
- rucio/gateway/lifetime_exception.py +3 -2
- rucio/gateway/meta_conventions.py +17 -6
- rucio/gateway/permission.py +4 -1
- rucio/gateway/quarantined_replica.py +3 -2
- rucio/gateway/replica.py +31 -22
- rucio/gateway/request.py +27 -18
- rucio/gateway/rse.py +69 -37
- rucio/gateway/rule.py +46 -26
- rucio/gateway/scope.py +3 -2
- rucio/gateway/subscription.py +14 -11
- rucio/gateway/vo.py +12 -8
- rucio/rse/__init__.py +3 -3
- rucio/rse/protocols/bittorrent.py +11 -1
- rucio/rse/protocols/cache.py +0 -11
- rucio/rse/protocols/dummy.py +0 -11
- rucio/rse/protocols/gfal.py +14 -9
- rucio/rse/protocols/globus.py +1 -1
- rucio/rse/protocols/http_cache.py +1 -1
- rucio/rse/protocols/posix.py +2 -2
- rucio/rse/protocols/protocol.py +84 -317
- rucio/rse/protocols/rclone.py +2 -1
- rucio/rse/protocols/rfio.py +10 -1
- rucio/rse/protocols/ssh.py +2 -1
- rucio/rse/protocols/storm.py +2 -13
- rucio/rse/protocols/webdav.py +74 -30
- rucio/rse/protocols/xrootd.py +2 -1
- rucio/rse/rsemanager.py +170 -53
- rucio/rse/translation.py +260 -0
- rucio/tests/common.py +23 -13
- rucio/tests/common_server.py +26 -9
- rucio/transfertool/bittorrent.py +15 -14
- rucio/transfertool/bittorrent_driver.py +5 -7
- rucio/transfertool/bittorrent_driver_qbittorrent.py +9 -8
- rucio/transfertool/fts3.py +20 -16
- rucio/transfertool/mock.py +2 -3
- rucio/vcsversion.py +4 -4
- rucio/version.py +7 -0
- rucio/web/rest/flaskapi/v1/accounts.py +17 -3
- rucio/web/rest/flaskapi/v1/auth.py +5 -5
- rucio/web/rest/flaskapi/v1/credentials.py +3 -2
- rucio/web/rest/flaskapi/v1/dids.py +21 -15
- rucio/web/rest/flaskapi/v1/identities.py +33 -9
- rucio/web/rest/flaskapi/v1/redirect.py +5 -4
- rucio/web/rest/flaskapi/v1/replicas.py +12 -8
- rucio/web/rest/flaskapi/v1/rses.py +15 -4
- rucio/web/rest/flaskapi/v1/traces.py +56 -19
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/alembic.ini.template +1 -1
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/alembic_offline.ini.template +1 -1
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rucio.cfg.atlas.client.template +3 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rucio.cfg.template +3 -19
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rucio_multi_vo.cfg.template +1 -18
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/requirements.server.txt +97 -68
- rucio-37.0.0.data/scripts/rucio +133 -0
- rucio-37.0.0.data/scripts/rucio-admin +97 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-atropos +2 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-auditor +2 -1
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-automatix +2 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-cache-client +17 -10
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-receiver +1 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-kronos +1 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-minos +2 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-minos-temporary-expiration +2 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-necromancer +2 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-reaper +6 -6
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-transmogrifier +2 -2
- rucio-37.0.0.dist-info/METADATA +92 -0
- {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/RECORD +237 -243
- {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/licenses/AUTHORS.rst +3 -0
- rucio/common/schema/atlas.py +0 -413
- rucio/common/schema/belleii.py +0 -408
- rucio/common/schema/domatpc.py +0 -401
- rucio/common/schema/escape.py +0 -426
- rucio/common/schema/icecube.py +0 -406
- rucio/core/permission/atlas.py +0 -1348
- rucio/core/permission/belleii.py +0 -1077
- rucio/core/permission/escape.py +0 -1078
- rucio/daemons/c3po/algorithms/__init__.py +0 -13
- rucio/daemons/c3po/algorithms/simple.py +0 -134
- rucio/daemons/c3po/algorithms/t2_free_space.py +0 -128
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +0 -130
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +0 -294
- rucio/daemons/c3po/c3po.py +0 -371
- rucio/daemons/c3po/collectors/agis.py +0 -108
- rucio/daemons/c3po/collectors/free_space.py +0 -81
- rucio/daemons/c3po/collectors/jedi_did.py +0 -57
- rucio/daemons/c3po/collectors/mock_did.py +0 -51
- rucio/daemons/c3po/collectors/network_metrics.py +0 -71
- rucio/daemons/c3po/collectors/workload.py +0 -112
- rucio/daemons/c3po/utils/__init__.py +0 -13
- rucio/daemons/c3po/utils/dataset_cache.py +0 -50
- rucio/daemons/c3po/utils/expiring_dataset_cache.py +0 -56
- rucio/daemons/c3po/utils/expiring_list.py +0 -62
- rucio/daemons/c3po/utils/popularity.py +0 -85
- rucio/daemons/c3po/utils/timeseries.py +0 -89
- rucio/rse/protocols/gsiftp.py +0 -92
- rucio-35.7.0.data/scripts/rucio-c3po +0 -85
- rucio-35.7.0.dist-info/METADATA +0 -72
- /rucio/{daemons/c3po → cli/bin_legacy}/__init__.py +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/globus-config.yml.template +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/ldap.cfg.template +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/tools/bootstrap.py +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/tools/merge_rucio_configs.py +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/tools/reset_database.py +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-abacus-account +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-abacus-collection-replica +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-abacus-rse +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-bb8 +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-cache-consumer +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-finisher +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-poller +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-preparer +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-stager +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-submitter +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-throttler +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-dark-reaper +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-dumper +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-follower +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-hermes +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-cleaner +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-evaluator +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-injector +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-repairer +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-oauth-manager +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-replica-recoverer +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-rse-decommissioner +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-storage-consistency-actions +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-undertaker +0 -0
- {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/WHEEL +0 -0
- {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/licenses/LICENSE +0 -0
- {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/top_level.txt +0 -0
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
from json import loads
|
|
16
|
-
from typing import Optional
|
|
17
|
-
|
|
18
|
-
from requests import get
|
|
19
|
-
|
|
20
|
-
from rucio.common.config import config_get
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class MappingCollector:
|
|
24
|
-
"""
|
|
25
|
-
Provides mappings from PanDA / DDM resources to ATLAS sites and back.
|
|
26
|
-
"""
|
|
27
|
-
class _MappingCollector:
|
|
28
|
-
'''
|
|
29
|
-
_MappingCollector
|
|
30
|
-
'''
|
|
31
|
-
|
|
32
|
-
def __init__(self):
|
|
33
|
-
'''
|
|
34
|
-
__init__
|
|
35
|
-
'''
|
|
36
|
-
self._fetch_panda_mapping()
|
|
37
|
-
self._fetch_ddm_mapping()
|
|
38
|
-
|
|
39
|
-
def _fetch_panda_mapping(self) -> None:
|
|
40
|
-
'''
|
|
41
|
-
_fetch_panda_mapping
|
|
42
|
-
'''
|
|
43
|
-
result = get(config_get('c3po-site-mapper', 'panda_url'))
|
|
44
|
-
data = loads(result.text)
|
|
45
|
-
self.panda_to_site = {}
|
|
46
|
-
self.site_to_panda = {}
|
|
47
|
-
|
|
48
|
-
for entry in data:
|
|
49
|
-
self.panda_to_site[entry['panda_resource']] = entry['atlas_site']
|
|
50
|
-
if entry['atlas_site'] not in self.site_to_panda:
|
|
51
|
-
self.site_to_panda[entry['atlas_site']] = []
|
|
52
|
-
self.site_to_panda[entry['atlas_site']].append(entry['panda_resource'])
|
|
53
|
-
|
|
54
|
-
def _fetch_ddm_mapping(self) -> None:
|
|
55
|
-
'''
|
|
56
|
-
_fetch_ddm_mapping
|
|
57
|
-
'''
|
|
58
|
-
result = get(config_get('c3po-site-mapper', 'ddm_url'))
|
|
59
|
-
data = loads(result.text)
|
|
60
|
-
self.site_to_ddm = {}
|
|
61
|
-
self.ddm_to_site = {}
|
|
62
|
-
|
|
63
|
-
for entry in data:
|
|
64
|
-
self.ddm_to_site[entry['name']] = entry['site']
|
|
65
|
-
if entry['site'] not in self.site_to_ddm:
|
|
66
|
-
self.site_to_ddm[entry['site']] = []
|
|
67
|
-
self.site_to_ddm[entry['site']].append(entry['name'])
|
|
68
|
-
|
|
69
|
-
instance = None
|
|
70
|
-
|
|
71
|
-
def __init__(self):
|
|
72
|
-
'''
|
|
73
|
-
__init__
|
|
74
|
-
'''
|
|
75
|
-
if not MappingCollector.instance:
|
|
76
|
-
MappingCollector.instance = MappingCollector._MappingCollector()
|
|
77
|
-
|
|
78
|
-
def ddm_to_site(self, ddm: str) -> Optional[str]:
|
|
79
|
-
'''
|
|
80
|
-
ddm_to_site
|
|
81
|
-
'''
|
|
82
|
-
if ddm not in self.instance.ddm_to_site: # type: ignore
|
|
83
|
-
return None
|
|
84
|
-
return self.instance.ddm_to_site[ddm] # type: ignore
|
|
85
|
-
|
|
86
|
-
def panda_to_site(self, panda: str) -> Optional[str]:
|
|
87
|
-
'''
|
|
88
|
-
panda_to_site
|
|
89
|
-
'''
|
|
90
|
-
if panda not in self.instance.panda_to_site: # type: ignore
|
|
91
|
-
return None
|
|
92
|
-
return self.instance.panda_to_site[panda] # type: ignore
|
|
93
|
-
|
|
94
|
-
def site_to_ddm(self, site: str) -> Optional[str]:
|
|
95
|
-
'''
|
|
96
|
-
site_to_ddm
|
|
97
|
-
'''
|
|
98
|
-
if site not in self.instance.site_to_ddm: # type: ignore
|
|
99
|
-
return None
|
|
100
|
-
return self.instance.site_to_ddm[site] # type: ignore
|
|
101
|
-
|
|
102
|
-
def site_to_panda(self, site: str) -> Optional[str]:
|
|
103
|
-
'''
|
|
104
|
-
site_to_panda
|
|
105
|
-
'''
|
|
106
|
-
if site not in self.instance.site_to_panda: # type: ignore
|
|
107
|
-
return None
|
|
108
|
-
return self.instance.site_to_panda[site] # type: ignore
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
"""
|
|
16
|
-
Collector to get the SRM free and used information for DATADISK RSEs.
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
from typing import TYPE_CHECKING, Optional
|
|
20
|
-
|
|
21
|
-
from sqlalchemy import and_, select
|
|
22
|
-
|
|
23
|
-
from rucio.db.sqla.models import RSEAttrAssociation, RSEUsage
|
|
24
|
-
from rucio.db.sqla.session import read_session
|
|
25
|
-
|
|
26
|
-
if TYPE_CHECKING:
|
|
27
|
-
from sqlalchemy.orm import Session
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class FreeSpaceCollector:
|
|
31
|
-
"""
|
|
32
|
-
Collector to get the SRM free and used information for DATADISK RSEs.
|
|
33
|
-
"""
|
|
34
|
-
class _FreeSpaceCollector:
|
|
35
|
-
"""
|
|
36
|
-
Hidden implementation
|
|
37
|
-
"""
|
|
38
|
-
def __init__(self):
|
|
39
|
-
self.rses = {}
|
|
40
|
-
|
|
41
|
-
@read_session
|
|
42
|
-
def _collect_free_space(
|
|
43
|
-
self,
|
|
44
|
-
*,
|
|
45
|
-
session: Optional["Session"] = None
|
|
46
|
-
) -> None:
|
|
47
|
-
"""
|
|
48
|
-
Retrieve free space from database
|
|
49
|
-
"""
|
|
50
|
-
stmt = select(
|
|
51
|
-
RSEUsage.rse_id,
|
|
52
|
-
RSEUsage.free,
|
|
53
|
-
RSEUsage.used
|
|
54
|
-
).join(
|
|
55
|
-
RSEAttrAssociation,
|
|
56
|
-
RSEAttrAssociation.rse_id == RSEUsage.rse_id
|
|
57
|
-
).where(
|
|
58
|
-
and_(RSEUsage.source == 'storage',
|
|
59
|
-
RSEAttrAssociation.key == 'type',
|
|
60
|
-
RSEAttrAssociation.value == 'DATADISK'),
|
|
61
|
-
)
|
|
62
|
-
for rse_id, free, used in session.execute(stmt).all(): # type: ignore (session could be None)
|
|
63
|
-
self.rses[rse_id] = {'total': used + free, 'used': used, 'free': free}
|
|
64
|
-
|
|
65
|
-
instance = None
|
|
66
|
-
|
|
67
|
-
def __init__(self):
|
|
68
|
-
if not FreeSpaceCollector.instance:
|
|
69
|
-
FreeSpaceCollector.instance = FreeSpaceCollector._FreeSpaceCollector()
|
|
70
|
-
|
|
71
|
-
def collect_free_space(self) -> None:
|
|
72
|
-
"""
|
|
73
|
-
Execute the free space collector
|
|
74
|
-
"""
|
|
75
|
-
self.instance._collect_free_space() # type: ignore
|
|
76
|
-
|
|
77
|
-
def get_rse_space(self) -> dict[str, dict[str, int]]:
|
|
78
|
-
"""
|
|
79
|
-
Return the RSE space
|
|
80
|
-
"""
|
|
81
|
-
return self.instance.rses # type: ignore
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
import logging
|
|
16
|
-
from typing import TYPE_CHECKING, Optional
|
|
17
|
-
|
|
18
|
-
from rucio.db.sqla.session import read_session
|
|
19
|
-
|
|
20
|
-
if TYPE_CHECKING:
|
|
21
|
-
from queue import Queue
|
|
22
|
-
|
|
23
|
-
from sqlalchemy.orm import Session
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class JediDIDCollector:
|
|
27
|
-
def __init__(self, queue: "Queue"):
|
|
28
|
-
self.queue = queue
|
|
29
|
-
self.max_tid = 0
|
|
30
|
-
|
|
31
|
-
@read_session
|
|
32
|
-
def get_dids(
|
|
33
|
-
self,
|
|
34
|
-
*,
|
|
35
|
-
session: Optional["Session"] = None
|
|
36
|
-
) -> None:
|
|
37
|
-
query = """select t.jeditaskid, t.username, t.status, d.datasetname from ATLAS_PANDA.JEDI_TASKS t
|
|
38
|
-
inner join ATLAS_PANDA.JEDI_DATASETS d
|
|
39
|
-
on t.jeditaskid = d.jeditaskid
|
|
40
|
-
where t.creationdate > SYS_EXTRACT_UTC(systimestamp) - 5/(24*60) and t.tasktype = 'anal' and t.prodsourcelabel = 'user'
|
|
41
|
-
and d.type = 'input'
|
|
42
|
-
order by d.jeditaskid asc"""
|
|
43
|
-
|
|
44
|
-
tasks = session.execute(query) # type: ignore
|
|
45
|
-
|
|
46
|
-
for t in tasks.fetchall():
|
|
47
|
-
status = t[2]
|
|
48
|
-
if status == 'running':
|
|
49
|
-
continue
|
|
50
|
-
tid = t[0]
|
|
51
|
-
if tid < self.max_tid:
|
|
52
|
-
continue
|
|
53
|
-
|
|
54
|
-
logging.debug("Received task: " + str(t))
|
|
55
|
-
did = t[3].split(':')
|
|
56
|
-
self.queue.put((did[0], did[1]))
|
|
57
|
-
self.max_tid = tid
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
"""
|
|
16
|
-
Mock DID collector
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
from secrets import choice
|
|
20
|
-
from typing import TYPE_CHECKING
|
|
21
|
-
|
|
22
|
-
if TYPE_CHECKING:
|
|
23
|
-
from multiprocessing import Queue
|
|
24
|
-
|
|
25
|
-
from _typeshed import FileDescriptorOrPath
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class MockDIDCollector:
|
|
29
|
-
"""
|
|
30
|
-
Simple collector that reads dids from a file. Used to
|
|
31
|
-
test the interface.
|
|
32
|
-
"""
|
|
33
|
-
def __init__(self, queue: "Queue"):
|
|
34
|
-
self._queue = queue
|
|
35
|
-
self._read_file('/opt/rucio/etc/dids_mc15_13TeV.csv')
|
|
36
|
-
|
|
37
|
-
def _read_file(self, infile: "FileDescriptorOrPath") -> None:
|
|
38
|
-
dids = []
|
|
39
|
-
with open(infile, 'r') as f:
|
|
40
|
-
f.readline()
|
|
41
|
-
for line in f:
|
|
42
|
-
items = line.strip().split('\t')
|
|
43
|
-
scope = items[0]
|
|
44
|
-
name = items[1]
|
|
45
|
-
dids.append((scope, name))
|
|
46
|
-
|
|
47
|
-
self._dids = tuple(dids)
|
|
48
|
-
|
|
49
|
-
def get_dids(self) -> None:
|
|
50
|
-
did = choice(self._dids)
|
|
51
|
-
self._queue.put(did)
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
from json import loads
|
|
16
|
-
from typing import Optional
|
|
17
|
-
|
|
18
|
-
from redis import StrictRedis
|
|
19
|
-
|
|
20
|
-
from rucio.common.config import config_get, config_get_int
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class NetworkMetricsCollector:
|
|
24
|
-
"""
|
|
25
|
-
Collector to get the bandwidth metrics between two sites.
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
def __init__(self):
|
|
29
|
-
self._r = StrictRedis(host=config_get('c3po-network-metrics', 'redis_host'), port=config_get_int('c3po-network-metrics', 'redis_port'))
|
|
30
|
-
self._prefix = config_get('c3po-network-metrics', 'prefix')
|
|
31
|
-
|
|
32
|
-
def getMbps(
|
|
33
|
-
self,
|
|
34
|
-
src: str,
|
|
35
|
-
type_: str
|
|
36
|
-
) -> Optional[dict[str, float]]:
|
|
37
|
-
pattern = "%s#%s:*" % (self._prefix, src)
|
|
38
|
-
keys = self._r.keys(pattern=pattern)
|
|
39
|
-
if len(keys) == 0:
|
|
40
|
-
return None
|
|
41
|
-
ret = {}
|
|
42
|
-
|
|
43
|
-
vals = self._r.mget(keys)
|
|
44
|
-
|
|
45
|
-
for i in range(len(keys)):
|
|
46
|
-
dst = keys[i].split(':')[1]
|
|
47
|
-
mbps_all = loads(vals[i]).get('mbps', {}).get(type_, {})
|
|
48
|
-
|
|
49
|
-
if '1h' in mbps_all:
|
|
50
|
-
ret[dst] = float(mbps_all['1h'])
|
|
51
|
-
else:
|
|
52
|
-
if '1d' in mbps_all:
|
|
53
|
-
ret[dst] = float(mbps_all['1d'])
|
|
54
|
-
else:
|
|
55
|
-
ret[dst] = float(mbps_all.get('1w', 0.0))
|
|
56
|
-
|
|
57
|
-
return ret
|
|
58
|
-
|
|
59
|
-
def getQueuedFiles(
|
|
60
|
-
self,
|
|
61
|
-
src: str,
|
|
62
|
-
dst: str
|
|
63
|
-
) -> int:
|
|
64
|
-
key = "%s#%s:%s" % (self._prefix, src, dst)
|
|
65
|
-
activities = loads(self._r.get(key)).get('files', {}).get('queued', {}).get('total', {})
|
|
66
|
-
|
|
67
|
-
total = 0
|
|
68
|
-
for _, values in activities.items():
|
|
69
|
-
total += values['total']
|
|
70
|
-
|
|
71
|
-
return total
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
"""
|
|
16
|
-
C3PO PanDA workload collector
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
import logging
|
|
20
|
-
from json import loads
|
|
21
|
-
from time import time
|
|
22
|
-
|
|
23
|
-
from requests import get
|
|
24
|
-
|
|
25
|
-
from rucio.common.config import config_get, config_get_int
|
|
26
|
-
from rucio.daemons.c3po.utils.timeseries import RedisTimeSeries
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class WorkloadCollector:
|
|
30
|
-
"""
|
|
31
|
-
Collector to retrieve the workload from PanDA. It stores it as a time series in Redis and provides
|
|
32
|
-
the average and maximum number of running jobs for a sliding window.
|
|
33
|
-
"""
|
|
34
|
-
|
|
35
|
-
class __WorkloadCollector:
|
|
36
|
-
"""
|
|
37
|
-
Private class needed implement singleton.
|
|
38
|
-
"""
|
|
39
|
-
def __init__(
|
|
40
|
-
self,
|
|
41
|
-
delete_keys: bool = False
|
|
42
|
-
):
|
|
43
|
-
self._avg_jobs = {}
|
|
44
|
-
self._cur_jobs = {}
|
|
45
|
-
self._max_jobs = {}
|
|
46
|
-
self._tms = RedisTimeSeries(config_get('c3po', 'redis_host'), config_get_int('c3po', 'redis_port'), config_get_int('c3po-workload', 'window'), 'jobs_')
|
|
47
|
-
|
|
48
|
-
self._request_headers = {"Accept": "application/json", "Content-Type": "application/json"}
|
|
49
|
-
self._request_url = config_get('c3po-workload', 'panda_url')
|
|
50
|
-
if delete_keys:
|
|
51
|
-
self._tms.delete_keys()
|
|
52
|
-
self.reload_cache()
|
|
53
|
-
|
|
54
|
-
def reload_cache(self) -> None:
|
|
55
|
-
self._tms.trim()
|
|
56
|
-
|
|
57
|
-
for key in self._tms.get_keys():
|
|
58
|
-
site = "_".join(key.split('_')[1:])
|
|
59
|
-
job_series = self._tms.get_series(site)
|
|
60
|
-
num_jobs = len(job_series)
|
|
61
|
-
if num_jobs > 0:
|
|
62
|
-
self._avg_jobs[site] = sum(job_series) / num_jobs
|
|
63
|
-
self._max_jobs[site] = max(job_series)
|
|
64
|
-
self._cur_jobs[site] = job_series[-1]
|
|
65
|
-
|
|
66
|
-
def collect_workload(self) -> None:
|
|
67
|
-
start = time()
|
|
68
|
-
resp = get(self._request_url, headers=self._request_headers)
|
|
69
|
-
logging.debug("PanDA response took %fs" % (time() - start))
|
|
70
|
-
|
|
71
|
-
start = time()
|
|
72
|
-
jobs = loads(resp.text)['jobs']
|
|
73
|
-
logging.debug("decoding JSON response took %fs" % (time() - start))
|
|
74
|
-
sites = {}
|
|
75
|
-
|
|
76
|
-
start = time()
|
|
77
|
-
for job in jobs:
|
|
78
|
-
if job['computingsite'] not in sites:
|
|
79
|
-
sites[job['computingsite']] = 0
|
|
80
|
-
sites[job['computingsite']] += 1
|
|
81
|
-
for site, jobs in sites.items():
|
|
82
|
-
self._tms.add_point(site, jobs)
|
|
83
|
-
|
|
84
|
-
logging.debug("processing took %fs" % (time() - start))
|
|
85
|
-
self.reload_cache()
|
|
86
|
-
|
|
87
|
-
instance = None
|
|
88
|
-
|
|
89
|
-
def __init__(self):
|
|
90
|
-
if not WorkloadCollector.instance:
|
|
91
|
-
WorkloadCollector.instance = WorkloadCollector.__WorkloadCollector()
|
|
92
|
-
|
|
93
|
-
def get_avg_jobs(self, site: str) -> float:
|
|
94
|
-
return self.instance._avg_jobs[site] # type: ignore
|
|
95
|
-
|
|
96
|
-
def get_max_jobs(self, site: str) -> int:
|
|
97
|
-
return self.instance._max_jobs[site] # type: ignore
|
|
98
|
-
|
|
99
|
-
def get_cur_jobs(self, site: str) -> int:
|
|
100
|
-
return self.instance._cur_jobs[site] # type: ignore
|
|
101
|
-
|
|
102
|
-
def get_sites(self) -> list[str]:
|
|
103
|
-
return list(self.instance._avg_jobs.keys()) # type: ignore
|
|
104
|
-
|
|
105
|
-
def get_job_info(self, site: str) -> tuple[int, float, int]:
|
|
106
|
-
return (self.get_cur_jobs(site), self.get_avg_jobs(site), self.get_max_jobs(site))
|
|
107
|
-
|
|
108
|
-
def get_series(self, site: str) -> tuple[int]:
|
|
109
|
-
return self.instance._tms.get_series(site) # type: ignore
|
|
110
|
-
|
|
111
|
-
def collect_workload(self) -> None:
|
|
112
|
-
self.instance.collect_workload() # type: ignore
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
from typing import TYPE_CHECKING
|
|
16
|
-
from uuid import uuid4
|
|
17
|
-
|
|
18
|
-
from rucio.daemons.c3po.utils.timeseries import RedisTimeSeries
|
|
19
|
-
|
|
20
|
-
if TYPE_CHECKING:
|
|
21
|
-
from rucio.common.types import InternalScope
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class DatasetCache:
|
|
25
|
-
"""
|
|
26
|
-
Utility to count the accesses of the datasets during the last day.
|
|
27
|
-
"""
|
|
28
|
-
def __init__(
|
|
29
|
-
self,
|
|
30
|
-
redis_host: str,
|
|
31
|
-
redis_port: int,
|
|
32
|
-
timeout: int = 1,
|
|
33
|
-
prefix: str = 'did_cache',
|
|
34
|
-
delete_keys: bool = False
|
|
35
|
-
):
|
|
36
|
-
self._prefix = prefix + '_' + str(uuid4()).split('-')[0]
|
|
37
|
-
self._tms = RedisTimeSeries(redis_host, redis_port, timeout, self._prefix)
|
|
38
|
-
|
|
39
|
-
if delete_keys:
|
|
40
|
-
self._tms.delete_keys()
|
|
41
|
-
|
|
42
|
-
def add_did(self, did: tuple['InternalScope', str]) -> None:
|
|
43
|
-
self._tms.add_point('{}_{}'.format(did[0].internal, did[1]), 1)
|
|
44
|
-
|
|
45
|
-
def get_did(self, did: tuple['InternalScope', str]) -> int:
|
|
46
|
-
self._tms.trim()
|
|
47
|
-
|
|
48
|
-
series = self._tms.get_series('{}_{}'.format(did[0].internal, did[1]))
|
|
49
|
-
|
|
50
|
-
return len(series)
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
"""
|
|
16
|
-
Expiring Dataset Cache
|
|
17
|
-
"""
|
|
18
|
-
from uuid import uuid4
|
|
19
|
-
|
|
20
|
-
from redis import StrictRedis
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class ExpiringDatasetCache:
|
|
24
|
-
"""
|
|
25
|
-
Cache with expiring values to keep track of recently created replicas.
|
|
26
|
-
"""
|
|
27
|
-
def __init__(
|
|
28
|
-
self,
|
|
29
|
-
redis_host: str,
|
|
30
|
-
redis_port: int,
|
|
31
|
-
timeout: int = 1,
|
|
32
|
-
prefix: str = 'expiring_did_cache'
|
|
33
|
-
):
|
|
34
|
-
self._redis = StrictRedis(host=redis_host, port=redis_port)
|
|
35
|
-
self._prefix = prefix + '_' + str(uuid4()).split('-')[0]
|
|
36
|
-
self._timeout = timeout
|
|
37
|
-
|
|
38
|
-
def add_dataset(
|
|
39
|
-
self,
|
|
40
|
-
dataset: str
|
|
41
|
-
) -> None:
|
|
42
|
-
""" Adds a datasets to cache with lifetime """
|
|
43
|
-
key = ':'.join((self._prefix, dataset))
|
|
44
|
-
self._redis.set(key, 1)
|
|
45
|
-
self._redis.expire(key, self._timeout)
|
|
46
|
-
|
|
47
|
-
def check_dataset(
|
|
48
|
-
self,
|
|
49
|
-
dataset: str
|
|
50
|
-
) -> bool:
|
|
51
|
-
""" Checks if dataset is still in cache """
|
|
52
|
-
key = ':'.join((self._prefix, dataset))
|
|
53
|
-
if self._redis.get(key) is None:
|
|
54
|
-
return False
|
|
55
|
-
|
|
56
|
-
return True
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
"""
|
|
16
|
-
Utility classes for C3PO
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
from collections import deque
|
|
20
|
-
from threading import Lock, Timer
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class ExpiringList:
|
|
24
|
-
"""
|
|
25
|
-
Simple list with time based element expiration
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
def __init__(self, timeout: int = 1):
|
|
29
|
-
self._lock = Lock()
|
|
30
|
-
self._timeout = timeout
|
|
31
|
-
self._items = deque()
|
|
32
|
-
|
|
33
|
-
def add(self, item):
|
|
34
|
-
"""Add event time
|
|
35
|
-
"""
|
|
36
|
-
with self._lock:
|
|
37
|
-
self._items.append(item)
|
|
38
|
-
Timer(self._timeout, self._expire).start()
|
|
39
|
-
|
|
40
|
-
def __len__(self) -> int:
|
|
41
|
-
"""
|
|
42
|
-
Return number of active events
|
|
43
|
-
"""
|
|
44
|
-
with self._lock:
|
|
45
|
-
return len(self._items)
|
|
46
|
-
|
|
47
|
-
def _expire(self) -> None:
|
|
48
|
-
"""
|
|
49
|
-
Remove any expired events
|
|
50
|
-
"""
|
|
51
|
-
with self._lock:
|
|
52
|
-
self._items.popleft()
|
|
53
|
-
|
|
54
|
-
def to_set(self) -> set:
|
|
55
|
-
"""
|
|
56
|
-
Return items as a set
|
|
57
|
-
"""
|
|
58
|
-
return set(self._items)
|
|
59
|
-
|
|
60
|
-
def __str__(self) -> str:
|
|
61
|
-
with self._lock:
|
|
62
|
-
return str(self._items)
|