From 9e88afad62c70f7cf483083c0c89a4b7e6585654 Mon Sep 17 00:00:00 2001 From: Adam Rutkowski Date: Mon, 7 Mar 2022 16:00:08 +0100 Subject: [PATCH] pyocf: cache and core exported object volumes Signed-off-by: Adam Rutkowski --- tests/functional/pyocf/types/volume_cache.py | 31 ++++++ tests/functional/pyocf/types/volume_core.py | 27 ++++++ .../functional/pyocf/types/volume_exp_obj.py | 97 +++++++++++++++++++ tests/functional/tests/conftest.py | 6 ++ 4 files changed, 161 insertions(+) create mode 100644 tests/functional/pyocf/types/volume_cache.py create mode 100644 tests/functional/pyocf/types/volume_core.py create mode 100644 tests/functional/pyocf/types/volume_exp_obj.py diff --git a/tests/functional/pyocf/types/volume_cache.py b/tests/functional/pyocf/types/volume_cache.py new file mode 100644 index 0000000..3751e43 --- /dev/null +++ b/tests/functional/pyocf/types/volume_cache.py @@ -0,0 +1,31 @@ +# +# Copyright(c) 2022 Intel Corporation +# SPDX-License-Identifier: BSD-3-Clause +# + +from ctypes import cast, POINTER + +from .cache import Cache +from .io import Io +from .io import IoDir +from .volume_exp_obj import ExpObjVolume +from .volume import Volume + + +class CacheVolume(ExpObjVolume): + def __init__(self, cache, open=False, uuid=None): + super().__init__(cache, uuid) + self.cache = cache + self.lib = cache.owner.lib + if open: + self.open() + + def md5(self): + data = self._read() + return data.md5() + + def open(self): + return Volume.open( + self.lib.ocf_cache_get_front_volume(self.cache.handle), + self + ) diff --git a/tests/functional/pyocf/types/volume_core.py b/tests/functional/pyocf/types/volume_core.py new file mode 100644 index 0000000..841bdaf --- /dev/null +++ b/tests/functional/pyocf/types/volume_core.py @@ -0,0 +1,27 @@ +# +# Copyright(c) 2022 Intel Corporation +# SPDX-License-Identifier: BSD-3-Clause +# + +from .core import Core +from .volume_exp_obj import ExpObjVolume +from .io import IoDir +from .volume import Volume + + +class CoreVolume(ExpObjVolume): + def __init__(self, core, open=False, uuid=None): + super().__init__(core, uuid) + self.core = core + self.lib = core.cache.owner.lib + if open: + self.open() + + def md5(self): + return self.core.exp_obj_md5() + + def open(self): + return Volume.open( + self.lib.ocf_core_get_front_volume(self.core.handle), + self + ) diff --git a/tests/functional/pyocf/types/volume_exp_obj.py b/tests/functional/pyocf/types/volume_exp_obj.py new file mode 100644 index 0000000..5cacc15 --- /dev/null +++ b/tests/functional/pyocf/types/volume_exp_obj.py @@ -0,0 +1,97 @@ +# +# Copyright(c) 2022 Intel Corporation +# SPDX-License-Identifier: BSD-3-Clause +# + +from ctypes import c_int, c_void_p, CFUNCTYPE, byref, c_uint32, c_uint64, cast, POINTER + +from ..ocf import OcfLib +from .volume import Volume, VOLUME_POISON +from pyocf.utils import Size +from pyocf.types.data import Data +from pyocf.types.io import IoDir, Io +from pyocf.types.shared import OcfCompletion + + +class ExpObjVolume(Volume): + def __init__(self, parent, uuid=None): + super().__init__(uuid) + self.parent = parent + + def __alloc_io(self, addr, _bytes, _dir, _class, _flags): + vol = self.parent.get_front_volume() + queue = self.parent.get_default_queue() # TODO multiple queues? + return vol.new_io( + queue, addr, _bytes, _dir, _class, _flags + ) + + def _alloc_io(self, io): + exp_obj_io = self.__alloc_io( + io.contents._addr, + io.contents._bytes, + io.contents._dir, + io.contents._class, + io.contents._flags, + ) + + lib = OcfLib.getInstance() + cdata = OcfLib.getInstance().ocf_io_get_data(io) + OcfLib.getInstance().ocf_io_set_data(byref(exp_obj_io), cdata, 0) + + def cb(error): + nonlocal io + io = cast(io, POINTER(Io)) + io.contents._end(io, error) + + exp_obj_io.callback = cb + + return exp_obj_io + + def get_length(self): + return Size.from_B(OcfLib.getInstance().ocf_volume_get_length(self.c_vol)) + + def get_max_io_size(self): + return Size.from_B(OcfLib.getInstance().ocf_volume_get_max_io_size(self.c_vol)) + + def do_submit_io(self, io): + io = self._alloc_io(io) + io.submit() + + def do_submit_flush(self, flush): + io = self._alloc_io(flush) + io.submit_flush() + + def do_submit_discard(self, discard): + io = self._alloc_io(discard) + io.submit_discard() + + def _read(self, offset=0, size=0): + if size == 0: + size = self.get_length().B - offset + exp_obj_io = self.__alloc_io(offset, size, IoDir.READ, 0, 0) + completion = OcfCompletion([("err", c_int)]) + exp_obj_io.callback = completion + data = Data.from_bytes(bytes(size)) + exp_obj_io.set_data(data) + exp_obj_io.submit() + completion.wait() + error = completion.results["err"] + if error: + raise Exception("error reading exported object for dump") + return data + + def dump(self, offset=0, size=0, ignore=VOLUME_POISON, **kwargs): + data = self._read(offset, size) + data.dump(ignore=ifnore, **kwargs) + + def md5(self): + raise NotImplementedError + + +lib = OcfLib.getInstance() +lib.ocf_volume_get_max_io_size.argtypes = [c_void_p] +lib.ocf_volume_get_max_io_size.restype = c_uint32 +lib.ocf_volume_get_length.argtypes = [c_void_p] +lib.ocf_volume_get_length.restype = c_uint64 +lib.ocf_io_get_data.argtypes = [POINTER(Io)] +lib.ocf_io_get_data.restype = c_void_p diff --git a/tests/functional/tests/conftest.py b/tests/functional/tests/conftest.py index 94a9abc..52fe7ff 100644 --- a/tests/functional/tests/conftest.py +++ b/tests/functional/tests/conftest.py @@ -11,6 +11,8 @@ import gc sys.path.append(os.path.join(os.path.dirname(__file__), os.path.pardir)) from pyocf.types.logger import LogLevel, DefaultLogger, BufferLogger from pyocf.types.volume import RamVolume, ErrorDevice +from pyocf.types.volume_cache import CacheVolume +from pyocf.types.volume_core import CoreVolume from pyocf.types.volume_replicated import ReplicatedVolume from pyocf.types.ctx import OcfCtx @@ -24,6 +26,8 @@ def pyocf_ctx(): c = OcfCtx.with_defaults(DefaultLogger(LogLevel.WARN)) c.register_volume_type(RamVolume) c.register_volume_type(ErrorDevice) + c.register_volume_type(CacheVolume) + c.register_volume_type(CoreVolume) c.register_volume_type(ReplicatedVolume) yield c c.exit() @@ -36,6 +40,8 @@ def pyocf_ctx_log_buffer(): c = OcfCtx.with_defaults(logger) c.register_volume_type(RamVolume) c.register_volume_type(ErrorDevice) + c.register_volume_type(CacheVolume) + c.register_volume_type(CoreVolume) c.register_volume_type(ReplicatedVolume) yield logger c.exit()