diff vamp-client/CapnpRRClient.h @ 170:590b1a1fd955

More work on error and exception handling
author Chris Cannam <cannam@all-day-breakfast.com>
date Tue, 31 Jan 2017 14:53:24 +0000
parents 96488e9e9096
children 3eb00e5c76c4
line wrap: on
line diff
--- a/vamp-client/CapnpRRClient.h	Tue Jan 31 11:26:07 2017 +0000
+++ b/vamp-client/CapnpRRClient.h	Tue Jan 31 14:53:24 2017 +0000
@@ -143,11 +143,8 @@
 
         LOG_E("CapnpRRClient::listPluginData called");
         
-        if (!m_transport->isOK()) {
-            log("Piper server crashed or failed to start (caller should have checked this)");
-            throw std::runtime_error("Piper server crashed or failed to start");
-        }
-
+        checkServerOK();
+        
         capnp::MallocMessageBuilder message;
         piper::RpcRequest::Builder builder = message.initRoot<piper::RpcRequest>();
         VampnProto::buildRpcRequest_List(builder, req);
@@ -174,11 +171,8 @@
 
         LOG_E("CapnpRRClient::loadPlugin called");
         
-        if (!m_transport->isOK()) {
-            log("Piper server crashed or failed to start (caller should have checked this)");
-            throw std::runtime_error("Piper server crashed or failed to start");
-        }
-
+        checkServerOK();
+        
         LoadResponse resp;
         PluginHandleMapper::Handle handle = serverLoad(req.pluginKey,
                                                        req.inputSampleRate,
@@ -210,12 +204,9 @@
               PluginConfiguration config) override {
 
         LOG_E("CapnpRRClient::configure called");
+
+        checkServerOK();
         
-        if (!m_transport->isOK()) {
-            log("Piper server crashed or failed to start (caller should have checked this)");
-            throw std::runtime_error("Piper server crashed or failed to start");
-        }
-
         ConfigurationRequest request;
         request.plugin = plugin;
         request.configuration = config;
@@ -232,8 +223,6 @@
         capnp::FlatArrayMessageReader responseMessage(karr);
         piper::RpcResponse::Reader reader = responseMessage.getRoot<piper::RpcResponse>();
 
-        //!!! handle (explicit) error case
-
         checkResponseType(reader, piper::RpcResponse::Response::Which::CONFIGURE, id);
 
         ConfigurationResponse cr;
@@ -254,11 +243,8 @@
 
         LOG_E("CapnpRRClient::process called");
         
-        if (!m_transport->isOK()) {
-            log("Piper server crashed or failed to start (caller should have checked this)");
-            throw std::runtime_error("Piper server crashed or failed to start");
-        }
-
+        checkServerOK();
+        
         ProcessRequest request;
         request.plugin = plugin;
         request.inputBuffers = inputBuffers;
@@ -275,8 +261,6 @@
         capnp::FlatArrayMessageReader responseMessage(karr);
         piper::RpcResponse::Reader reader = responseMessage.getRoot<piper::RpcResponse>();
 
-        //!!! handle (explicit) error case
-
         checkResponseType(reader, piper::RpcResponse::Response::Which::PROCESS, id);
 
         ProcessResponse pr;
@@ -294,11 +278,8 @@
 
         LOG_E("CapnpRRClient::finish called");
         
-        if (!m_transport->isOK()) {
-            log("Piper server crashed or failed to start (caller should have checked this)");
-            throw std::runtime_error("Piper server crashed or failed to start");
-        }
-
+        checkServerOK();
+        
         FinishRequest request;
         request.plugin = plugin;
         
@@ -314,8 +295,6 @@
         capnp::FlatArrayMessageReader responseMessage(karr);
         piper::RpcResponse::Reader reader = responseMessage.getRoot<piper::RpcResponse>();
 
-        //!!! handle (explicit) error case
-
         checkResponseType(reader, piper::RpcResponse::Response::Which::FINISH, id);
 
         FinishResponse pr;
@@ -341,11 +320,8 @@
 
         log("CapnpRRClient: reset() called, plugin will be closed and reloaded");
         
-        if (!m_transport->isOK()) {
-            log("Piper server crashed or failed to start (caller should have checked this)");
-            throw std::runtime_error("Piper server crashed or failed to start");
-        }
-
+        checkServerOK();
+        
         if (m_mapper.havePlugin(plugin)) {
             (void)finish(plugin); // server-side unload
         }
@@ -384,23 +360,58 @@
     }
 
     void
+    checkServerOK() {
+        if (!m_transport->isOK()) {
+            log("Piper server crashed or failed to start (caller should have checked this)");
+            throw ServerCrashed();
+        }
+    }
+    
+    /**
+     * Check (i) that the response has the same id as supplied (which
+     * presumably is the corresponding request id) and (ii) that the
+     * response has the expected type.
+     *
+     * Return only if both of these things are the case.
+     * 
+     * If the response has the right id but is an error response,
+     * throw a ServiceError exception with the error response's
+     * message in it.
+     *
+     * If the response has the wrong id, or if it has the wrong type
+     * and is not an error response, throw ProtocolError. (i.e. for
+     * cases having errors that are not conveyed through our official
+     * error response.)
+     */
+    void
     checkResponseType(const piper::RpcResponse::Reader &r,
                       piper::RpcResponse::Response::Which type,
                       ReqId id) {
         
-        if (r.getResponse().which() != type) {
-            std::ostringstream s;
-            s << "checkResponseType: wrong response type (received "
-              << int(r.getResponse().which()) << ", expected " << int(type) << ")";
-            log(s.str());
-            throw std::runtime_error("Wrong response type");
-        }
         if (ReqId(r.getId().getNumber()) != id) {
             std::ostringstream s;
             s << "checkResponseType: wrong response id (received "
               << r.getId().getNumber() << ", expected " << id << ")";
             log(s.str());
-            throw std::runtime_error("Wrong response id");
+            throw ProtocolError("Wrong response id");
+        }
+        if (r.getResponse().which() != type) {
+            if (r.getResponse().which() == piper::RpcResponse::Response::Which::ERROR) {
+                int code;
+                std::string message;
+                VampnProto::readRpcResponse_Error(code, message, r);
+                std::ostringstream s;
+                s << "checkResponseType: received an error with message: "
+                  << message;
+                log(s.str());
+                throw ServiceError(message);
+            } else {
+                std::ostringstream s;
+                s << "checkResponseType: wrong response type (received "
+                  << int(r.getResponse().which()) << ", expected " << int(type) << ")";
+                log(s.str());
+                throw ProtocolError("Wrong response type");
+            }
         }
     }
 
@@ -433,14 +444,9 @@
 
         auto karr = call(message, "load", false);
 
-        //!!! ... --> will also need some way to kill this process
-        //!!! (from another thread)
-
         capnp::FlatArrayMessageReader responseMessage(karr);
         piper::RpcResponse::Reader reader = responseMessage.getRoot<piper::RpcResponse>();
 
-        //!!! handle (explicit) error case
-
         checkResponseType(reader, piper::RpcResponse::Response::Which::LOAD, id);
         
         const piper::LoadResponse::Reader &lr = reader.getResponse().getLoad();