def write_metadata(path_or_fd, metadata): """ Helper function to write serialized metadata for a File/Directory. :param path_or_fd: File/Directory path or fd to write the metadata :param metadata: dictionary of metadata write """ assert isinstance(metadata, dict) metastr = serialize_metadata(metadata) key = 0 while metastr: try: do_setxattr(path_or_fd, '%s%s' % (METADATA_KEY, key or ''), metastr[:MAX_XATTR_SIZE]) except IOError as err: if err.errno in (errno.ENOSPC, errno.EDQUOT): if isinstance(path_or_fd, int): filename = get_filename_from_fd(path_or_fd) do_log_rl("write_metadata(%d, metadata) failed: %s : %s", path_or_fd, err, filename) else: do_log_rl("write_metadata(%s, metadata) failed: %s", path_or_fd, err) raise DiskFileNoSpace() else: raise SwiftOnFileSystemIOError( err.errno, '%s, setxattr("%s", %s, metastr)' % (err.strerror, path_or_fd, key)) metastr = metastr[MAX_XATTR_SIZE:] key += 1
def clean_metadata(path_or_fd): key = 0 while True: try: do_removexattr(path_or_fd, '%s%s' % (METADATA_KEY, (key or ''))) except IOError as err: if err.errno == errno.ENODATA: break raise SwiftOnFileSystemIOError( err.errno, '%s, removexattr("%s", %s)' % (err.strerror, path_or_fd, key)) key += 1
def read_metadata(path_or_fd): """ Helper function to read the pickled metadata from a File/Directory. :param path_or_fd: File/Directory path or fd from which to read metadata. :returns: dictionary of metadata """ metadata = None metadata_s = '' key = 0 while metadata is None: try: metadata_s += do_getxattr(path_or_fd, '%s%s' % (METADATA_KEY, (key or ''))) except IOError as err: if err.errno == errno.ENODATA: if key > 0: # No errors reading the xattr keys, but since we have not # been able to find enough chunks to get a successful # unpickle operation, we consider the metadata lost, and # drop the existing data so that the internal state can be # recreated. clean_metadata(path_or_fd) # We either could not find any metadata key, or we could find # some keys, but were not successful in performing the # unpickling (missing keys perhaps)? Either way, just report # to the caller we have no metadata. metadata = {} else: # Note that we don't touch the keys on errors fetching the # data since it could be a transient state. raise SwiftOnFileSystemIOError( err.errno, '%s, getxattr("%s", %s)' % (err.strerror, path_or_fd, key)) else: try: # If this key provides all or the remaining part of the pickle # data, we don't need to keep searching for more keys. This # means if we only need to store data in N xattr key/value # pair, we only need to invoke xattr get N times. With large # keys sizes we are shooting for N = 1. metadata = pickle.loads(metadata_s) assert isinstance(metadata, dict) except (EOFError, pickle.UnpicklingError): # We still are not able recognize this existing data collected # as a pickled object. Make sure we loop around to try to get # more from another xattr key. metadata = None key += 1 return metadata
def _mock_rm(path): print "_mock_rm-metadata_enoent(%s)" % path shutil.rmtree(path) raise SwiftOnFileSystemIOError(errno.ENOENT, os.strerror(errno.ENOENT))