Mercurial > hg > piper-cpp
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()); |