Improve error message when using closed ECDriver instances

Previously, we would wrap an error coming out of our pyeclib_c
extension to get something like

   pyeclib.ec_iface.ECInvalidParameter: pyeclib_c_encode ERROR:
   Invalid arguments. Please inspect syslog for liberasurecode
   error report.

Now, raise something more specific/useful:

   ECBackendInstanceNotAvailable: erasure coding backend is closed

Change-Id: Iec889153f2b8c034be6a2e91ffe6bc82ed079e61
Signed-off-by: Tim Burke <tim.burke@gmail.com>
This commit is contained in:
Tim Burke
2025-08-04 21:12:55 -07:00
parent 301e8f0cd7
commit d876bef65f
2 changed files with 34 additions and 4 deletions

View File

@@ -21,6 +21,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from .ec_iface import ECBackendInstanceNotAvailable
from .ec_iface import ECDriverError
from .ec_iface import ECInsufficientFragments
from .ec_iface import PyECLib_FRAGHDRCHKSUM_Types
@@ -49,7 +50,7 @@ class ECPyECLibDriver(object):
if self.chksum_type is PyECLib_FRAGHDRCHKSUM_Types.inline_crc32:
self.inline_chksum = 1
self.handle = pyeclib_c.init(
self._handle = pyeclib_c.init(
self.k,
self.m,
ec_type.value,
@@ -64,9 +65,16 @@ class ECPyECLibDriver(object):
self.chksum_type)
def close(self):
if self.handle:
pyeclib_c.destroy(self.handle)
self.handle = None
if self._handle is not None:
pyeclib_c.destroy(self._handle)
self._handle = None
@property
def handle(self):
if self._handle is None:
raise ECBackendInstanceNotAvailable(
'erasure coding handle is closed')
return self._handle
def encode(self, data_bytes):
return pyeclib_c.encode(self.handle, data_bytes)

View File

@@ -33,6 +33,7 @@ import unittest
from itertools import combinations
import pyeclib.ec_iface
from pyeclib.ec_iface import ECBackendInstanceNotAvailable
from pyeclib.ec_iface import ECBackendNotSupported
from pyeclib.ec_iface import ECDriver
from pyeclib.ec_iface import ECDriverError
@@ -294,6 +295,27 @@ class TestPyECLibDriver(unittest.TestCase):
chksum_type=csum))
return pyeclib_drivers
def test_use_after_close(self):
pyeclib_drivers = self.get_pyeclib_testspec()
for pyeclib_driver in pyeclib_drivers:
frags = pyeclib_driver.encode(b"testdata")
self.assertEqual(
pyeclib_driver.reconstruct(frags[1:], [0])[0], frags[0])
pyeclib_driver.close()
with self.assertRaises(ECBackendInstanceNotAvailable) as ctx:
pyeclib_driver.encode(b"testdata")
self.assertEqual(str(ctx.exception),
'erasure coding handle is closed')
with self.assertRaises(ECBackendInstanceNotAvailable) as ctx:
pyeclib_driver.decode(frags)
self.assertEqual(str(ctx.exception),
'erasure coding handle is closed')
with self.assertRaises(ECBackendInstanceNotAvailable) as ctx:
pyeclib_driver.reconstruct(frags[1:], [0])
self.assertEqual(str(ctx.exception),
'erasure coding handle is closed')
def test_small_encode(self):
pyeclib_drivers = self.get_pyeclib_testspec()
encode_strs = [b"a", b"hello", b"hellohyhi", b"yo"]