]> www.infradead.org Git - users/dhowells/kafs-utils.git/commitdiff
rxgen: Emit individual exception classes for defined abort codes and raise them
authorDavid Howells <dhowells@redhat.com>
Wed, 9 Apr 2014 22:38:32 +0000 (23:38 +0100)
committerDavid Howells <dhowells@redhat.com>
Wed, 9 Apr 2014 22:38:32 +0000 (23:38 +0100)
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 <dhowells@redhat.com>
py_rxgen.c
py_rxgen.h
rpc-api/ka.xg
rpc-api/rxgen.xg [new file with mode: 0644]
rxgen/emit_py_module.pm
rxgen/emit_py_sync_funcs.pm
rxgen/rxgen.pl
suite/commands/vos/listaddrs.py

index 7a3261c713748ca48ecd1dfa1bd3afe8b79f1ea4..db8713aca2a5c855e5a8bbc5e54c743747fdbe5d 100644 (file)
@@ -13,6 +13,7 @@
 #include "structmember.h"
 #include <arpa/inet.h>
 #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);
+}
index f566b4b178d8a33700e46b433407bb233127215d..8fd2d164d809585f506df09144c1a0ecc2558488 100644 (file)
@@ -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 */
index b7c31d4ba8909222c4d83ad051fd20fe35a2ff71..3c7d1678c00f979b817d5d41c843ea4875205d85 100644 (file)
@@ -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 (file)
index 0000000..986d45d
--- /dev/null
@@ -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;
index 5e8efe099741a238c5007d9787f9767dcbabee3b..ceca7ed6f342b788b9e4971e77cad4697472ddee 100644 (file)
@@ -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";
index 5735546547f4ce117ab297b14b6f9eb8c2ed0a17..6a95b0bd64b911d3956a6f0b41d265bb9bc78437 100644 (file)
@@ -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";
index 33d15c83d1e6ee34ecd02258dbf705979a3adea9..5c5a7501b614d0a31a2ec25b67568e506218678e 100755 (executable)
@@ -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);
 
 ###############################################################################
 #
index 68573af23354aedabad59acfa56cbed78088f199..1c3f05f9928ce45091fd83233863750065ff7ce8 100644 (file)
@@ -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