Commit df6132cc authored by David COME's avatar David COME
Browse files

Added a mechanism to send error to the client when the server has an exception

parent c2641b20
......@@ -209,7 +209,9 @@ void castor::tape::tapeserver::daemon::TapeMessageHandler::dispatchEvent(
}
}
//------------------------------------------------------------------------------
// dealWith
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::TapeMessageHandler::dealWith(
const castor::messages::Header& header, const castor::messages::Heartbeat& body){
......@@ -229,9 +231,13 @@ const castor::messages::NotifyDriveBeforeMountStarted& body){
legacymsg::VmgrTapeInfoMsgBody tapeInfo;
m_vmgr.queryTape(body.vid(), tapeInfo);
// If the client is the tape gateway and the volume is not marked as BUSY
if(body.clienttype() == castor::messages::NotifyDriveBeforeMountStarted::CLIENT_TYPE_GATEWAY && !(tapeInfo.status & TAPE_BUSY)) {
if(body.clienttype() == castor::messages::NotifyDriveBeforeMountStarted::CLIENT_TYPE_GATEWAY
&& !(tapeInfo.status & TAPE_BUSY)) {
castor::exception::Exception ex;
ex.getMessage() << "The tape gateway is the client and the tape to be mounted is not BUSY: vid=" << body.vid();
//send an error to the client
sendErrorReplyToClient(ex);
throw ex;
}
......@@ -243,13 +249,18 @@ const castor::messages::NotifyDriveBeforeMountStarted& body){
header.set_bodyhashvalue(castor::messages::computeSHA1Base64(body));
header.set_bodysignature("PIPO");
//send the number of files on the tape to the client
castor::messages::sendMessage(m_socket,header,ZMQ_SNDMORE);
castor::messages::sendMessage(m_socket,body);
} else {
//we were not event in castor::messages::TAPE_MODE_READWRITE mpde
//so send empty answer
sendSuccessReplyToClient();
}
}
//------------------------------------------------------------------------------
// dealWith
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::TapeMessageHandler::dealWith(
const castor::messages::Header& header,
const castor::messages::NotifyDriveTapeMounted& body){
......@@ -259,33 +270,57 @@ const castor::messages::NotifyDriveTapeMounted& body){
const utils::DriveConfig &driveConfig = drive->getConfig();
const std::string vid = body.vid();
switch(body.mode()) {
case castor::messages::TAPE_MODE_READ:
m_vmgr.tapeMountedForRead(vid);
break;
case castor::messages::TAPE_MODE_READWRITE:
m_vmgr.tapeMountedForWrite(vid);
break;
case castor::messages::TAPE_MODE_DUMP:
m_vmgr.tapeMountedForRead(vid);
break;
case castor::messages::TAPE_MODE_NONE:
break;
default:
castor::exception::Exception ex;
ex.getMessage() << "Unknown tape mode: " << body.mode();
throw ex;
try
{
switch(body.mode()) {
case castor::messages::TAPE_MODE_READ:
m_vmgr.tapeMountedForRead(vid);
break;
case castor::messages::TAPE_MODE_READWRITE:
m_vmgr.tapeMountedForWrite(vid);
break;
case castor::messages::TAPE_MODE_DUMP:
m_vmgr.tapeMountedForRead(vid);
break;
case castor::messages::TAPE_MODE_NONE:
break;
default:
castor::exception::Exception ex;
ex.getMessage() << "Unknown tape mode: " << body.mode();
throw ex;
}
m_vdqm.tapeMounted(m_hostName, body.unitname(), driveConfig.dgn, body.vid(),
drive->getSessionPid());
}catch(const castor::exception::Exception& ex){
sendErrorReplyToClient(ex);
throw;
}
m_vdqm.tapeMounted(m_hostName, body.unitname(), driveConfig.dgn, body.vid(),
drive->getSessionPid());
sendSuccessReplyToClient();
}
//------------------------------------------------------------------------------
// sendSuccessReplyToClient
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::TapeMessageHandler::sendSuccessReplyToClient(){
castor::messages::ReturnValue body;
body.set_returnvalue(0);
body.set_message("");
sendReplyToClient(0,"");
}
//------------------------------------------------------------------------------
// sendErrorReplyToClient
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::TapeMessageHandler::
sendErrorReplyToClient(const castor::exception::Exception& ex){
//any positive value will trigger an exception in the client side
sendReplyToClient(ex.code(),ex.getMessageValue());
}
//------------------------------------------------------------------------------
// sendReplyToClient
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::TapeMessageHandler::
sendReplyToClient(int returnValue,const std::string& msg){
castor::messages::ReturnValue body;
body.set_returnvalue(returnValue);
body.set_message(msg);
castor::messages::Header header = castor::messages::preFillHeader();
header.set_reqtype(messages::reqType::ReturnValue);
......@@ -294,4 +329,4 @@ void castor::tape::tapeserver::daemon::TapeMessageHandler::sendSuccessReplyToCli
castor::messages::sendMessage(m_socket,header,ZMQ_SNDMORE);
castor::messages::sendMessage(m_socket,body);
}
}
\ No newline at end of file
......@@ -93,8 +93,30 @@ public:
bool handleEvent(const zmq_pollitem_t &fd);
private:
/**
* Send to the client a ReturnValue(0,"")
*/
void sendSuccessReplyToClient();
/**
* Send to the client a ReturnValue(ex.code(),ex.getGetMessageValue())
* @param e
*/
void sendErrorReplyToClient(const castor::exception::Exception& e);
/**
* Send to the client a ReturnValue Message with the given parameters
* @param returnValue the interger value to send (0 = everything ok,
* positive integer will trigger an exception
* @param msg The string to display (should be empty if returnValue=0)
*/
void sendReplyToClient(int returnValue,const std::string& msg);
/**
* Will try to parse a message of type T into msg from the data which are
* within blob
* @param msg
* @param blob
*/
template <class T> void unserialize(T& msg, tape::utils::ZmqMsg& blob){
std::string logMessage="Cant parse " ;
logMessage+=castor::utils::demangledNameOf(msg)+" from binary data. Wrong body";
......@@ -126,7 +148,7 @@ private:
const std::string m_hostName;
/**
* Reference to the VdqmProxy, allowing reporting of the drive status. It
* Reference to the VdqmProxy, allowing reporting of the drive status. It
* will be used by the StatusReporter
*/
castor::legacymsg::VdqmProxy & m_vdqm;
......@@ -137,8 +159,17 @@ private:
*/
castor::legacymsg::VmgrProxy & m_vmgr;
/**
* Make sure the zmq_pollitem_t's socket is the same as m_socket
* Throw an exception if it is not the case
* @param fd the poll item
*/
void checkSocket(const zmq_pollitem_t &fd);
/**
* Call the right dealWith according to header.reqType()
* @param header
*/
void dispatchEvent(castor::messages::Header& header);
void dealWith(const castor::messages::Header&,
......@@ -147,12 +178,12 @@ private:
void dealWith(const castor::messages::Header& header,
const castor::messages::NotifyDriveBeforeMountStarted& body);
void dealWith(const castor::messages::Header& header,
void dealWith(const castor::messages::Header& header,
const castor::messages::NotifyDriveTapeMounted& body);
/**
* Unserialise the blob and check the header
* @param headerBlob
* Unserialize the blob and check the header
* @param headerBlob The blob from the header
*/
castor::messages::Header buildHeader(tape::utils::ZmqMsg& headerBlob);
}; // class TapeMessageHandler
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment