class_docstr: Manages downloading of products or parts of them.
  
  Intended for internal use, but may also be used directly if more fine-grained
  configuration or custom download logic is needed.
  
  Parameters
  ----------
  api : SentinelAPI
      A SentinelAPI instance.
  node_filter : callable, optional
      The callable is used to select which files of each product will be downloaded.
      If None (the default), the full products will be downloaded.
      See :mod:`sentinelsat.products` for sample node filters.
  verify_checksum : bool, default True
      If True, verify the downloaded files' integrity by checking its checksum.
      Throws InvalidChecksumError if the checksum does not match.
  fail_fast : bool, default False
      if True, all other downloads are cancelled when one of the downloads fails in :meth:`download_all()`.
  n_concurrent_dl : integer, optional
      Number of concurrent downloads.
      Defaults to the maximum allowed by :attr:`SentinelAPI.concurrent_dl_limit`.
  max_attempts : int, default 10
      Number of allowed retries before giving up downloading a product in :meth:`download_all()`.
  dl_retry_delay : float, default 10
      Number of seconds to wait between retrying of failed downloads.
  lta_retry_delay : float, default 60
      Number of seconds to wait between requests to the Long Term Archive.
  lta_timeout : float, optional
      Maximum number of seconds to wait for triggered products to come online.
      Defaults to no timeout.
docstr: Triggers retrieval of an offline product.
  
  Parameters
  ----------
  uuid : string
      UUID of the product
  
  Returns
  -------
  bool
      True, if the product retrieval was successfully triggered.
      False, if the product is already online.
  
  Raises
  ------
  LTAError
      If the request was not accepted due to exceeded user quota or server overload.
  ServerError
      If an unexpected response was received from server.
  UnauthorizedError
      If the provided credentials were invalid.
  
  Notes
  -----
  https://scihub.copernicus.eu/userguide/LongTermArchive
docstr_tok: ["Triggers","retrieval","of","an","offline","product",".","Parameters","--","--","--","--","--","uuid",":","string","UUID","of","the","product","Returns","--","--","--","-","bool","True",",","if","the","product","retrieval","was","successfully","triggered",".","False",",","if","the","product","is","already","online",".","Raises","--","--","--","LTAError","If","the","request","was","not","accepted","due","to","exceeded","user","quota","or","server","overload",".","ServerError","If","an","unexpected","response","was","received","from","server",".","UnauthorizedError","If","the","provided","credentials","were","invalid",".","Notes","--","--","-","https",":","\/\/scihub.copernicus.eu\/userguide\/LongTermArchive"]
code: def trigger_offline_retrieval(self, uuid):
      """Triggers retrieval of an offline product.
  
      Parameters
      ----------
      uuid : string
          UUID of the product
  
      Returns
      -------
      bool
          True, if the product retrieval was successfully triggered.
          False, if the product is already online.
  
      Raises
      ------
      LTAError
          If the request was not accepted due to exceeded user quota or server overload.
      ServerError
          If an unexpected response was received from server.
      UnauthorizedError
          If the provided credentials were invalid.
  
      Notes
      -----
      https://scihub.copernicus.eu/userguide/LongTermArchive
      """
      # Request just a single byte to avoid accidental downloading of the whole product.
      # Requesting zero bytes results in NullPointerException in the server.
      with self.api.dl_limit_semaphore:
          r = self.api.session.get(
              self.api._get_download_url(uuid),
              headers={"Range": "bytes=0-1"},
          )
      cause = r.headers.get("cause-message")
      # check https://scihub.copernicus.eu/userguide/LongTermArchive#HTTP_Status_codes
      if r.status_code in (200, 206):
          self.logger.debug("Product is online")
          return False
      elif r.status_code == 202:
          self.logger.debug("Accepted for retrieval")
          return True
      elif (
          r.status_code == 403 and cause and "concurrent flows" in cause
      ):
          # cause: 'An exception occured while creating a stream: Maximum number of 4 concurrent flows achieved by the user "username""'
          self.logger.debug(
              "Product is online but concurrent downloads limit was exceeded"
          )
          return False
      elif r.status_code == 403:
          # cause: 'User 'username' offline products retrieval quota exceeded (20 fetches max) trying to fetch product PRODUCT_FILENAME (BYTES_COUNT bytes compressed)'
          msg = f"User quota exceeded: {cause}"
          self.logger.error(msg)
          raise LTAError(msg, r)
      elif r.status_code == 503:
          msg = f"Request not accepted: {cause}"
          self.logger.error(msg)
          raise LTAError(msg, r)
      elif r.status_code < 400:
          msg = f"Unexpected response {r.status_code}: {cause}"
          self.logger.error(msg)
          raise ServerError(msg, r)
      self.api._check_scihub_response(r, test_json=False)
  
imports: import concurrent.futures
  import enum
  import itertools
  import shutil
  import threading
  import time
  import traceback
  from collections import namedtuple
  from concurrent.futures import ThreadPoolExecutor
  from contextlib import closing
  from pathlib import Path
  from typing import Any, Dict
  from xml.etree import ElementTree
  from sentinelsat.exceptions import InvalidChecksumError, LTAError, LTATriggered, SentinelAPIError, ServerError, UnauthorizedError
label_desc: Use image node_id 8 for calling the Downloader obj's underlying member method code with example usage: obj.trigger_offline_retrieval(uuid) and returns: False, True, False