docs: def RecursiveDownload(dir_obj,
                        target_dir,
                        max_depth=10,
                        depth=1,
                        overwrite=False,
                        max_threads=10):
    """Recursively downloads a file entry to the target path.
  
    Args:
      dir_obj: An aff4 object that contains children.
      target_dir: Full path of the directory to write to.
      max_depth: Depth to download to. 1 means just the directory itself.
      depth: Current depth of recursion.
      overwrite: Should we overwrite files that exist.
      max_threads: Use this many threads to do the downloads.
    """
    if not isinstance(dir_obj, aff4.AFF4Volume):
      return
  
    # Reuse the same threadpool as we call recursively.
    thread_pool = threadpool.ThreadPool.Factory("Downloader", max_threads)
    thread_pool.Start()
  
    for sub_file_entry in dir_obj.OpenChildren():
      path_elements = [target_dir]
      sub_target_dir = u"/".join(path_elements)
      try:
        # Any file-like object with data in AFF4 should inherit AFF4Stream.
        if isinstance(sub_file_entry, aff4.AFF4Stream):
          args = (sub_file_entry.urn, sub_target_dir, sub_file_entry.token,
                  overwrite)
          thread_pool.AddTask(
              target=CopyAFF4ToLocal, args=args, name="Downloader")
        elif "Container" in sub_file_entry.behaviours:
          if depth >= max_depth:  # Don't go any deeper.
            continue
          try:
            os.makedirs(sub_target_dir)
          except OSError:
            pass
          RecursiveDownload(
              sub_file_entry,
              sub_target_dir,
              overwrite=overwrite,
              depth=depth + 1)
      except IOError:
        logging.exception("Unable to download %s", sub_file_entry.urn)
      finally:
        sub_file_entry.Close()
  
    # Join and stop the threadpool.
    if depth <= 1:
      thread_pool.Stop(join_timeout=THREADPOOL_JOIN_TIMEOUT)