diff options
Diffstat (limited to 'swift/1.4.8/plugins/utils.py')
-rw-r--r-- | swift/1.4.8/plugins/utils.py | 56 |
1 files changed, 43 insertions, 13 deletions
diff --git a/swift/1.4.8/plugins/utils.py b/swift/1.4.8/plugins/utils.py index 61112c8c38f..72b2f389bc7 100644 --- a/swift/1.4.8/plugins/utils.py +++ b/swift/1.4.8/plugins/utils.py @@ -190,34 +190,63 @@ def _add_timestamp(metadata_i): def read_metadata(path): """ - Helper function to read the pickled metadata from a File/Directory . + Helper function to read the pickled metadata from a File/Directory. :param path: File/Directory to read metadata from. :returns: dictionary of metadata """ - metadata = '' + metadata = None + metadata_s = '' key = 0 - while True: + while metadata is None: try: - metadata += xattr.get(path, '%s%s' % (METADATA_KEY, (key or ''))) + metadata_s += xattr.get(path, '%s%s' % (METADATA_KEY, (key or ''))) except IOError as err: - if err.errno != errno.ENODATA: - logging.exception("xattr.get failed on %s key %s err: %s", path, key, str(err)) - break - key += 1 - if metadata: - return pickle.loads(metadata) - else: - return {} + 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) + # 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: + logging.exception("xattr.get failed on %s key %s err: %s", + path, key, str(err)) + # Note that we don't touch the keys on errors fetching the + # data since it could be a transient state. + raise + 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 write_metadata(path, metadata): """ Helper function to write pickled metadata for a File/Directory. :param path: File/Directory path to write the metadata - :param metadata: metadata to write + :param metadata: dictionary to metadata write """ + assert isinstance(metadata, dict) metastr = pickle.dumps(metadata, PICKLE_PROTOCOL) key = 0 while metastr: @@ -237,6 +266,7 @@ def clean_metadata(path): except IOError as err: if err.errno == errno.ENODATA: break + raise key += 1 def dir_empty(path): |