From 200f68438e230ea96138e193885ab6f609a33b3b Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 9 Apr 2014 23:38:32 +0100 Subject: [PATCH] rxgen: Emit individual exception classes for defined abort codes and raise them Emit an exception class for each defined abort code and raise the appropriate exception when an abort is received. Each set of classes is subclassed from a package-specific class (eg. AbortVL_NOENT -> VLAbort) and each package-specific class is subclassed from a generic class (eg. VLAbort -> RemoteAbort) so that all package codes can be trapped in one statement and all remote aborts can be trapped together. If an unknown code is received, then this is raised as RemoteAbort only. RxRPC/rxgen codes are supplied now also in the rxgen.xg file under the RXGEN package name. KAA/KAM/KAT codes are under the KA package. Signed-off-by: David Howells --- py_rxgen.c | 30 ++++++++++++++++++++ py_rxgen.h | 10 +++++++ rpc-api/ka.xg | 2 ++ rpc-api/rxgen.xg | 32 +++++++++++++++++++++ rxgen/emit_py_module.pm | 49 +++++++++++++++++++++++++++++++++ rxgen/emit_py_sync_funcs.pm | 3 +- rxgen/rxgen.pl | 32 +++++++++++++++++++-- suite/commands/vos/listaddrs.py | 11 +++----- 8 files changed, 157 insertions(+), 12 deletions(-) create mode 100644 rpc-api/rxgen.xg diff --git a/py_rxgen.c b/py_rxgen.c index 7a3261c..db8713a 100644 --- a/py_rxgen.c +++ b/py_rxgen.c @@ -13,6 +13,7 @@ #include "structmember.h" #include #include "py_rxgen.h" +#include "afs_py.h" #include "rxgen.h" PyObject *py_rxgen_get_struct(const void *p, PyObject **cache, @@ -1031,3 +1032,32 @@ error: PyBuffer_Release(&view); return -1; } + +static int py_rxgen_received_abort_cmp(const void *key, const void *_entry) +{ + const struct kafs_abort_list *entry = _entry; + + return (uint32_t)(unsigned long)key - entry->id; +} + +/* + * Turn a received abort into a Python exception + */ +PyObject *py_rxgen_received_abort(struct rx_call *call) +{ + const struct kafs_abort_list *entry; + PyObject *ex; + + entry = bsearch((void *)(unsigned long)call->abort_code, + kafs_abort_map, + sizeof(kafs_abort_map) / sizeof(kafs_abort_map[0]), + sizeof(kafs_abort_map[0]), + py_rxgen_received_abort_cmp); + + if (entry) + ex = entry->obj; + else + ex = kafs_remote_abort; + + return PyErr_Format(ex, "Aborted %u", call->abort_code); +} diff --git a/py_rxgen.h b/py_rxgen.h index f566b4b..8fd2d16 100644 --- a/py_rxgen.h +++ b/py_rxgen.h @@ -89,4 +89,14 @@ extern int py_rxgen_premarshal_structs(void *array, size_t n, size_t size, size_ PyObject *cache, int (*premarshal)(PyObject *object)); +/* + * Abort mapping + */ +struct kafs_abort_list { + uint32_t id; + PyObject *obj; +}; + +extern PyObject *py_rxgen_received_abort(struct rx_call *call); + #endif /* _PY_RXGEN_H */ diff --git a/rpc-api/ka.xg b/rpc-api/ka.xg index b7c31d4..3c7d167 100644 --- a/rpc-api/ka.xg +++ b/rpc-api/ka.xg @@ -35,6 +35,8 @@ * SUCH DAMAGE. */ +package KA_ + const AUTHENTICATE_OLD = 1; const CHANGEPASSWORD = 2; const GETTICKET_OLD = 3; diff --git a/rpc-api/rxgen.xg b/rpc-api/rxgen.xg new file mode 100644 index 0000000..986d45d --- /dev/null +++ b/rpc-api/rxgen.xg @@ -0,0 +1,32 @@ +/* -*-c-*- + **************************************************************************** + * Copyright IBM Corporation 1988, 1989 - All Rights Reserved * + * * + * Permission to use, copy, modify, and distribute this software and its * + * documentation for any purpose and without fee is hereby granted, * + * provided that the above copyright notice appear in all copies and * + * that both that copyright notice and this permission notice appear in * + * supporting documentation, and that the name of IBM not be used in * + * advertising or publicity pertaining to distribution of the software * + * without specific, written prior permission. * + * * + * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL IBM * + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY * + * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER * + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * + **************************************************************************** + */ + +package RXGEN_ + +/* Error codes */ +const RXGEN_CC_MARSHAL = -450; +const RXGEN_CC_UNMARSHAL = -451; +const RXGEN_SS_MARSHAL = -452; +const RXGEN_SS_UNMARSHAL = -453; +const RXGEN_DECODE = -454; +const RXGEN_OPCODE = -455; +const RXGEN_SS_XDRFREE = -456; +const RXGEN_CC_XDRFREE = -457; diff --git a/rxgen/emit_py_module.pm b/rxgen/emit_py_module.pm index 5e8efe0..ceca7ed 100644 --- a/rxgen/emit_py_module.pm +++ b/rxgen/emit_py_module.pm @@ -23,6 +23,26 @@ sub emit_py_module() { print PYOUT " */\n"; print PYOUT "PyObject *kafs_remote_abort;\n"; + foreach $_ (sort(keys(%packages))) { + my $pkg = $packages{$_}; + my $codes = $pkg->{abort_codes}; + next unless (@{$codes}); + print PYOUT "PyObject *kafs_", $pkg->{name}, "_abort;\n"; + } + + print PYOUT "\n"; + print PYHDR "extern struct kafs_abort_list kafs_abort_map[", $abort_count, "];\n"; + + my %abort_table_map = (); + my $index = 0; + print PYOUT "struct kafs_abort_list kafs_abort_map[", $abort_count, "] = {\n"; + foreach my $id (sort {$a <=> $b} keys(%abort_ids)) { + my $name = $abort_ids{$id}; + print PYOUT "\t{ .id = ", $name, " }, /* ", $id, " */\n"; + $abort_table_map{$name} = $index++; + } + print PYOUT "};\n\n"; + # Emit python structure wrapper static method table print PYOUT "\n"; print PYOUT "/*\n"; @@ -93,6 +113,7 @@ sub emit_py_module() { } } + # Emit a base remote abort class that all others can be subclassed off print PYOUT "\n"; print PYOUT "\tkafs_remote_abort = PyErr_NewException(\"kafs.RemoteAbort\", NULL, NULL);\n"; print PYOUT "\tif (!kafs_remote_abort)\n"; @@ -100,6 +121,34 @@ sub emit_py_module() { print PYOUT "\tPy_INCREF(kafs_remote_abort);\n"; print PYOUT "\tPyModule_AddObject(m, \"RemoteAbort\", kafs_remote_abort);\n"; + foreach $_ (sort(keys(%packages))) { + my $pkg = $packages{$_}; + my $codes = $pkg->{abort_codes}; + next unless (@{$codes}); + + my $pkg_abort = $pkg->{name} . "Abort"; + my $pkg_sym = "kafs_" . $pkg->{name} . "_abort"; + + print PYOUT "\n"; + print PYOUT "\t", $pkg_sym, " = PyErr_NewException(\"kafs.", $pkg_abort, "\", kafs_remote_abort, NULL);\n"; + print PYOUT "\tif (!", $pkg_sym, ")\n"; + print PYOUT "\t\treturn NULL;\n"; + print PYOUT "\tPy_INCREF(", $pkg_sym, ");\n"; + print PYOUT "\tPyModule_AddObject(m, \"", $pkg_abort, "\", ", $pkg_sym, ");\n"; + + foreach my $code (sort(@{$codes})) { + my $code_abort = "Abort" . $code; + my $code_sym = "kafs_abort_map[" . $abort_table_map{$code} . "].obj"; + + print PYOUT "\n"; + print PYOUT "\t", $code_sym, " = PyErr_NewException(\"kafs.", $code_abort, "\", ", $pkg_sym, ", NULL);\n"; + print PYOUT "\tif (!", $code_sym, ")\n"; + print PYOUT "\t\treturn NULL;\n"; + print PYOUT "\tPy_INCREF(", $code_sym, ");\n"; + print PYOUT "\tPyModule_AddObject(m, \"", $code_abort, "\", ", $code_sym, ");\n"; + } + } + print PYOUT "\n"; print PYOUT "\treturn m;\n"; print PYOUT "}\n"; diff --git a/rxgen/emit_py_sync_funcs.pm b/rxgen/emit_py_sync_funcs.pm index 5735546..6a95b0b 100644 --- a/rxgen/emit_py_sync_funcs.pm +++ b/rxgen/emit_py_sync_funcs.pm @@ -405,8 +405,7 @@ sub emit_py_func_simple_sync_call($) print PYOUT "enomem:\n"; print PYOUT "\t\tres = PyExc_MemoryError;\n"; print PYOUT "\telse if (errno == ECONNABORTED)\n"; - print PYOUT "\t\tres = PyErr_Format(kafs_remote_abort, \"Aborted %u\", call->abort_code);\n"; - #print PYOUT "\t\tres = PyLong_FromLong(call->abort_code);\n"; + print PYOUT "\t\tres = py_rxgen_received_abort(call);\n"; print PYOUT "\telse\n"; print PYOUT "\t\tres = PyErr_SetFromErrno(PyExc_IOError);\n"; print PYOUT "\trxrpc_terminate_call(call, ENOMEM);\n"; diff --git a/rxgen/rxgen.pl b/rxgen/rxgen.pl index 33d15c8..5c5a750 100755 --- a/rxgen/rxgen.pl +++ b/rxgen/rxgen.pl @@ -32,7 +32,10 @@ our @funcs = (); # Functions in declaration order our %func_names = (); # Function name uniquifier our %constants = (); # Constants our %packages = (); # Packages -our @abort_codes = (); # Abort codes +our $abort_codes = (); # Abort codes +our %abort_syms = (); # Abort symbol to code map +our %abort_ids = (); # Abort code to symbol map +our $abort_count = 0; # Number of abort codes our @py_type_defs = (); # Python type definitions our @py_func_defs = (); # Python function definitions @@ -218,8 +221,10 @@ discarded_comments: $pkg = { name => $name, prefix => $prefix, + abort_codes => [], }; $packages{$prefix} = $pkg; + $abort_codes = $pkg->{abort_codes}; next; } @@ -237,7 +242,18 @@ discarded_comments: val => $v, where => $where, }; - push @abort_codes, $c if $error_codes; + if ($error_codes) { + if ($v < 0) { + $v = 0xffffffff + $v + 1; + } + + die $where, ": Duplicate abort ID" + if (exists $abort_ids{$v}); + push @{$abort_codes}, $c; + $abort_syms{$c} = $v; + $abort_ids{$v} = $c; + $abort_count++; + } next; } @@ -450,7 +466,17 @@ print "Extracted ", scalar keys %constants, " constants\n"; print "Extracted ", scalar @structs, " structs\n"; print "Extracted ", scalar keys %types, " types\n"; print "Extracted ", scalar @funcs, " functions\n"; -print "Extracted ", scalar @abort_codes, " abort codes\n"; + +my @no_abort_codes = (); +foreach $_ (sort(keys(%packages))) { + my $pkg = $packages{$_}; + if (@{$pkg->{abort_codes}}) { + print "Extracted ", scalar @{$pkg->{abort_codes}}, " ", $pkg->{name}, " abort codes\n"; + } else { + push @no_abort_codes, $pkg->{name}; + } +} +print "No abort codes for ", join(" ", @no_abort_codes), "\n" if (@no_abort_codes); ############################################################################### # diff --git a/suite/commands/vos/listaddrs.py b/suite/commands/vos/listaddrs.py index 68573af..1c3f05f 100644 --- a/suite/commands/vos/listaddrs.py +++ b/suite/commands/vos/listaddrs.py @@ -77,13 +77,10 @@ def list_all(params, vl_conn): try: list_one(params, vl_conn, attributes) found -= 1 - except kafs.RemoteAbort as msg: - if str(msg) == "Aborted 363524": - continue - elif str(msg) == "Aborted 363549": - break - else: - raise + except kafs.AbortVL_NOENT: + continue + except kafs.AbortVL_INDEXERANGE: + break if found <= 0: break -- 2.49.0