open and close ioctx only once

The io context handle should be open only once in the life
of the application, there's no need to open and close
with every I/O transaction

Change-Id: I9948a71dbdcd20b4732c109ad35a400bd5962766
Signed-off-by: Thiago da Silva <thiago@redhat.com>
This commit is contained in:
Thiago da Silva 2015-09-16 00:01:38 +00:00
parent 0a11da7bb0
commit d90d1ca900
3 changed files with 26 additions and 48 deletions

View File

@ -22,17 +22,17 @@ import time
from swift.common.utils import normalize_timestamp from swift.common.utils import normalize_timestamp
from swift.common.exceptions import DiskFileQuarantined, DiskFileNotExist, \ from swift.common.exceptions import DiskFileQuarantined, DiskFileNotExist, \
DiskFileCollision, DiskFileDeleted, DiskFileNotOpen, DiskFileNoSpace, \ DiskFileCollision, DiskFileNotOpen, DiskFileNoSpace, DiskFileError
DiskFileError
from swift.common.swob import multi_range_iterator from swift.common.swob import multi_range_iterator
from swift.obj.diskfile import METADATA_KEY from swift.obj.diskfile import METADATA_KEY
class RadosFileSystem(object): class RadosFileSystem(object):
def __init__(self, ceph_conf, rados_user, rados_pool, **kwargs): def __init__(self, ceph_conf, rados_user, rados_pool, logger, **kwargs):
self._conf = ceph_conf self._conf = ceph_conf
self._user = rados_user self._user = rados_user
self._pool = rados_pool self._pool = rados_pool
self._logger = logger
self._rados = None self._rados = None
self._ioctx = None self._ioctx = None
@ -47,21 +47,19 @@ class RadosFileSystem(object):
if self._rados is None: if self._rados is None:
self._rados = fs.RADOS.Rados(conffile=fs._conf, rados_id=fs._user) self._rados = fs.RADOS.Rados(conffile=fs._conf, rados_id=fs._user)
self._rados.connect() self._rados.connect()
return self._rados self._ioctx = self._rados.open_ioctx(self._pool)
return self._rados, self._ioctx
def _shutdown(self): def _shutdown(self):
if self._rados: if self._rados:
self._ioctx.close()
self._rados.shutdown() self._rados.shutdown()
class _radosfs(object): class _radosfs(object):
def __init__(self, fs, _get_rados): def __init__(self, fs, _get_rados):
self._rados = _get_rados(fs) self._rados, self._ioctx = _get_rados(fs)
self._fs = fs self._fs = fs
self._pool = fs._pool self._pool = fs._pool
self._ioctx = self._rados.open_ioctx(self._pool)
def close(self):
self._ioctx.close()
def del_object(self, obj): def del_object(self, obj):
try: try:
@ -189,7 +187,6 @@ class DiskFileReader(object):
self._obj_size = obj_size self._obj_size = obj_size
self._etag = etag self._etag = etag
self._iter_hook = iter_hook self._iter_hook = iter_hook
#
self._iter_etag = None self._iter_etag = None
self._bytes_read = 0 self._bytes_read = 0
self._read_offset = 0 self._read_offset = 0
@ -275,9 +272,8 @@ class DiskFileReader(object):
def close(self): def close(self):
""" """
Close the file. Will handle quarantining file if necessary. handle quarantining file if necessary.
""" """
self._fs.close()
try: try:
if self._started_at_0 and self._read_to_eof: if self._started_at_0 and self._read_to_eof:
self._handle_close_quarantine() self._handle_close_quarantine()
@ -312,15 +308,14 @@ class DiskFile(object):
This method must populate the _metadata attribute. This method must populate the _metadata attribute.
:raises DiskFileCollision: on name mis-match with metadata :raises DiskFileCollision: on name mis-match with metadata
:raises DiskFileDeleted: if it does not exist, or a tombstone is :raises DiskFileNotExist: if it does not exist
present
:raises DiskFileQuarantined: if while reading metadata of the file :raises DiskFileQuarantined: if while reading metadata of the file
some data did pass cross checks some data did not pass cross checks
""" """
self._fs_inst = self._fs.open() self._fs_inst = self._fs.open()
self._metadata = self._fs_inst.get_metadata(self._name) self._metadata = self._fs_inst.get_metadata(self._name)
if self._metadata is None: if self._metadata is None:
raise DiskFileDeleted() raise DiskFileNotExist()
self._verify_data_file() self._verify_data_file()
self._metadata = self._metadata or {} self._metadata = self._metadata or {}
return self return self
@ -331,7 +326,7 @@ class DiskFile(object):
return self return self
def __exit__(self, t, v, tb): def __exit__(self, t, v, tb):
self._fs_inst.close() pass
def _quarantine(self, msg): def _quarantine(self, msg):
self._fs_inst.quarantine(self._name) self._fs_inst.quarantine(self._name)
@ -437,15 +432,11 @@ class DiskFile(object):
:raises DiskFileNoSpace: if a size is specified and allocation fails :raises DiskFileNoSpace: if a size is specified and allocation fails
""" """
fs_inst = None fs_inst = None
try: fs_inst = self._fs.open()
fs_inst = self._fs.open() if size is not None:
if size is not None: fs_inst.create(self._name, size)
fs_inst.create(self._name, size)
yield DiskFileWriter(fs_inst, self._name) yield DiskFileWriter(fs_inst, self._name)
finally:
if fs_inst is not None:
fs_inst.close()
def write_metadata(self, metadata): def write_metadata(self, metadata):
""" """
@ -462,12 +453,8 @@ class DiskFile(object):
:param timestamp: timestamp to compare with each file :param timestamp: timestamp to compare with each file
""" """
fs_inst = None fs_inst = None
try: timestamp = normalize_timestamp(timestamp)
timestamp = normalize_timestamp(timestamp) fs_inst = self._fs.open()
fs_inst = self._fs.open() md = fs_inst.get_metadata(self._name)
md = fs_inst.get_metadata(self._name) if md and md['X-Timestamp'] < timestamp:
if md and md['X-Timestamp'] < timestamp: fs_inst.del_object(self._name)
fs_inst.del_object(self._name)
finally:
if fs_inst is not None:
fs_inst.close()

