class_docstr: The base class for external storage.
  
  This class provides some useful functions for zero-copy object
  put/get from plasma store. Also it specifies the interface for
  object spilling.
  
  When inheriting this class, please make sure to implement validation
  logic inside __init__ method. When ray instance starts, it will
  instantiating external storage to validate the config.
  
  Raises:
      ValueError: when given configuration for
          the external storage is invalid.
class_docstr_tok: ["The","base","class","for","external","storage",".","This","class","provides","some","useful","functions","for","zero-copy","object","put\/get","from","plasma","store",".","Also","it","specifies","the","interface","for","object","spilling",".","When","inheriting","this","class",",","please","make","sure","to","implement","validation","logic","inside","__init__","method",".","When","ray","instance","starts",",","it","will","instantiating","external","storage","to","validate","the","config",".","Raises",":","ValueError",":","when","given","configuration","for","the","external","storage","is","invalid","."]
docstr: Fuse all given objects into a given file handle.
  
  Args:
      f: File handle to fusion all given object refs.
      object_refs: Object references to fusion to a single file.
      owner_addresses: Owner addresses for the provided objects.
      url: url where the object ref is stored
          in the external storage.
  
  Return:
      List of urls_with_offset of fused objects.
      The order of returned keys are equivalent to the one
      with given object_refs.
docstr_tok: ["Fuse","all","given","objects","into","a","given","file","handle",".","Args",":","f",":","File","handle","to","fusion","all","given","object","refs",".","object_refs",":","Object","references","to","fusion","to","a","single","file",".","owner_addresses",":","Owner","addresses","for","the","provided","objects",".","url",":","url","where","the","object","ref","is","stored","in","the","external","storage",".","Return",":","List","of","urls_with_offset","of","fused","objects",".","The","order","of","returned","keys","are","equivalent","to","the","one","with","given","object_refs","."]
code: def _write_multiple_objects(
      self,
      f: IO,
      object_refs: List[ObjectRef],
      owner_addresses: List[str],
      url: str,
  ) -> List[str]:
      """Fuse all given objects into a given file handle.
  
      Args:
          f: File handle to fusion all given object refs.
          object_refs: Object references to fusion to a single file.
          owner_addresses: Owner addresses for the provided objects.
          url: url where the object ref is stored
              in the external storage.
  
      Return:
          List of urls_with_offset of fused objects.
          The order of returned keys are equivalent to the one
          with given object_refs.
      """
      keys = []
      offset = 0
      ray_object_pairs = self._get_objects_from_store(object_refs)
      for ref, (buf, metadata), owner_address in zip(
          object_refs, ray_object_pairs, owner_addresses
      ):
          address_len = len(owner_address)
          metadata_len = len(metadata)
          if buf is None and len(metadata) == 0:
              error = f"Object {ref.hex()} does not exist."
              raise ValueError(error)
          buf_len = 0 if buf is None else len(buf)
          payload = (
              address_len.to_bytes(8, byteorder="little")
              + metadata_len.to_bytes(8, byteorder="little")
              + buf_len.to_bytes(8, byteorder="little")
              + owner_address
              + metadata
              + (memoryview(buf) if buf_len else b"")
          )
          # 24 bytes to store owner address, metadata, and buffer lengths.
          payload_len = len(payload)
          assert (
              self.HEADER_LENGTH + address_len + metadata_len + buf_len
              == payload_len
          )
          written_bytes = f.write(payload)
          assert written_bytes == payload_len
          url_with_offset = create_url_with_offset(
              url=url, offset=offset, size=written_bytes
          )
          keys.append(url_with_offset.encode())
          offset += written_bytes
      # Necessary because pyarrow.io.NativeFile does not flush() on close().
      f.flush()
      return keys
  
imports: import abc
  import logging
  import os
  import random
  import shutil
  import time
  import urllib
  import uuid
  from collections import namedtuple
  from typing import IO, List, Optional, Tuple
  import ray
  from ray._private.ray_constants import DEFAULT_OBJECT_PREFIX
  from ray._raylet import ObjectRef
label_desc: Use image node_id 3 for calling the ExternalStorage obj's underlying member method code with example usage: obj._write_multiple_objects(f, object_refs, owner_addresses, url) and returns: keys