pyocf: unique volume ops for each volume class

Signed-off-by: Adam Rutkowski <adam.j.rutkowski@intel.com>
This commit is contained in:
Adam Rutkowski 2022-03-12 15:19:22 +01:00
parent 7cb9523d8c
commit 2672f5460a
2 changed files with 96 additions and 94 deletions

View File

@ -66,10 +66,9 @@ class VolumeProperties(Structure):
("_caps", VolumeCaps), ("_caps", VolumeCaps),
("_io_ops", IoOps), ("_io_ops", IoOps),
("_deinit", c_char_p), ("_deinit", c_char_p),
("_ops", VolumeOps), ("_ops_", VolumeOps),
] ]
class VolumeIoPriv(Structure): class VolumeIoPriv(Structure):
_fields_ = [("_data", c_void_p), ("_offset", c_uint64)] _fields_ = [("_data", c_void_p), ("_offset", c_uint64)]
@ -80,21 +79,96 @@ VOLUME_POISON = 0x13
class Volume: class Volume:
_instances_ = weakref.WeakValueDictionary() _instances_ = weakref.WeakValueDictionary()
_uuid_ = weakref.WeakValueDictionary() _uuid_ = weakref.WeakValueDictionary()
_ops_ = {}
_props_ = {}
@classmethod @classmethod
def get_ops(cls): def get_ops(cls):
cls.ops = VolumeOps( if cls in Volume._ops_:
_submit_io=cls._submit_io, return Volume._ops_[cls]
_submit_flush=cls._submit_flush,
_submit_metadata=cls._submit_metadata, @VolumeOps.SUBMIT_IO
_submit_discard=cls._submit_discard, def _submit_io(io):
_submit_write_zeroes=cls._submit_write_zeroes, io_structure = cast(io, POINTER(Io))
_open=cls._open, volume = Volume.get_instance(
_close=cls._close, OcfLib.getInstance().ocf_io_get_volume(io_structure)
_get_max_io_size=cls._get_max_io_size, )
_get_length=cls._get_length,
volume.submit_io(io_structure)
@VolumeOps.SUBMIT_FLUSH
def _submit_flush(flush):
io_structure = cast(flush, POINTER(Io))
volume = Volume.get_instance(
OcfLib.getInstance().ocf_io_get_volume(io_structure)
)
volume.submit_flush(io_structure)
@VolumeOps.SUBMIT_METADATA
def _submit_metadata(meta):
raise NotImplementedError
@VolumeOps.SUBMIT_DISCARD
def _submit_discard(discard):
io_structure = cast(discard, POINTER(Io))
volume = Volume.get_instance(
OcfLib.getInstance().ocf_io_get_volume(io_structure)
)
volume.submit_discard(io_structure)
@VolumeOps.SUBMIT_WRITE_ZEROES
def _submit_write_zeroes(write_zeroes):
raise NotImplementedError
@VolumeOps.OPEN
def _open(ref):
uuid_ptr = cast(
OcfLib.getInstance().ocf_volume_get_uuid(ref), POINTER(Uuid)
)
uuid = str(uuid_ptr.contents._data, encoding="ascii")
try:
volume = Volume.get_by_uuid(uuid)
except: # noqa E722 TODO:Investigate whether this really should be so broad
print("Tried to access unallocated volume {}".format(uuid))
print("{}".format(Volume._uuid_))
return -1
if volume.opened:
return -OcfErrorCode.OCF_ERR_NOT_OPEN_EXC
Volume._instances_[ref] = volume
return volume.do_open()
@VolumeOps.CLOSE
def _close(ref):
volume = Volume.get_instance(ref)
volume.close()
volume.opened = False
@VolumeOps.GET_MAX_IO_SIZE
def _get_max_io_size(ref):
return Volume.get_instance(ref).get_max_io_size()
@VolumeOps.GET_LENGTH
def _get_length(ref):
return Volume.get_instance(ref).get_length()
Volume._ops_[cls] = VolumeOps(
_submit_io=_submit_io,
_submit_flush=_submit_flush,
_submit_metadata=_submit_metadata,
_submit_discard=_submit_discard,
_submit_write_zeroes=_submit_write_zeroes,
_open=_open,
_close=_close,
_get_max_io_size=_get_max_io_size,
_get_length=_get_length,
) )
return cls.ops
return Volume._ops_[cls]
@classmethod @classmethod
def get_io_ops(cls): def get_io_ops(cls):
@ -102,16 +176,19 @@ class Volume:
@classmethod @classmethod
def get_props(cls): def get_props(cls):
cls.props = VolumeProperties( if cls in Volume._props_:
return Volume._props_[cls]
Volume._props_[cls] = VolumeProperties(
_name=str(cls.__name__).encode("ascii"), _name=str(cls.__name__).encode("ascii"),
_io_priv_size=sizeof(VolumeIoPriv), _io_priv_size=sizeof(VolumeIoPriv),
_volume_priv_size=0, _volume_priv_size=0,
_caps=VolumeCaps(_atomic_writes=0), _caps=VolumeCaps(_atomic_writes=0),
_ops=cls.get_ops(), _ops_=cls.get_ops(),
_io_ops=cls.get_io_ops(), _io_ops=cls.get_io_ops(),
_deinit=0, _deinit=0,
) )
return cls.props return Volume._props_[cls]
def get_copy(self): def get_copy(self):
raise NotImplementedError raise NotImplementedError
@ -128,84 +205,6 @@ class Volume:
def get_by_uuid(cls, uuid): def get_by_uuid(cls, uuid):
return cls._uuid_[uuid] return cls._uuid_[uuid]
@staticmethod
@VolumeOps.SUBMIT_IO
def _submit_io(io):
io_structure = cast(io, POINTER(Io))
volume = Volume.get_instance(
OcfLib.getInstance().ocf_io_get_volume(io_structure)
)
volume.submit_io(io_structure)
@staticmethod
@VolumeOps.SUBMIT_FLUSH
def _submit_flush(flush):
io_structure = cast(flush, POINTER(Io))
volume = Volume.get_instance(
OcfLib.getInstance().ocf_io_get_volume(io_structure)
)
volume.submit_flush(io_structure)
@staticmethod
@VolumeOps.SUBMIT_METADATA
def _submit_metadata(meta):
raise NotImplementedError
@staticmethod
@VolumeOps.SUBMIT_DISCARD
def _submit_discard(discard):
io_structure = cast(discard, POINTER(Io))
volume = Volume.get_instance(
OcfLib.getInstance().ocf_io_get_volume(io_structure)
)
volume.submit_discard(io_structure)
@staticmethod
@VolumeOps.SUBMIT_WRITE_ZEROES
def _submit_write_zeroes(write_zeroes):
raise NotImplementedError
@staticmethod
@CFUNCTYPE(c_int, c_void_p)
def _open(ref):
uuid_ptr = cast(
OcfLib.getInstance().ocf_volume_get_uuid(ref), POINTER(Uuid)
)
uuid = str(uuid_ptr.contents._data, encoding="ascii")
try:
volume = Volume.get_by_uuid(uuid)
except: # noqa E722 TODO:Investigate whether this really should be so broad
print("Tried to access unallocated volume {}".format(uuid))
print("{}".format(Volume._uuid_))
return -1
if volume.opened:
return -OcfErrorCode.OCF_ERR_NOT_OPEN_EXC
Volume._instances_[ref] = volume
return volume.do_open()
@staticmethod
@VolumeOps.CLOSE
def _close(ref):
volume = Volume.get_instance(ref)
volume.close()
volume.opened = False
@staticmethod
@VolumeOps.GET_MAX_IO_SIZE
def _get_max_io_size(ref):
return Volume.get_instance(ref).get_max_io_size()
@staticmethod
@VolumeOps.GET_LENGTH
def _get_length(ref):
return Volume.get_instance(ref).get_length()
@staticmethod @staticmethod
@IoOps.SET_DATA @IoOps.SET_DATA
def _io_set_data(io, data, offset): def _io_set_data(io, data, offset):

View File

@ -21,6 +21,7 @@ from pyocf.types.cache import (
Backfill Backfill
) )
from pyocf.types.core import Core from pyocf.types.core import Core
from pyocf.types.ctx import OcfCtx
from pyocf.types.data import Data from pyocf.types.data import Data
from pyocf.types.io import IoDir from pyocf.types.io import IoDir
from pyocf.types.shared import OcfError, OcfCompletion, CacheLineSize, SeqCutOffPolicy from pyocf.types.shared import OcfError, OcfCompletion, CacheLineSize, SeqCutOffPolicy
@ -349,6 +350,8 @@ def test_start_cache_huge_device(pyocf_ctx_log_buffer, cls):
def submit_io(self, io): def submit_io(self, io):
io.contents._end(io, 0) io.contents._end(io, 0)
OcfCtx.get_default().register_volume_type(HugeDevice)
cache_device = HugeDevice() cache_device = HugeDevice()
with pytest.raises(OcfError, match="OCF_ERR_INVAL_CACHE_DEV"): with pytest.raises(OcfError, match="OCF_ERR_INVAL_CACHE_DEV"):