View File

@ -39,7 +39,8 @@ class ObjectController(server.ObjectController):
ceph_conf = conf.get("rados_ceph_conf", None) ceph_conf = conf.get("rados_ceph_conf", None)
rados_user = conf.get("rados_user", None) rados_user = conf.get("rados_user", None)
rados_pool = conf.get("rados_pool", None) rados_pool = conf.get("rados_pool", None)
self._filesystem = RadosFileSystem(ceph_conf, rados_user, rados_pool) self._filesystem = RadosFileSystem(ceph_conf, rados_user, rados_pool,
self.logger)
def get_diskfile(self, device, partition, account, container, obj, def get_diskfile(self, device, partition, account, container, obj,
**kwargs): **kwargs):

View File

@ -39,9 +39,11 @@ class TestRadosDiskFile(unittest.TestCase):
self.account = 'account' self.account = 'account'
self.container = 'container' self.container = 'container'
self.obj_name = 'myobject' self.obj_name = 'myobject'
self.logger = mock.Mock()
self.rdf = RadosFileSystem(self.rados_ceph_conf, self.rdf = RadosFileSystem(self.rados_ceph_conf,
self.rados_name, self.rados_name,
self.rados_pool, self.rados_pool,
self.logger,
rados=self.mock_rados) rados=self.mock_rados)
self.df = self.rdf.get_diskfile(self.device, self.df = self.rdf.get_diskfile(self.device,
self.partition, self.partition,
@ -67,9 +69,6 @@ class TestRadosDiskFile(unittest.TestCase):
self.Rados.connect.assert_called_once_with() self.Rados.connect.assert_called_once_with()
self.Rados.open_ioctx.assert_called_once_with(self.rados_pool) self.Rados.open_ioctx.assert_called_once_with(self.rados_pool)
def _assert_if_rados_not_closed(self):
self.ioctx.close.assert_called_once_with()
def _assert_if_rados_opened(self): def _assert_if_rados_opened(self):
assert((self.mock_rados.Rados.call_count == 0) and assert((self.mock_rados.Rados.call_count == 0) and
(self.Rados.connect.call_count == 0) and (self.Rados.connect.call_count == 0) and
@ -85,7 +84,7 @@ class TestRadosDiskFile(unittest.TestCase):
(self.Rados.open_ioctx.call_count > 0)) (self.Rados.open_ioctx.call_count > 0))
assert((self.Rados.connect.call_count > 0) and assert((self.Rados.connect.call_count > 0) and
(self.Rados.open_ioctx.call_count == (self.Rados.open_ioctx.call_count ==
self.ioctx.close.call_count)) self.Rados.connect.call_count))
def test_df_open_1(self): def test_df_open_1(self):
meta = {'name': self._obj_name(), 'Content-Length': 0} meta = {'name': self._obj_name(), 'Content-Length': 0}
@ -96,7 +95,6 @@ class TestRadosDiskFile(unittest.TestCase):
self._assert_if_rados_not_opened() self._assert_if_rados_not_opened()
self.ioctx.get_xattr.assert_called_once_with(self._obj_name(), self.ioctx.get_xattr.assert_called_once_with(self._obj_name(),
METADATA_KEY) METADATA_KEY)
self._assert_if_rados_not_closed()
def test_df_open_invalid_name(self): def test_df_open_invalid_name(self):
meta = {'name': 'invalid', 'Content-Length': 0} meta = {'name': 'invalid', 'Content-Length': 0}
@ -169,7 +167,6 @@ class TestRadosDiskFile(unittest.TestCase):
assert(success) assert(success)
assert(ret_meta == meta) assert(ret_meta == meta)
self._assert_if_rados_not_opened() self._assert_if_rados_not_opened()
self._assert_if_rados_not_closed()
def test_df_read_metadata(self): def test_df_read_metadata(self):
meta = {'name': self._obj_name(), 'Content-Length': 0} meta = {'name': self._obj_name(), 'Content-Length': 0}
@ -186,7 +183,6 @@ class TestRadosDiskFile(unittest.TestCase):
assert(success) assert(success)
assert(ret_meta == meta) assert(ret_meta == meta)
self._assert_if_rados_not_opened() self._assert_if_rados_not_opened()
self._assert_if_rados_not_closed()
def test_df_notopen_reader(self): def test_df_notopen_reader(self):
success = False success = False
@ -215,7 +211,6 @@ class TestRadosDiskFile(unittest.TestCase):
finally: finally:
assert(success) assert(success)
self._assert_if_rados_not_opened() self._assert_if_rados_not_opened()
self._assert_if_rados_not_closed()
def test_df_open_reader_2(self): def test_df_open_reader_2(self):
meta = {'name': self._obj_name(), 'Content-Length': 0, 'ETag': ''} meta = {'name': self._obj_name(), 'Content-Length': 0, 'ETag': ''}
@ -386,7 +381,6 @@ class TestRadosDiskFile(unittest.TestCase):
pass pass
assert(self.ioctx.trunc.call_count == 0) assert(self.ioctx.trunc.call_count == 0)
self._assert_if_rados_not_opened() self._assert_if_rados_not_opened()
self._assert_if_rados_not_closed()
with self.df.create(500): with self.df.create(500):
pass pass
@ -414,7 +408,6 @@ class TestRadosDiskFile(unittest.TestCase):
(fcont[8:], 8)] (fcont[8:], 8)]
assert(writes == check_list) assert(writes == check_list)
self._assert_if_rados_not_opened() self._assert_if_rados_not_opened()
self._assert_if_rados_not_closed()
def test_df_writer_put(self): def test_df_writer_put(self):
meta = {'Content-Length': 0, meta = {'Content-Length': 0,
@ -430,7 +423,6 @@ class TestRadosDiskFile(unittest.TestCase):
assert(ca == check_1) assert(ca == check_1)
assert(meta['name'] == self._obj_name()) assert(meta['name'] == self._obj_name())
self._assert_if_rados_not_opened() self._assert_if_rados_not_opened()
self._assert_if_rados_not_closed()
def test_df_write_metadata(self): def test_df_write_metadata(self):
meta = {'Content-Length': 0, meta = {'Content-Length': 0,
@ -444,7 +436,6 @@ class TestRadosDiskFile(unittest.TestCase):
assert(ca == check_1) assert(ca == check_1)
assert(meta['name'] == self._obj_name()) assert(meta['name'] == self._obj_name())
self._assert_if_rados_not_opened() self._assert_if_rados_not_opened()
self._assert_if_rados_not_closed()
def test_df_delete(self): def test_df_delete(self):
meta = {'name': self._obj_name(), 'Content-Length': 0, meta = {'name': self._obj_name(), 'Content-Length': 0,
@ -460,7 +451,6 @@ class TestRadosDiskFile(unittest.TestCase):
finally: finally:
assert(success) assert(success)
self._assert_if_rados_not_opened() self._assert_if_rados_not_opened()
self._assert_if_rados_not_closed()
self.ioctx.remove_object.assert_called_once_with(self._obj_name()) self.ioctx.remove_object.assert_called_once_with(self._obj_name())