pyocf: Extract generic volume logic from RamVolume

Signed-off-by: Adam Rutkowski <adam.j.rutkowski@intel.com>
This commit is contained in:
Adam Rutkowski 2021-10-18 23:40:33 +02:00
parent 16f9d58f28
commit 9e13364896

View File

@ -77,65 +77,45 @@ class VolumeIoPriv(Structure):
VOLUME_POISON = 0x13 VOLUME_POISON = 0x13
class RamVolume(): class Volume:
_instances_ = weakref.WeakValueDictionary() _instances_ = weakref.WeakValueDictionary()
_uuid_ = weakref.WeakValueDictionary() _uuid_ = weakref.WeakValueDictionary()
props = None @classmethod
def get_ops(cls):
cls.ops = VolumeOps(
_submit_io=cls._submit_io,
_submit_flush=cls._submit_flush,
_submit_metadata=cls._submit_metadata,
_submit_discard=cls._submit_discard,
_submit_write_zeroes=cls._submit_write_zeroes,
_open=cls._open,
_close=cls._close,
_get_max_io_size=cls._get_max_io_size,
_get_length=cls._get_length,
)
return cls.ops
def __init__(self, size: S, uuid=None): @classmethod
super().__init__() def get_io_ops(cls):
self.size = size return IoOps(_set_data=cls._io_set_data, _get_data=cls._io_get_data)
if uuid:
if uuid in type(self)._uuid_:
raise Exception(
"RamVolume with uuid {} already created".format(uuid)
)
self.uuid = uuid
else:
self.uuid = str(id(self))
type(self)._uuid_[self.uuid] = self
self.data = create_string_buffer(int(self.size))
memset(self.data, VOLUME_POISON, self.size)
self.data_ptr = cast(self.data, c_void_p).value
self.reset_stats()
self.opened = False
def get_copy(self):
new_volume = RamVolume(self.size)
memmove(new_volume.data, self.data, self.size)
return new_volume
@classmethod @classmethod
def get_props(cls): def get_props(cls):
if not cls.props: cls.props = VolumeProperties(
cls.props = 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=VolumeOps( _io_ops=cls.get_io_ops(),
_submit_io=cls._submit_io, _deinit=0,
_submit_flush=cls._submit_flush, )
_submit_metadata=cls._submit_metadata,
_submit_discard=cls._submit_discard,
_submit_write_zeroes=cls._submit_write_zeroes,
_open=cls._open,
_close=cls._close,
_get_max_io_size=cls._get_max_io_size,
_get_length=cls._get_length,
),
_io_ops=IoOps(
_set_data=cls._io_set_data, _get_data=cls._io_get_data
),
_deinit=0,
)
return cls.props return cls.props
def get_copy(self):
raise NotImplementedError
@classmethod @classmethod
def get_instance(cls, ref): def get_instance(cls, ref):
instance = cls._instances_[ref] instance = cls._instances_[ref]
@ -152,7 +132,7 @@ class RamVolume():
@VolumeOps.SUBMIT_IO @VolumeOps.SUBMIT_IO
def _submit_io(io): def _submit_io(io):
io_structure = cast(io, POINTER(Io)) io_structure = cast(io, POINTER(Io))
volume = RamVolume.get_instance( volume = Volume.get_instance(
OcfLib.getInstance().ocf_io_get_volume(io_structure) OcfLib.getInstance().ocf_io_get_volume(io_structure)
) )
@ -162,7 +142,7 @@ class RamVolume():
@VolumeOps.SUBMIT_FLUSH @VolumeOps.SUBMIT_FLUSH
def _submit_flush(flush): def _submit_flush(flush):
io_structure = cast(flush, POINTER(Io)) io_structure = cast(flush, POINTER(Io))
volume = RamVolume.get_instance( volume = Volume.get_instance(
OcfLib.getInstance().ocf_io_get_volume(io_structure) OcfLib.getInstance().ocf_io_get_volume(io_structure)
) )
@ -171,13 +151,13 @@ class RamVolume():
@staticmethod @staticmethod
@VolumeOps.SUBMIT_METADATA @VolumeOps.SUBMIT_METADATA
def _submit_metadata(meta): def _submit_metadata(meta):
pass raise NotImplementedError
@staticmethod @staticmethod
@VolumeOps.SUBMIT_DISCARD @VolumeOps.SUBMIT_DISCARD
def _submit_discard(discard): def _submit_discard(discard):
io_structure = cast(discard, POINTER(Io)) io_structure = cast(discard, POINTER(Io))
volume = RamVolume.get_instance( volume = Volume.get_instance(
OcfLib.getInstance().ocf_io_get_volume(io_structure) OcfLib.getInstance().ocf_io_get_volume(io_structure)
) )
@ -186,7 +166,7 @@ class RamVolume():
@staticmethod @staticmethod
@VolumeOps.SUBMIT_WRITE_ZEROES @VolumeOps.SUBMIT_WRITE_ZEROES
def _submit_write_zeroes(write_zeroes): def _submit_write_zeroes(write_zeroes):
pass raise NotImplementedError
@staticmethod @staticmethod
@CFUNCTYPE(c_int, c_void_p) @CFUNCTYPE(c_int, c_void_p)
@ -196,35 +176,35 @@ class RamVolume():
) )
uuid = str(uuid_ptr.contents._data, encoding="ascii") uuid = str(uuid_ptr.contents._data, encoding="ascii")
try: try:
volume = RamVolume.get_by_uuid(uuid) volume = Volume.get_by_uuid(uuid)
except: # noqa E722 TODO:Investigate whether this really should be so broad except: # noqa E722 TODO:Investigate whether this really should be so broad
print("Tried to access unallocated volume {}".format(uuid)) print("Tried to access unallocated volume {}".format(uuid))
print("{}".format(RamVolume._uuid_)) print("{}".format(Volume._uuid_))
return -1 return -1
if volume.opened: if volume.opened:
return -OcfErrorCode.OCF_ERR_NOT_OPEN_EXC return -OcfErrorCode.OCF_ERR_NOT_OPEN_EXC
RamVolume._instances_[ref] = volume Volume._instances_[ref] = volume
return volume.open() return volume.do_open()
@staticmethod @staticmethod
@VolumeOps.CLOSE @VolumeOps.CLOSE
def _close(ref): def _close(ref):
volume = RamVolume.get_instance(ref) volume = Volume.get_instance(ref)
volume.close() volume.close()
volume.opened = False volume.opened = False
@staticmethod @staticmethod
@VolumeOps.GET_MAX_IO_SIZE @VolumeOps.GET_MAX_IO_SIZE
def _get_max_io_size(ref): def _get_max_io_size(ref):
return RamVolume.get_instance(ref).get_max_io_size() return Volume.get_instance(ref).get_max_io_size()
@staticmethod @staticmethod
@VolumeOps.GET_LENGTH @VolumeOps.GET_LENGTH
def _get_length(ref): def _get_length(ref):
return RamVolume.get_instance(ref).get_length() return Volume.get_instance(ref).get_length()
@staticmethod @staticmethod
@IoOps.SET_DATA @IoOps.SET_DATA
@ -246,12 +226,76 @@ class RamVolume():
) )
return io_priv.contents._data return io_priv.contents._data
def open(self): def __init__(self, uuid=None):
if uuid:
if uuid in type(self)._uuid_:
raise Exception(
"Volume with uuid {} already created".format(uuid)
)
self.uuid = uuid
else:
self.uuid = str(id(self))
type(self)._uuid_[self.uuid] = self
self.reset_stats()
self.opened = False
def do_open(self):
self.opened = True self.opened = True
return 0 return 0
def close(self): def close(self):
pass self.opened = False
def get_length(self):
raise NotImplementedError
def get_max_io_size(self):
raise NotImplementedError
def submit_flush(self, flush):
raise NotImplementedError
def submit_discard(self, discard):
raise NotImplementedError
def get_stats(self):
return self.stats
def reset_stats(self):
self.stats = {IoDir.WRITE: 0, IoDir.READ: 0}
def inc_stats(self, _dir):
self.stats[_dir] += 1
def submit_io(self, io):
volume.inc_stats(IoDir(io.contents._dir))
volume.do_submit_io(io)
def do_submit_io(self, io):
raise NotImplementedError
def dump(self, offset=0, size=0, ignore=VOLUME_POISON, **kwargs):
raise NotImplementedError
def md5(self):
raise NotImplementedError
class RamVolume(Volume):
props = None
def __init__(self, size: S, uuid=None):
super().__init__(uuid)
self.size = size
self.data = create_string_buffer(int(self.size))
memset(self.data, VOLUME_POISON, self.size)
self.data_ptr = cast(self.data, c_void_p).value
def get_copy(self):
new_volume = RamVolume(self.size)
memmove(new_volume.data, self.data, self.size)
return new_volume
def get_length(self): def get_length(self):
return self.size return self.size
@ -277,16 +321,8 @@ class RamVolume():
except: # noqa E722 except: # noqa E722
discard.contents._end(discard, -OcfErrorCode.OCF_ERR_NOT_SUPP) discard.contents._end(discard, -OcfErrorCode.OCF_ERR_NOT_SUPP)
def get_stats(self): def do_submit_io(self, io):
return self.stats
def reset_stats(self):
self.stats = {IoDir.WRITE: 0, IoDir.READ: 0}
def submit_io(self, io):
try: try:
self.stats[IoDir(io.contents._dir)] += 1
io_priv = cast( io_priv = cast(
OcfLib.getInstance().ocf_io_get_priv(io), POINTER(VolumeIoPriv)) OcfLib.getInstance().ocf_io_get_priv(io), POINTER(VolumeIoPriv))
offset = io_priv.contents._offset offset = io_priv.contents._offset
@ -341,9 +377,9 @@ class ErrorDevice(RamVolume):
def set_mapping(self, error_sectors: set): def set_mapping(self, error_sectors: set):
self.error_sectors = error_sectors self.error_sectors = error_sectors
def submit_io(self, io): def do_submit_io(self, io):
if not self.armed: if not self.armed:
super().submit_io(io) super().do_submit_io(io)
return return
direction = IoDir(io.contents._dir) direction = IoDir(io.contents._dir)
@ -368,7 +404,7 @@ class ErrorDevice(RamVolume):
io.contents._end(io, -OcfErrorCode.OCF_ERR_IO) io.contents._end(io, -OcfErrorCode.OCF_ERR_IO)
self.stats["errors"][direction] += 1 self.stats["errors"][direction] += 1
else: else:
super().submit_io(io) super().do_submit_io(io)
def arm(self): def arm(self):
self.armed = True self.armed = True
@ -389,7 +425,7 @@ class TraceDevice(RamVolume):
super().__init__(size, uuid) super().__init__(size, uuid)
self.trace_fcn = trace_fcn self.trace_fcn = trace_fcn
def submit_io(self, io): def do_submit_io(self, io):
submit = True submit = True
if self.trace_fcn: if self.trace_fcn: