Commit 7f74c7d5 authored by Steven Murray's avatar Steven Murray
Browse files

Put back legecay message handling of castor-tape-label command

parent 59644045
......@@ -300,7 +300,7 @@ void castor::tape::label::LabelCmd::writeTapeLabelRequest(const int timeout) {
char buf[REQBUFSZ];
const size_t len = castor::legacymsg::marshal(buf, sizeof(buf), body);
m_smartClientConnectionSock.reset(castor::io::connectWithTimeout("127.0.0.1",
castor::tape::tapeserver::daemon::TAPE_SERVER_MOUNTSESSION_LISTENING_PORT, timeout));
castor::tape::tapeserver::daemon::TAPE_SERVER_LABELCMD_LISTENING_PORT, timeout));
try {
castor::io::writeBytes(m_smartClientConnectionSock.get(), timeout, len, buf);
......
......@@ -14,6 +14,8 @@ add_library(castorTapeServerDaemon
DriveCatalogueEntry.cpp
../drive/Drive.cpp
GlobalStatusReporter.cpp
LabelCmdAcceptHandler.cpp
LabelCmdConnectionHandler.cpp
LabelSession.cpp
MigrationMemoryManager.cpp
MigrationReportPacker.cpp
......
......@@ -41,9 +41,10 @@ const unsigned short TAPE_SERVER_ADMIN_LISTENING_PORT = 5011;
/**
* The TCP/IP port on which the tape server daemon listens for incoming
* connections from the mount session.
* connections from the label command.
*/
const unsigned short TAPE_SERVER_MOUNTSESSION_LISTENING_PORT = 54321;
const unsigned short TAPE_SERVER_LABELCMD_LISTENING_PORT = 54321;
/*
* The port on which ZMQ sockets will bind for internal communication between
* motherforker and forked session
......
/******************************************************************************
* castor/tape/tapeserver/daemon/LabelCmdAcceptHandler.cpp
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 CERN
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* @author dkruse@cern.ch
*****************************************************************************/
#include "castor/exception/BadAlloc.hpp"
#include "castor/exception/Errnum.hpp"
#include "castor/io/io.hpp"
#include "castor/legacymsg/CommonMarshal.hpp"
#include "castor/legacymsg/legacymsg.hpp"
#include "castor/legacymsg/TapeMarshal.hpp"
#include "castor/tape/utils/utils.hpp"
#include "castor/tape/tapeserver/daemon/DriveCatalogue.hpp"
#include "castor/tape/tapeserver/daemon/LabelCmdAcceptHandler.hpp"
#include "castor/tape/tapeserver/daemon/LabelCmdConnectionHandler.hpp"
#include "castor/utils/SmartFd.hpp"
#include "h/common.h"
#include "h/Ctape.h"
#include "h/serrno.h"
#include "h/vdqm_api.h"
#include "h/vmgr_constants.h"
#include <errno.h>
#include <memory>
#include <list>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
castor::tape::tapeserver::daemon::LabelCmdAcceptHandler::LabelCmdAcceptHandler(
const int fd, reactor::ZMQReactor &reactor, log::Logger &log,
DriveCatalogue &driveCatalogue, const std::string &hostName,
castor::legacymsg::VdqmProxy & vdqm,
castor::legacymsg::VmgrProxy & vmgr) throw():
m_fd(fd),
m_reactor(reactor),
m_log(log),
m_driveCatalogue(driveCatalogue),
m_hostName(hostName),
m_vdqm(vdqm),
m_vmgr(vmgr),
m_netTimeout(10) {
}
//------------------------------------------------------------------------------
// destructor
//------------------------------------------------------------------------------
castor::tape::tapeserver::daemon::LabelCmdAcceptHandler::~LabelCmdAcceptHandler()
throw() {
log::Param params[] = {log::Param("fd", m_fd)};
m_log(LOG_DEBUG, "Closing label-command listen socket", params);
close(m_fd);
}
//------------------------------------------------------------------------------
// getFd
//------------------------------------------------------------------------------
int castor::tape::tapeserver::daemon::LabelCmdAcceptHandler::getFd() throw() {
return m_fd;
}
//------------------------------------------------------------------------------
// fillPollFd
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::LabelCmdAcceptHandler::fillPollFd(zmq::pollitem_t &fd) throw() {
fd.fd = m_fd;
fd.revents = 0;
fd.socket = NULL;
}
//------------------------------------------------------------------------------
// handleEvent
//------------------------------------------------------------------------------
bool castor::tape::tapeserver::daemon::LabelCmdAcceptHandler::handleEvent(
const zmq::pollitem_t &fd) {
logLabelCmdAcceptEvent(fd);
checkHandleEventFd(fd.fd);
// Accept the connection
castor::utils::SmartFd connection;
try {
const time_t acceptTimeout = 1; // Timeout in seconds
connection.reset(io::acceptConnection(fd.fd, acceptTimeout));
} catch(castor::exception::Exception &ne) {
castor::exception::Exception ex;
ex.getMessage() << "Failed to accept a connection from the admin command"
": " << ne.getMessage().str();
throw ex;
}
log::Param params[] = {log::Param("fd", connection.get())};
m_log(LOG_DEBUG, "Accepted a possible label-command connection", params);
// Create a new label-command connection handler
std::auto_ptr<LabelCmdConnectionHandler> connectionHandler;
try {
connectionHandler.reset(new LabelCmdConnectionHandler(connection.get(),
m_reactor, m_log, m_driveCatalogue, m_hostName, m_vdqm, m_vmgr));
connection.release();
} catch(std::bad_alloc &ba) {
castor::exception::BadAlloc ex;
ex.getMessage() <<
"Failed to allocate a new label-command connection handler: " <<
ba.what();
throw ex;
}
m_log(LOG_DEBUG, "Created a new label-command connection handler", params);
// Register the new label-command connection handler with the reactor
try {
m_reactor.registerHandler(connectionHandler.get());
connectionHandler.release();
} catch(castor::exception::Exception &ne) {
castor::exception::Exception ex;
ex.getMessage() <<
"Failed to register a new label-command connection handler: " <<
ne.getMessage().str();
throw ex;
}
m_log(LOG_DEBUG, "Registered the new label-command connection handler",
params);
return false; // Stay registered with the reactor
}
//------------------------------------------------------------------------------
// logLabelCmdAcceptConnectionEvent
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::LabelCmdAcceptHandler::
logLabelCmdAcceptEvent(const zmq::pollitem_t &fd) {
log::Param params[] = {
log::Param("fd", fd.fd),
log::Param("ZMQ_POLLIN", fd.revents & ZMQ_POLLIN ? "true" : "false"),
log::Param("ZMQ_POLLOUT", fd.revents & ZMQ_POLLOUT ? "true" : "false"),
log::Param("ZMQ_POLLERR", fd.revents & ZMQ_POLLERR ? "true" : "false")};
m_log(LOG_DEBUG, "I/O event on label-command connection socket", params);
}
//------------------------------------------------------------------------------
// checkHandleEventFd
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::LabelCmdAcceptHandler::
checkHandleEventFd(const int fd) {
if(m_fd != fd) {
castor::exception::Exception ex;
ex.getMessage() <<
"LabelCmdAcceptHandler passed wrong file descriptor"
": expected=" << m_fd << " actual=" << fd;
throw ex;
}
}
/******************************************************************************
* castor/tape/tapeserver/daemon/LabelCmdAcceptHandler.hpp
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 CERN
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* @author dkruse@cern.ch
*****************************************************************************/
#pragma once
#include "castor/legacymsg/MessageHeader.hpp"
#include "castor/legacymsg/VdqmProxy.hpp"
#include "castor/legacymsg/VmgrProxy.hpp"
#include "castor/log/Logger.hpp"
#include "castor/tape/reactor/ZMQReactor.hpp"
#include "castor/tape/tapeserver/daemon/DriveCatalogue.hpp"
namespace castor {
namespace tape {
namespace tapeserver {
namespace daemon {
/**
* Handles the events of the socket listening for connectiosn from the label
* tape command.
*/
class LabelCmdAcceptHandler: public reactor::ZMQPollEventHandler {
public:
/**
* Constructor.
*
* @param fd The file descriptor of the socket listening for
* connections from the mount session
* @param reactor The reactor to which new connection handlers are to be
* registered.
* @param log The object representing the API of the CASTOR logging system.
* @param driveCatalogue The catalogue of tape drives controlled by the tape
* server daemon.
*/
LabelCmdAcceptHandler(const int fd,
reactor::ZMQReactor &reactor,
log::Logger &log,
DriveCatalogue &driveCatalogue,
const std::string &hostName,
castor::legacymsg::VdqmProxy & vdqm,
castor::legacymsg::VmgrProxy & vmgr) throw();
/**
* Returns the integer file descriptor of this event handler.
*/
int getFd() throw();
/**
* Fills the specified poll file-descriptor ready to be used in a call to
* poll().
*/
void fillPollFd(zmq::pollitem_t &fd) throw();
/**
* Handles the specified event.
*
* @param fd The poll file-descriptor describing the event.
* @return true if the event handler should be removed from and deleted by
* the reactor.
*/
bool handleEvent(const zmq::pollitem_t &fd);
/**
* Destructor.
*/
~LabelCmdAcceptHandler() throw();
private:
/**
* Logs the specifed IO event of the label-command listen-socket.
*/
void logLabelCmdAcceptEvent(const zmq::pollitem_t &fd);
/**
* Throws an exception if the specified file-descriptor does not match the
* file-descriptor of this event handler.
*
* @param fd The file descriptor to be checked.
*/
void checkHandleEventFd(const int fd);
/**
* The file descriptor of the socket listening for label-command
* connections.
*/
const int m_fd;
/**
* The reactor to which new Vdqm connection handlers are to be registered.
*/
reactor::ZMQReactor &m_reactor;
/**
* The object representing the API of the CASTOR logging system.
*/
log::Logger &m_log;
/**
* The catalogue of tape drives controlled by the tape server daemon.
*/
DriveCatalogue &m_driveCatalogue;
/**
* The name of the host on which tape daemon is running.
*/
const std::string m_hostName;
/**
* Reference to the VdqmProxy, allowing reporting of the drive status. It
* will be used by the StatusReporter
*/
castor::legacymsg::VdqmProxy & m_vdqm;
/**
* Reference to the VmgrProxy, allowing reporting and checking tape status.
* It is also used by the StatusReporter
*/
castor::legacymsg::VmgrProxy & m_vmgr;
/**
* The timeout in seconds to be applied when performing network read and
* write operations.
*/
const int m_netTimeout;
}; // class VdqmAcceptHandler
} // namespace daemon
} // namespace tapeserver
} // namespace tape
} // namespace castor
/******************************************************************************
* castor/tape/tapeserver/daemon/LabelCmdConnectionHandler.cpp
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 CERN
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* @author dkruse@cern.ch
*****************************************************************************/
#include "castor/exception/BadAlloc.hpp"
#include "castor/exception/Errnum.hpp"
#include "castor/io/io.hpp"
#include "castor/legacymsg/CommonMarshal.hpp"
#include "castor/legacymsg/legacymsg.hpp"
#include "castor/legacymsg/TapeMarshal.hpp"
#include "castor/tape/utils/utils.hpp"
#include "castor/tape/tapeserver/daemon/DriveCatalogue.hpp"
#include "castor/tape/tapeserver/daemon/LabelCmdConnectionHandler.hpp"
#include "castor/utils/SmartFd.hpp"
#include "h/common.h"
#include "h/serrno.h"
#include "h/Ctape.h"
#include "h/vdqm_api.h"
#include "h/vmgr_constants.h"
#include <errno.h>
#include <fcntl.h>
#include <memory>
#include <list>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
castor::tape::tapeserver::daemon::LabelCmdConnectionHandler::LabelCmdConnectionHandler(
const int fd, reactor::ZMQReactor &reactor, log::Logger &log,
DriveCatalogue &driveCatalogue, const std::string &hostName,
castor::legacymsg::VdqmProxy & vdqm,
castor::legacymsg::VmgrProxy & vmgr) throw():
m_fd(fd),
m_thisEventHandlerOwnsFd(true),
m_reactor(reactor),
m_log(log),
m_driveCatalogue(driveCatalogue),
m_hostName(hostName),
m_vdqm(vdqm),
m_vmgr(vmgr),
m_netTimeout(10) { // Timeout in seconds
}
//------------------------------------------------------------------------------
// destructor
//------------------------------------------------------------------------------
castor::tape::tapeserver::daemon::LabelCmdConnectionHandler::
~LabelCmdConnectionHandler() throw() {
if(m_thisEventHandlerOwnsFd) {
log::Param params[] = {log::Param("fd", m_fd)};
m_log(LOG_DEBUG, "Closing label-command connection", params);
close(m_fd);
}
}
//------------------------------------------------------------------------------
// getFd
//------------------------------------------------------------------------------
int castor::tape::tapeserver::daemon::LabelCmdConnectionHandler::getFd() throw() {
return m_fd;
}
//------------------------------------------------------------------------------
// fillPollFd
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::LabelCmdConnectionHandler::fillPollFd(zmq::pollitem_t &fd) throw() {
fd.fd = m_fd;
fd.revents = 0;
fd.socket = NULL;
}
//------------------------------------------------------------------------------
// handleEvent
//------------------------------------------------------------------------------
bool castor::tape::tapeserver::daemon::LabelCmdConnectionHandler::handleEvent(
const zmq::pollitem_t &fd) {
logLabelCmdConnectionEvent(fd);
checkHandleEventFd(fd.fd);
std::list<log::Param> params;
params.push_back(log::Param("fd", m_fd));
try {
const legacymsg::MessageHeader header = readMsgHeader();
handleRequest(header);
} catch(castor::exception::Exception &ex) {
params.push_back(log::Param("message", ex.getMessage().str()));
m_log(LOG_ERR, "Failed to handle IO event on label-command connection",
params);
}
m_log(LOG_DEBUG, "Asking reactor to remove and delete"
" LabelCmdConnectionHandler", params);
return true; // Ask reactor to remove and delete this handler
}
//------------------------------------------------------------------------------
// logLabelCmdConnectionEvent
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::LabelCmdConnectionHandler::
logLabelCmdConnectionEvent(const zmq::pollitem_t &fd) {
log::Param params[] = {
log::Param("fd", fd.fd),
log::Param("ZMQ_POLLIN", fd.revents & ZMQ_POLLIN ? "true" : "false"),
log::Param("ZMQ_POLLOUT", fd.revents & ZMQ_POLLOUT ? "true" : "false"),
log::Param("ZMQ_POLLERR", fd.revents & ZMQ_POLLERR ? "true" : "false")};
m_log(LOG_DEBUG, "I/O event on label-command connection", params);
}
//------------------------------------------------------------------------------
// checkHandleEventFd
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::LabelCmdConnectionHandler::
checkHandleEventFd(const int fd) {
if(m_fd != fd) {
castor::exception::Exception ex;
ex.getMessage() <<
"LabelCmdConnectionHandler passed wrong file descriptor"
": expected=" << m_fd << " actual=" << fd;
throw ex;
}
}
//------------------------------------------------------------------------------
// readMsgHeader
//------------------------------------------------------------------------------
castor::legacymsg::MessageHeader castor::tape::tapeserver::daemon::
LabelCmdConnectionHandler::readMsgHeader() {
// Read in the message header
char buf[3 * sizeof(uint32_t)]; // magic + request type + len
io::readBytes(m_fd, m_netTimeout, sizeof(buf), buf);
const char *bufPtr = buf;
size_t bufLen = sizeof(buf);
legacymsg::MessageHeader header;
memset(&header, '\0', sizeof(header));
legacymsg::unmarshal(bufPtr, bufLen, header);
if(TPMAGIC != header.magic) {
castor::exception::Exception ex;
ex.getMessage() << "Invalid admin job message: Invalid magic"
": expected=0x" << std::hex << TPMAGIC << " actual=0x" <<
header.magic;
throw ex;
}
// The length of the message body is checked later, just before it is read in
// to memory
return header;
}
//------------------------------------------------------------------------------
// handleRequest
//------------------------------------------------------------------------------
void
castor::tape::tapeserver::daemon::LabelCmdConnectionHandler::handleRequest(
const legacymsg::MessageHeader &header) {
switch(header.reqType) {
case TPLABEL:
handleLabelRequest(header);
break;
default:
{
castor::exception::Exception ex;
ex.getMessage() << "Failed to handle label-command request"
": Unknown request type: reqType=" << header.reqType;
throw ex;
}
}
}
//------------------------------------------------------------------------------
// handleLabelRequest
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::LabelCmdConnectionHandler::
handleLabelRequest(const legacymsg::MessageHeader &header) {
const char *const task = "handle incoming label job";
try {
// Read message body
const uint32_t totalLen = header.lenOrStatus;
const uint32_t headerLen = 3 * sizeof(uint32_t); // magic, type and length
const uint32_t bodyLen = totalLen - headerLen;
const legacymsg::TapeLabelRqstMsgBody body = readLabelRqstMsgBody(bodyLen);
logLabelRequest(body);
// Try to inform the drive catalogue of the reception of the label job
DriveCatalogueEntry &drive = m_driveCatalogue.findDrive(body.drive);
drive.receivedLabelJob(body, m_fd);
// The drive catalogue will now remember and own the client connection,
// therefore it is now safe and necessary for this connection handler to
// relinquish ownership of the connection
m_thisEventHandlerOwnsFd = false;
{
log::Param params[] = {log::Param("fd", m_fd)};
m_log(LOG_DEBUG, "Mount-session handler released label connection",
params);
}
} catch(castor::exception::Exception &ex) {
log::Param params[] = {log::Param("message", ex.getMessage().str())};
m_log(LOG_ERR, "Informing client label-command of error", params);
// Inform the client there was an error
try {
legacymsg::writeTapeReplyMsg(m_netTimeout, m_fd, 1,
ex.getMessage().str());