diff --git a/cmdline/EosCtaStub.cpp b/cmdline/EosCtaStub.cpp index 7badf903ebfb684c0800ad006533732bdc98bdd2..6775f2b2aac3e842ceec90ccb92a92b3b6767f45 100644 --- a/cmdline/EosCtaStub.cpp +++ b/cmdline/EosCtaStub.cpp @@ -69,6 +69,21 @@ void RequestCallback<eos::wfe::Alert>::operator()(const eos::wfe::Alert &alert) OutputJsonString(&alert); } + + +/*! + * Convert exceptions into Alerts. + * + * This tells the framework how to log exceptions received on the client side + */ + +template<> +void ExceptionToAlert<eos::wfe::Alert>::operator()(const std::exception &e, eos::wfe::Alert &alert) +{ + alert.set_audience(eos::wfe::Alert::EOSLOG); + alert.set_message_txt(e.what()); +} + } // namespace XrdSsiPb @@ -299,7 +314,7 @@ int exceptionThrowingMain(int argc, const char *const *const argv) std::cout << "Request sent, going to sleep..." << std::endl; - int wait_secs = 5; + int wait_secs = 20; while(wait_secs--) { diff --git a/eos/messages/eos_messages.proto b/eos/messages/eos_messages.proto index fcdc333f70d181f95bb7d881be52bd2b618b0265..3fb6c963f8975b8e746c8106abecbcd54f28bd36 100644 --- a/eos/messages/eos_messages.proto +++ b/eos/messages/eos_messages.proto @@ -40,7 +40,7 @@ message Security { message Alert { enum Audience { EOSLOG = 0; ENDUSER = 1; } Audience audience = 1; //< The intended audience of the error message - string message = 2; //< An empty if success, else an error message + string message_txt = 2; //< An empty if success, else an error message } diff --git a/xroot_plugins/XrdSsiCtaRequestProc.cpp b/xroot_plugins/XrdSsiCtaRequestProc.cpp index 6056e79db99ba8c32c1e94fa8e45147d8c03fa02..266ec775e60e4f142a218583b01244917cdb39ec 100644 --- a/xroot_plugins/XrdSsiCtaRequestProc.cpp +++ b/xroot_plugins/XrdSsiCtaRequestProc.cpp @@ -154,16 +154,14 @@ void RequestProc<eos::wfe::Notification, eos::wfe::Response, eos::wfe::Alert>::E template <> void RequestProc<eos::wfe::Notification, eos::wfe::Response, eos::wfe::Alert>::ExecuteAlerts() { - // Allocate alert messages on the heap, they are self-destructing + eos::wfe::Alert alert_msg; - auto *alert_msg = new eos::wfe::Alert(); + alert_msg.set_audience(eos::wfe::Alert::EOSLOG); + alert_msg.set_message_txt("Something bad happened"); - alert_msg->set_audience(eos::wfe::Alert::EOSLOG); - alert_msg->set_message("Something bad happened"); + // Serialize and send the alert message - // Send the alert message - - Alert(*alert_msg); + Alert(alert_msg); } @@ -187,7 +185,7 @@ void RequestProc<eos::wfe::Notification, eos::wfe::Response, eos::wfe::Alert>:: //case PB_PARSE_ERR: m_metadata.mutable_exception()->set_code(eos::wfe::Exception::PB_PARSE_ERR); //} - m_metadata.mutable_alert_msg()->set_message(err_text); + m_metadata.mutable_alert_msg()->set_message_txt(err_text); // Output message in Json format (for debugging) diff --git a/xroot_ssi_pb/XrdSsiPbRequest.h b/xroot_ssi_pb/XrdSsiPbRequest.h index 5e790d4bbeaeadda0ec76e59355a9fe940a00c7d..f1b2e85182be1ac125e7e4dbf0aee22735e13b51 100644 --- a/xroot_ssi_pb/XrdSsiPbRequest.h +++ b/xroot_ssi_pb/XrdSsiPbRequest.h @@ -26,7 +26,7 @@ namespace XrdSsiPb { /*! * XRootD SSI + Protocol Buffers Callback class * - * The client should specialize on this class for each XRootD reply type (Metadata, Alert, Error) + * The client should specialize on this class for each XRootD reply type (Metadata, Alert) */ template<typename CallbackArg> @@ -38,6 +38,21 @@ public: +/*! + * Convert Exceptions to Alerts + * + * The client should specialize on this class to specify how to log exceptions + */ + +template<typename AlertType> +class ExceptionToAlert +{ +public: + void operator()(const std::exception &e, AlertType &alert); +}; + + + /*! * XRootD SSI + Protocol Buffers Request class */ @@ -100,16 +115,21 @@ public: virtual XrdSsiRequest::PRD_Xeq ProcessResponseData(const XrdSsiErrInfo &eInfo, char *buff, int blen, bool last) override; /*! - * The Alert method is optional. By default, Alert messages are ignored. + * Deserialize Alert messages and call the Alert callback */ - virtual void Alert(XrdSsiRespInfoMsg &aMsg) override; + virtual void Alert(XrdSsiRespInfoMsg &alert_msg) override; + private: const char *m_request_bufptr; //!< Pointer to the Request buffer int m_request_len; //!< Size of the Request buffer int m_response_bufsize; //!< Size of the Response buffer + // Convert exceptions to Alerts. Must be defined on the client side. + + ExceptionToAlert<AlertType> ExceptionHandler; + // Callbacks for each of the XRootD reply types RequestCallback<MetadataType> MetadataCallback; @@ -136,40 +156,26 @@ bool Request<RequestType, MetadataType, AlertType>::ProcessResponse(const XrdSsi std::cout << "[DEBUG] ProcessResponse(): response type = " << rInfo.State() << std::endl; #endif - switch(rInfo.rType) - { + try { + switch(rInfo.rType) { + // Handle errors in the XRootD framework (e.g. no response from server) - case XrdSsiRespInfo::isError: - //ErrorCallback(eInfo.Get()); - Finished(); // Return control of the object to the calling thread and delete rInfo - - // Andy says it is now safe to delete the Request object, which implies that the pointer on the calling side - // will never refer to it again and the destructor of the base class doesn't access any class members. - - delete this; - break; - - case XrdSsiRespInfo::isHandle: - // To implement detached requests, add another callback type which saves the handle - //ErrorCallback("Detached requests are not implemented."); - Finished(); - delete this; - break; - - case XrdSsiRespInfo::isFile: - // To implement file requests, add another callback type - //ErrorCallback("File requests are not implemented."); - Finished(); - delete this; - break; - - case XrdSsiRespInfo::isStream: - // To implement stream requests, add another callback type - //ErrorCallback("Stream requests are not implemented."); - Finished(); - delete this; - break; + case XrdSsiRespInfo::isError: throw XrdSsiException(eInfo.Get()); + + // To implement detached requests, add another callback type which saves the handle + + case XrdSsiRespInfo::isHandle: throw XrdSsiException("Detached requests are not implemented."); + + // To implement file requests, add another callback type + + case XrdSsiRespInfo::isFile: throw XrdSsiException("File requests are not implemented."); + + // To implement stream requests, add another callback type + + case XrdSsiRespInfo::isStream: throw XrdSsiException("Stream requests are not implemented."); + + // Metadata-only responses and data responses case XrdSsiRespInfo::isNone: case XrdSsiRespInfo::isData: @@ -191,17 +197,14 @@ bool Request<RequestType, MetadataType, AlertType>::ProcessResponse(const XrdSsi } else { - //ErrorCallback("metadata.ParseFromArray() failed"); - Finished(); - delete this; - break; + throw PbException("metadata.ParseFromArray() failed"); } } - // If this is a metadata-only response, there is nothing more to do - if(rInfo.rType == XrdSsiRespInfo::isNone) { + // If this is a metadata-only response, we are done + Finished(); delete this; break; @@ -216,6 +219,24 @@ bool Request<RequestType, MetadataType, AlertType>::ProcessResponse(const XrdSsi GetResponseData(response_bufptr, m_response_bufsize); } + } + } + catch(std::exception &e) + { + // Pass the exception to the Alert callback to be logged + + AlertType alert; + ExceptionHandler(e, alert); + AlertCallback(alert); + + // Return control of the object to the calling thread and delete rInfo + + Finished(); + + // It is now safe to delete the Request object (which implies that the pointer on the calling side + // will never refer to it again and the destructor of the base class doesn't access any class members). + + delete this; } return true; @@ -231,22 +252,7 @@ XrdSsiRequest::PRD_Xeq Request<RequestType, MetadataType, AlertType> if(response_buflen != 0) { -#if 0 - // How do we handle message boundaries for multi-block responses? - - // Deserialize the response - - ResponseType response; - - if(response.ParseFromArray(response_bufptr, response_buflen)) - { - ResponseCallback(response); - } - else - { - ErrorCallback("response.ParseFromArray() failed"); - } -#endif + // Handle one block of response data } // If there is more data then get it, otherwise clean up @@ -287,15 +293,14 @@ void Request<RequestType, MetadataType, AlertType>::Alert(XrdSsiRespInfoMsg &ale AlertType alert; - if(alert.ParseFromArray(alert_buffer, alert_len)) + if(!alert.ParseFromArray(alert_buffer, alert_len)) { - AlertCallback(alert); - } - else - { - //ErrorCallback("alert.ParseFromArray() failed"); + PbException e("alert.ParseFromArray() failed"); + ExceptionHandler(e, alert); } + AlertCallback(alert); + // Recycle the message to free memory alert_msg.RecycleMsg();