8000 Avoid GFAL error when `exists(None)` is called. · Issue #7398 · rucio/rucio · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Avoid GFAL error when exists(None) is called. #7398

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Geogouz opened this issue Feb 11, 2025 · 1 comment · Fixed by #7438
Closed

Avoid GFAL error when exists(None) is called. #7398

Geogouz opened this issue Feb 11, 2025 · 1 comment · Fixed by #7438
Assignees
Milestone

Comments

@Geogouz
Copy link
Contributor
Geogouz commented Feb 11, 2025

Description

In our code (e.g., rsemanager.exists(...)), we do:

protocol = create_protocol(rse_settings, 'read', scheme=scheme, impl=impl, domain=domain, auth_token=auth_token, logger=logger)
protocol.connect()
try:
protocol.exists(None)
except NotImplementedError:
protocol = create_protocol(rse_settings, 'write', scheme=scheme, domain=domain, auth_token=auth_token, logger=logger)
protocol.connect()
except:
pass

  • With GFAL, calling exists(None) would lead to an internal ctx.stat("None") which raises "Protocol not supported or path/url invalid: None."
  • This is currently caught in rsemanager.exists(...) by except Exception: pass, so we never fall back to the “write” protocol. The rest of the flow may work, but we see messy log errors about “stat(None).”
  • For a quick solution, and if we want to preserve the current behavior (i.e. remain in the “read” protocol and skip fallback) but avoid trying with GFAL to stat None, maybe, at the beginning of gfal's def exists(self, path): we should do something like:
if path is None:
    # Ignoring exists(None) in GFAL plugin, returning False."
    return False

Steps to reproduce

Trigger the exists(...) of rsemanager.py with gfal.

Rucio Version

36.3.0

Additional Information

No response

@rdimaio
Copy link
Contributor
rdimaio commented Feb 26, 2025

Personally, I feel like we should fix this issue in RSEManager itself. I don't think we should even run exists(None) in the first place, as it doesn't make much sense (particularly just to check that exists is implemented)

IMO the core issue is this: we mark exists as abstractmethod in the Protocol ABC:

@abstractmethod
def exists(self, path):
"""
Checks if the requested file is known by the referred RSE.
:param path: Physical file name
:returns: True if the file exists, False if it doesn't
:raises SourceNotFound: if the source file was not found on the referred storage.
"""
raise NotImplementedError

And from https://docs.python.org/3/library/abc.html#abc.abstractmethod:

A class that has a metaclass derived from ABCMeta cannot be instantiated unless all of its abstract methods and properties are overridden.

But clearly, it seems that we are okay with having subclasses of Protocol that don't actually define exists, such as storm:

def exists(self, pfn):
""" Checks if the requested file is known by the referred RSE.
:param pfn: Physical file name
:returns: True if the file exists, False if it doesn't
:raise ServiceUnavailable
"""
raise NotImplementedError

And of course based on the fact that we rely on this NotImplementedError logic here:

try:
protocol.exists(None)
except NotImplementedError:
protocol = create_protocol(rse_settings, 'write', scheme=scheme, domain=domain, auth_token=auth_token, logger=logger)
protocol.connect()
except:
pass

I think what we should do is:

  1. remove the abstractmethod decorator from exists - we are not treating this as a proper abstractmethod
  2. removing all the improper implementations of exists in the protocols (i.e. the ones that don't do anything other than passing or raising NotImplementedError)
  3. Refactoring that rsemanager block to use getattr to see if the method is implemented: https://stackoverflow.com/questions/5268404/what-is-the-fastest-way-to-check-if-a-class-has-a-function-defined

bari12 pushed a commit that referenced this issue Mar 10, 2025
bari12 pushed a commit that referenced this issue Mar 10, 2025
Removed completely the usage of protocol.exists(None) and placed the fallback to `write` protocol when exists(..) is not overridden.
0xquark pushed a commit to 0xquark/rucio that referenced this issue Mar 10, 2025
0xquark pushed a commit to 0xquark/rucio that referenced this issue Mar 10, 2025
0xquark pushed a commit to 0xquark/rucio that referenced this issue Mar 10, 2025
Removed completely the usage of protocol.exists(None) and placed the fallback to `write` protocol when exists(..) is not overridden.
0xquark pushed a commit to 0xquark/rucio that referenced this issue Mar 14, 2025
0xquark pushed a commit to 0xquark/rucio that referenced this issue Mar 14, 2025
0xquark pushed a commit to 0xquark/rucio that referenced this issue Mar 14, 2025
Removed completely the usage of protocol.exists(None) and placed the fallback to `write` protocol when exists(..) is not overridden.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Development

Successfully merging a pull request may close this issue.

3 participants
0