From 60eaebbb01b094f94f33224df7f9ea8277608174 Mon Sep 17 00:00:00 2001 From: Prashanth Pai Date: Tue, 17 Nov 2015 18:11:31 +0530 Subject: [PATCH] Remove redundant syscalls This will optimize the first GET on files added from file interface. More info: https://gist.github.com/prashanthpai/62e0bec770421561ea79 Change-Id: I3f0fd897eedf1413c3e7d5dca0f6196c62549fcb Signed-off-by: Prashanth Pai --- swiftonfile/swift/common/utils.py | 28 ++++++++++++++-------------- swiftonfile/swift/obj/diskfile.py | 4 ++-- test/unit/common/test_utils.py | 11 +++-------- 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/swiftonfile/swift/common/utils.py b/swiftonfile/swift/common/utils.py index aa8d0ce..c446238 100644 --- a/swiftonfile/swift/common/utils.py +++ b/swiftonfile/swift/common/utils.py @@ -292,18 +292,19 @@ def _get_etag(path_or_fd): return etag -def get_object_metadata(obj_path_or_fd): +def get_object_metadata(obj_path_or_fd, stats=None): """ Return metadata of object. """ - if isinstance(obj_path_or_fd, int): - # We are given a file descriptor, so this is an invocation from the - # DiskFile.open() method. - stats = do_fstat(obj_path_or_fd) - else: - # We are given a path to the object when the DiskDir.list_objects_iter - # method invokes us. - stats = do_stat(obj_path_or_fd) + if not stats: + if isinstance(obj_path_or_fd, int): + # We are given a file descriptor, so this is an invocation from the + # DiskFile.open() method. + stats = do_fstat(obj_path_or_fd) + else: + # We are given a path to the object when the + # DiskDir.list_objects_iter method invokes us. + stats = do_stat(obj_path_or_fd) if not stats: metadata = {} @@ -320,8 +321,7 @@ def get_object_metadata(obj_path_or_fd): return metadata -def restore_metadata(path, metadata): - meta_orig = read_metadata(path) +def restore_metadata(path, metadata, meta_orig): if meta_orig: meta_new = meta_orig.copy() meta_new.update(metadata) @@ -332,12 +332,12 @@ def restore_metadata(path, metadata): return meta_new -def create_object_metadata(obj_path_or_fd): +def create_object_metadata(obj_path_or_fd, stats=None, existing_meta={}): # We must accept either a path or a file descriptor as an argument to this # method, as the diskfile modules uses a file descriptior and the DiskDir # module (for container operations) uses a path. - metadata = get_object_metadata(obj_path_or_fd) - return restore_metadata(obj_path_or_fd, metadata) + metadata_from_stat = get_object_metadata(obj_path_or_fd, stats) + return restore_metadata(obj_path_or_fd, metadata_from_stat, existing_meta) # The following dir_xxx calls should definitely be replaced diff --git a/swiftonfile/swift/obj/diskfile.py b/swiftonfile/swift/obj/diskfile.py index 9f9d15e..4d00ef9 100644 --- a/swiftonfile/swift/obj/diskfile.py +++ b/swiftonfile/swift/obj/diskfile.py @@ -636,8 +636,8 @@ class DiskFile(object): self._metadata = read_metadata(self._fd) if not validate_object(self._metadata, self._stat): - create_object_metadata(self._fd) - self._metadata = read_metadata(self._fd) + self._metadata = create_object_metadata(self._fd, self._stat, + self._metadata) assert self._metadata is not None self._filter_metadata() diff --git a/test/unit/common/test_utils.py b/test/unit/common/test_utils.py index 44d905b..c7278c8 100644 --- a/test/unit/common/test_utils.py +++ b/test/unit/common/test_utils.py @@ -320,10 +320,9 @@ class TestUtils(unittest.TestCase): def test_restore_metadata_none(self): # No initial metadata path = "/tmp/foo/i" - res_d = utils.restore_metadata(path, {'b': 'y'}) + res_d = utils.restore_metadata(path, {'b': 'y'}, {}) expected_d = {'b': 'y'} assert res_d == expected_d, "Expected %r, result %r" % (expected_d, res_d) - assert _xattr_op_cnt['get'] == 1, "%r" % _xattr_op_cnt assert _xattr_op_cnt['set'] == 1, "%r" % _xattr_op_cnt def test_restore_metadata(self): @@ -332,10 +331,9 @@ class TestUtils(unittest.TestCase): initial_d = {'a': 'z'} xkey = _xkey(path, utils.METADATA_KEY) _xattrs[xkey] = serialize_metadata(initial_d) - res_d = utils.restore_metadata(path, {'b': 'y'}) + res_d = utils.restore_metadata(path, {'b': 'y'}, initial_d) expected_d = {'a': 'z', 'b': 'y'} assert res_d == expected_d, "Expected %r, result %r" % (expected_d, res_d) - assert _xattr_op_cnt['get'] == 1, "%r" % _xattr_op_cnt assert _xattr_op_cnt['set'] == 1, "%r" % _xattr_op_cnt def test_restore_metadata_nochange(self): @@ -344,10 +342,9 @@ class TestUtils(unittest.TestCase): initial_d = {'a': 'z'} xkey = _xkey(path, utils.METADATA_KEY) _xattrs[xkey] = serialize_metadata(initial_d) - res_d = utils.restore_metadata(path, {}) + res_d = utils.restore_metadata(path, {}, initial_d) expected_d = {'a': 'z'} assert res_d == expected_d, "Expected %r, result %r" % (expected_d, res_d) - assert _xattr_op_cnt['get'] == 1, "%r" % _xattr_op_cnt assert _xattr_op_cnt['set'] == 0, "%r" % _xattr_op_cnt def test_deserialize_metadata_pickle(self): @@ -460,7 +457,6 @@ class TestUtils(unittest.TestCase): xkey = _xkey(tf.name, utils.METADATA_KEY) assert len(_xattrs.keys()) == 1 assert xkey in _xattrs - assert _xattr_op_cnt['get'] == 1 assert _xattr_op_cnt['set'] == 1 md = deserialize_metadata(_xattrs[xkey]) assert r_md == md @@ -482,7 +478,6 @@ class TestUtils(unittest.TestCase): xkey = _xkey(td, utils.METADATA_KEY) assert len(_xattrs.keys()) == 1 assert xkey in _xattrs - assert _xattr_op_cnt['get'] == 1 assert _xattr_op_cnt['set'] == 1 md = deserialize_metadata(_xattrs[xkey]) assert r_md == md