comparison 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
comparison
equal deleted inserted replaced
169:f13dc1db2229 170:590b1a1fd955
141 ListResponse 141 ListResponse
142 listPluginData(const ListRequest &req) override { 142 listPluginData(const ListRequest &req) override {
143 143
144 LOG_E("CapnpRRClient::listPluginData called"); 144 LOG_E("CapnpRRClient::listPluginData called");
145 145
146 if (!m_transport->isOK()) { 146 checkServerOK();
147 log("Piper server crashed or failed to start (caller should have checked this)"); 147
148 throw std::runtime_error("Piper server crashed or failed to start");
149 }
150
151 capnp::MallocMessageBuilder message; 148 capnp::MallocMessageBuilder message;
152 piper::RpcRequest::Builder builder = message.initRoot<piper::RpcRequest>(); 149 piper::RpcRequest::Builder builder = message.initRoot<piper::RpcRequest>();
153 VampnProto::buildRpcRequest_List(builder, req); 150 VampnProto::buildRpcRequest_List(builder, req);
154 ReqId id = getId(); 151 ReqId id = getId();
155 builder.getId().setNumber(id); 152 builder.getId().setNumber(id);
172 LoadResponse 169 LoadResponse
173 loadPlugin(const LoadRequest &req) override { 170 loadPlugin(const LoadRequest &req) override {
174 171
175 LOG_E("CapnpRRClient::loadPlugin called"); 172 LOG_E("CapnpRRClient::loadPlugin called");
176 173
177 if (!m_transport->isOK()) { 174 checkServerOK();
178 log("Piper server crashed or failed to start (caller should have checked this)"); 175
179 throw std::runtime_error("Piper server crashed or failed to start");
180 }
181
182 LoadResponse resp; 176 LoadResponse resp;
183 PluginHandleMapper::Handle handle = serverLoad(req.pluginKey, 177 PluginHandleMapper::Handle handle = serverLoad(req.pluginKey,
184 req.inputSampleRate, 178 req.inputSampleRate,
185 req.adapterFlags, 179 req.adapterFlags,
186 resp.staticData, 180 resp.staticData,
208 Vamp::Plugin::OutputList 202 Vamp::Plugin::OutputList
209 configure(PluginStub *plugin, 203 configure(PluginStub *plugin,
210 PluginConfiguration config) override { 204 PluginConfiguration config) override {
211 205
212 LOG_E("CapnpRRClient::configure called"); 206 LOG_E("CapnpRRClient::configure called");
213 207
214 if (!m_transport->isOK()) { 208 checkServerOK();
215 log("Piper server crashed or failed to start (caller should have checked this)"); 209
216 throw std::runtime_error("Piper server crashed or failed to start");
217 }
218
219 ConfigurationRequest request; 210 ConfigurationRequest request;
220 request.plugin = plugin; 211 request.plugin = plugin;
221 request.configuration = config; 212 request.configuration = config;
222 213
223 capnp::MallocMessageBuilder message; 214 capnp::MallocMessageBuilder message;
229 220
230 auto karr = call(message, "configure", true); 221 auto karr = call(message, "configure", true);
231 222
232 capnp::FlatArrayMessageReader responseMessage(karr); 223 capnp::FlatArrayMessageReader responseMessage(karr);
233 piper::RpcResponse::Reader reader = responseMessage.getRoot<piper::RpcResponse>(); 224 piper::RpcResponse::Reader reader = responseMessage.getRoot<piper::RpcResponse>();
234
235 //!!! handle (explicit) error case
236 225
237 checkResponseType(reader, piper::RpcResponse::Response::Which::CONFIGURE, id); 226 checkResponseType(reader, piper::RpcResponse::Response::Which::CONFIGURE, id);
238 227
239 ConfigurationResponse cr; 228 ConfigurationResponse cr;
240 VampnProto::readConfigurationResponse(cr, 229 VampnProto::readConfigurationResponse(cr,
252 std::vector<std::vector<float> > inputBuffers, 241 std::vector<std::vector<float> > inputBuffers,
253 Vamp::RealTime timestamp) override { 242 Vamp::RealTime timestamp) override {
254 243
255 LOG_E("CapnpRRClient::process called"); 244 LOG_E("CapnpRRClient::process called");
256 245
257 if (!m_transport->isOK()) { 246 checkServerOK();
258 log("Piper server crashed or failed to start (caller should have checked this)"); 247
259 throw std::runtime_error("Piper server crashed or failed to start");
260 }
261
262 ProcessRequest request; 248 ProcessRequest request;
263 request.plugin = plugin; 249 request.plugin = plugin;
264 request.inputBuffers = inputBuffers; 250 request.inputBuffers = inputBuffers;
265 request.timestamp = timestamp; 251 request.timestamp = timestamp;
266 252
273 auto karr = call(message, "process", false); 259 auto karr = call(message, "process", false);
274 260
275 capnp::FlatArrayMessageReader responseMessage(karr); 261 capnp::FlatArrayMessageReader responseMessage(karr);
276 piper::RpcResponse::Reader reader = responseMessage.getRoot<piper::RpcResponse>(); 262 piper::RpcResponse::Reader reader = responseMessage.getRoot<piper::RpcResponse>();
277 263
278 //!!! handle (explicit) error case
279
280 checkResponseType(reader, piper::RpcResponse::Response::Which::PROCESS, id); 264 checkResponseType(reader, piper::RpcResponse::Response::Which::PROCESS, id);
281 265
282 ProcessResponse pr; 266 ProcessResponse pr;
283 VampnProto::readProcessResponse(pr, 267 VampnProto::readProcessResponse(pr,
284 reader.getResponse().getProcess(), 268 reader.getResponse().getProcess(),
292 virtual Vamp::Plugin::FeatureSet 276 virtual Vamp::Plugin::FeatureSet
293 finish(PluginStub *plugin) override { 277 finish(PluginStub *plugin) override {
294 278
295 LOG_E("CapnpRRClient::finish called"); 279 LOG_E("CapnpRRClient::finish called");
296 280
297 if (!m_transport->isOK()) { 281 checkServerOK();
298 log("Piper server crashed or failed to start (caller should have checked this)"); 282
299 throw std::runtime_error("Piper server crashed or failed to start");
300 }
301
302 FinishRequest request; 283 FinishRequest request;
303 request.plugin = plugin; 284 request.plugin = plugin;
304 285
305 capnp::MallocMessageBuilder message; 286 capnp::MallocMessageBuilder message;
306 piper::RpcRequest::Builder builder = message.initRoot<piper::RpcRequest>(); 287 piper::RpcRequest::Builder builder = message.initRoot<piper::RpcRequest>();
311 292
312 auto karr = call(message, "finish", true); 293 auto karr = call(message, "finish", true);
313 294
314 capnp::FlatArrayMessageReader responseMessage(karr); 295 capnp::FlatArrayMessageReader responseMessage(karr);
315 piper::RpcResponse::Reader reader = responseMessage.getRoot<piper::RpcResponse>(); 296 piper::RpcResponse::Reader reader = responseMessage.getRoot<piper::RpcResponse>();
316
317 //!!! handle (explicit) error case
318 297
319 checkResponseType(reader, piper::RpcResponse::Response::Which::FINISH, id); 298 checkResponseType(reader, piper::RpcResponse::Response::Which::FINISH, id);
320 299
321 FinishResponse pr; 300 FinishResponse pr;
322 VampnProto::readFinishResponse(pr, 301 VampnProto::readFinishResponse(pr,
339 318
340 // Reload the plugin on the server side, and configure it as requested 319 // Reload the plugin on the server side, and configure it as requested
341 320
342 log("CapnpRRClient: reset() called, plugin will be closed and reloaded"); 321 log("CapnpRRClient: reset() called, plugin will be closed and reloaded");
343 322
344 if (!m_transport->isOK()) { 323 checkServerOK();
345 log("Piper server crashed or failed to start (caller should have checked this)"); 324
346 throw std::runtime_error("Piper server crashed or failed to start");
347 }
348
349 if (m_mapper.havePlugin(plugin)) { 325 if (m_mapper.havePlugin(plugin)) {
350 (void)finish(plugin); // server-side unload 326 (void)finish(plugin); // server-side unload
351 } 327 }
352 328
353 PluginStaticData psd; 329 PluginStaticData psd;
382 memcpy(karr.begin(), buffer.data(), words * wordSize); 358 memcpy(karr.begin(), buffer.data(), words * wordSize);
383 return karr; 359 return karr;
384 } 360 }
385 361
386 void 362 void
363 checkServerOK() {
364 if (!m_transport->isOK()) {
365 log("Piper server crashed or failed to start (caller should have checked this)");
366 throw ServerCrashed();
367 }
368 }
369
370 /**
371 * Check (i) that the response has the same id as supplied (which
372 * presumably is the corresponding request id) and (ii) that the
373 * response has the expected type.
374 *
375 * Return only if both of these things are the case.
376 *
377 * If the response has the right id but is an error response,
378 * throw a ServiceError exception with the error response's
379 * message in it.
380 *
381 * If the response has the wrong id, or if it has the wrong type
382 * and is not an error response, throw ProtocolError. (i.e. for
383 * cases having errors that are not conveyed through our official
384 * error response.)
385 */
386 void
387 checkResponseType(const piper::RpcResponse::Reader &r, 387 checkResponseType(const piper::RpcResponse::Reader &r,
388 piper::RpcResponse::Response::Which type, 388 piper::RpcResponse::Response::Which type,
389 ReqId id) { 389 ReqId id) {
390 390
391 if (r.getResponse().which() != type) {
392 std::ostringstream s;
393 s << "checkResponseType: wrong response type (received "
394 << int(r.getResponse().which()) << ", expected " << int(type) << ")";
395 log(s.str());
396 throw std::runtime_error("Wrong response type");
397 }
398 if (ReqId(r.getId().getNumber()) != id) { 391 if (ReqId(r.getId().getNumber()) != id) {
399 std::ostringstream s; 392 std::ostringstream s;
400 s << "checkResponseType: wrong response id (received " 393 s << "checkResponseType: wrong response id (received "
401 << r.getId().getNumber() << ", expected " << id << ")"; 394 << r.getId().getNumber() << ", expected " << id << ")";
402 log(s.str()); 395 log(s.str());
403 throw std::runtime_error("Wrong response id"); 396 throw ProtocolError("Wrong response id");
397 }
398 if (r.getResponse().which() != type) {
399 if (r.getResponse().which() == piper::RpcResponse::Response::Which::ERROR) {
400 int code;
401 std::string message;
402 VampnProto::readRpcResponse_Error(code, message, r);
403 std::ostringstream s;
404 s << "checkResponseType: received an error with message: "
405 << message;
406 log(s.str());
407 throw ServiceError(message);
408 } else {
409 std::ostringstream s;
410 s << "checkResponseType: wrong response type (received "
411 << int(r.getResponse().which()) << ", expected " << int(type) << ")";
412 log(s.str());
413 throw ProtocolError("Wrong response type");
414 }
404 } 415 }
405 } 416 }
406 417
407 kj::Array<capnp::word> 418 kj::Array<capnp::word>
408 call(capnp::MallocMessageBuilder &message, std::string type, bool slow) { 419 call(capnp::MallocMessageBuilder &message, std::string type, bool slow) {
431 ReqId id = getId(); 442 ReqId id = getId();
432 builder.getId().setNumber(id); 443 builder.getId().setNumber(id);
433 444
434 auto karr = call(message, "load", false); 445 auto karr = call(message, "load", false);
435 446
436 //!!! ... --> will also need some way to kill this process
437 //!!! (from another thread)
438
439 capnp::FlatArrayMessageReader responseMessage(karr); 447 capnp::FlatArrayMessageReader responseMessage(karr);
440 piper::RpcResponse::Reader reader = responseMessage.getRoot<piper::RpcResponse>(); 448 piper::RpcResponse::Reader reader = responseMessage.getRoot<piper::RpcResponse>();
441
442 //!!! handle (explicit) error case
443 449
444 checkResponseType(reader, piper::RpcResponse::Response::Which::LOAD, id); 450 checkResponseType(reader, piper::RpcResponse::Response::Which::LOAD, id);
445 451
446 const piper::LoadResponse::Reader &lr = reader.getResponse().getLoad(); 452 const piper::LoadResponse::Reader &lr = reader.getResponse().getLoad();
447 VampnProto::readExtractorStaticData(psd, lr.getStaticData()); 453 VampnProto::readExtractorStaticData(psd, lr.getStaticData());