summaryrefslogtreecommitdiffstats
path: root/swift/1.4.8/plugins/utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'swift/1.4.8/plugins/utils.py')
-rw-r--r--swift/1.4.8/plugins/utils.py56
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):