Commit 5b5500a6 authored by Steven Murray's avatar Steven Murray
Browse files

First step of refactoring the drive-catalogue tape-sessions

Please note that the "integration" code of tapserverd is not fully
functional.  One should however be able to run a data transfer
session.
parent 8b17b0cb
......@@ -701,8 +701,7 @@ bool castor::io::readBytesFromCloseable(
const int socketFd,
const int timeout,
const int nbBytes,
char *const buf)
{
char *const buf) {
// Throw an exception if socketFd is invalid
if(socketFd < 0) {
......
......@@ -65,10 +65,34 @@ void castor::tape::reactor::ZMQReactor::registerHandler(
ZMQPollEventHandler *const handler) {
zmq_pollitem_t item;
handler->fillPollFd(item);
//TODO, handle double registration
std::ostringstream socketInHex;
socketInHex << std::hex << item.socket;
log::Param params[] = {log::Param("fd", item.fd),
log::Param("socket", socketInHex)};
m_log(LOG_DEBUG, "ZMQReactor registering a new handler", params);
checkDoubleRegistration(item);
m_handlers.push_back(std::make_pair(item,handler));
}
//------------------------------------------------------------------------------
// checkDoubleRegistration
//------------------------------------------------------------------------------
void castor::tape::reactor::ZMQReactor::checkDoubleRegistration(
const zmq_pollitem_t &item) const {
for(HandlerMap::const_iterator it=m_handlers.begin(); it!=m_handlers.end();
++it) {
const std::pair<zmq_pollitem_t, ZMQPollEventHandler*> &maplet = *it;
if(item == maplet.first) {
castor::exception::Exception ex;
ex.getMessage() << "ZMQReactor detected a double registration: fd=" <<
item.fd << " socket=" << std::hex << item.socket;
throw ex;
}
}
}
//------------------------------------------------------------------------------
// handleEvents
//------------------------------------------------------------------------------
......
......@@ -91,6 +91,14 @@ private:
typedef std::vector<std::pair<zmq_pollitem_t, ZMQPollEventHandler*> >
HandlerMap;
/**
* Throws a cator::exception::Exception if a handler has already been
* registered for the specified poll item.
*
* @prama item The poll item.
*/
void checkDoubleRegistration(const zmq_pollitem_t &item) const;
/**
* Builds the vector of file descriptors to be passed to poll().
*
......
......@@ -188,8 +188,8 @@ void castor::tape::tapeserver::daemon::AdminConnectionHandler::
const std::string unitName(body.drive);
DriveCatalogueEntry *drive = m_driveCatalogue.findDrive(unitName);
const utils::DriveConfig &driveConfig = drive->getConfig();
DriveCatalogueEntry &drive = m_driveCatalogue.findDrive(unitName);
const utils::DriveConfig &driveConfig = drive.getConfig();
log::Param params[] = {
log::Param("unitName", unitName),
......@@ -198,18 +198,19 @@ void castor::tape::tapeserver::daemon::AdminConnectionHandler::
switch(body.status) {
case CONF_UP:
m_vdqm.setDriveUp(m_hostName, unitName, driveConfig.dgn);
drive->configureUp();
drive.configureUp();
m_log(LOG_INFO, "Drive configured up", params);
break;
case CONF_DOWN:
m_vdqm.setDriveDown(m_hostName, unitName, driveConfig.dgn);
drive->configureDown();
drive.configureDown();
m_log(LOG_INFO, "Drive configured down", params);
break;
default:
{
castor::exception::Exception ex;
ex.getMessage() << "Failed to configure drive. Reason: wrong drive status requested: " << body.status;
ex.getMessage() << "Failed to configure drive"
": Unexpected drive status requested: status=" << body.status;
throw ex;
}
}
......@@ -311,8 +312,8 @@ void castor::tape::tapeserver::daemon::AdminConnectionHandler::
for(std::list<std::string>::const_iterator itor = unitNames.begin();
itor!=unitNames.end() and i<CA_MAXNBDRIVES; itor++) {
const std::string &unitName = *itor;
const DriveCatalogueEntry * drive = m_driveCatalogue.findDrive(unitName);
body.drives[i] = drive->getTapeStatDriveEntry();
const DriveCatalogueEntry &drive = m_driveCatalogue.findDrive(unitName);
body.drives[i] = drive.getTapeStatDriveEntry();
i++;
}
......
......@@ -26,6 +26,7 @@ add_library(castorTapeServerDaemon
ProcessForker.cpp
ProcessForkerConnectionHandler.cpp
ProcessForkerProxy.cpp
ProcessForkerProxyDummy.cpp
ProcessForkerProxySocket.cpp
ProcessForkerUtils.cpp
RecallMemoryManager.cpp
......
......@@ -27,6 +27,22 @@
#include <string.h>
#include <time.h>
//-----------------------------------------------------------------------------
// constructor
//-----------------------------------------------------------------------------
castor::tape::tapeserver::daemon::DriveCatalogue::DriveCatalogue(
log::Logger &log,
const DataTransferSession::CastorConf &dataTransferConfig,
ProcessForkerProxy &processForker,
legacymsg::VdqmProxy &vdqm,
const std::string &hostName):
m_log(log),
m_dataTransferConfig(dataTransferConfig),
m_processForker(processForker),
m_vdqm(vdqm),
m_hostName(hostName) {
}
//-----------------------------------------------------------------------------
// destructor
//-----------------------------------------------------------------------------
......@@ -81,7 +97,8 @@ void castor::tape::tapeserver::daemon::DriveCatalogue::enterDriveConfig(
// If the drive is not in the catalogue
if(m_drives.end() == itor) {
// Insert it
m_drives[driveConfig.unitName] = new DriveCatalogueEntry(driveConfig,
m_drives[driveConfig.unitName] = new DriveCatalogueEntry(m_log,
m_processForker, m_vdqm, m_hostName, driveConfig, m_dataTransferConfig,
DriveCatalogueEntry::DRIVE_STATE_DOWN);
// Else the drive is already in the catalogue
} else {
......@@ -142,122 +159,77 @@ std::list<std::string>
}
//-----------------------------------------------------------------------------
// getUnitNamesWaitingForTransferFork
// findDrive
//-----------------------------------------------------------------------------
std::list<std::string> castor::tape::tapeserver::daemon::DriveCatalogue::getUnitNamesWaitingForTransferFork() const {
std::list<std::string> unitNames;
for(DriveMap::const_iterator itor = m_drives.begin();
itor != m_drives.end(); itor++) {
const std::string &unitName = itor->first;
const DriveCatalogueEntry &drive = *(itor->second);
const utils::DriveConfig &driveConfig = drive.getConfig();
// Sanity check
if(unitName != driveConfig.unitName) {
// Should never get here
castor::exception::Exception ex;
ex.getMessage() << "Failed to get unit names of drives waiting for forking a transfer session" <<
": unit name mismatch: unitName=" << unitName <<
" driveConfig.unitName=" << driveConfig.unitName;
throw ex;
}
const castor::tape::tapeserver::daemon::DriveCatalogueEntry
&castor::tape::tapeserver::daemon::DriveCatalogue::findDrive(
const std::string &unitName) const {
std::ostringstream task;
task << "find tape drive in catalogue by unit name: unitName=" << unitName;
if(DriveCatalogueEntry::SESSION_TYPE_DATATRANSFER==drive.getSessionType()
&& DriveCatalogueSession::SESSION_STATE_WAITFORK == drive.getSessionState()) {
unitNames.push_back(itor->first);
}
DriveMap::const_iterator itor = m_drives.find(unitName);
if(m_drives.end() == itor) {
castor::exception::Exception ex;
ex.getMessage() << "Failed to " << task.str() << ": Entry does not exist";
throw ex;
}
return unitNames;
}
//-----------------------------------------------------------------------------
// getUnitNamesWaitingForLabelFork
//-----------------------------------------------------------------------------
std::list<std::string> castor::tape::tapeserver::daemon::DriveCatalogue::
getUnitNamesWaitingForLabelFork() const {
std::list<std::string> unitNames;
for(DriveMap::const_iterator itor = m_drives.begin();
itor != m_drives.end(); itor++) {
const std::string &unitName = itor->first;
const DriveCatalogueEntry &drive = *(itor->second);
const utils::DriveConfig &driveConfig = drive.getConfig();
// Sanity check
if(unitName != driveConfig.unitName) {
// Should never get here
castor::exception::Exception ex;
ex.getMessage() << "Failed to get unit names of drives waiting for forking a label session" <<
": unit name mismatch: unitName=" << unitName <<
" driveConfig.unitName=" << driveConfig.unitName;
throw ex;
}
if(DriveCatalogueEntry::SESSION_TYPE_LABEL==drive.getSessionType() &&
DriveCatalogueSession::SESSION_STATE_WAITFORK == drive.getSessionState()) {
unitNames.push_back(itor->first);
}
if(NULL == itor->second) {
// Should never get here
castor::exception::Exception ex;
ex.getMessage() << "Failed to " << task <<
": Pointer to drive entry is unexpectedly NULL";
throw ex;
}
return unitNames;
}
//-----------------------------------------------------------------------------
// getUnitNamesWaitingForCleanerFork
//-----------------------------------------------------------------------------
std::list<std::string> castor::tape::tapeserver::daemon::DriveCatalogue::
getUnitNamesWaitingForCleanerFork() const {
std::list<std::string> unitNames;
for(DriveMap::const_iterator itor = m_drives.begin();
itor != m_drives.end(); itor++) {
const std::string &unitName = itor->first;
const DriveCatalogueEntry &drive = *(itor->second);
const utils::DriveConfig &driveConfig = drive.getConfig();
const DriveCatalogueEntry &drive = *(itor->second);
const utils::DriveConfig &driveConfig = drive.getConfig();
// Sanity check
if(unitName != driveConfig.unitName) {
// Should never get here
castor::exception::Exception ex;
ex.getMessage() << "Failed to get unit names of drives waiting for forking a cleaner session" <<
": unit name mismatch: unitName=" << unitName <<
" driveConfig.unitName=" << driveConfig.unitName;
throw ex;
}
if(DriveCatalogueEntry::SESSION_TYPE_CLEANER==drive.getSessionType() &&
DriveCatalogueSession::SESSION_STATE_WAITFORK == drive.getSessionState()) {
unitNames.push_back(itor->first);
}
// Sanity check
if(unitName != driveConfig.unitName) {
// Should never get here
castor::exception::Exception ex;
ex.getMessage() << "Failed to " << task <<
": Found inconsistent entry in tape-drive catalogue"
": Unit name mismatch: actual=" << driveConfig.unitName;
throw ex;
}
return unitNames;
return drive;
}
//-----------------------------------------------------------------------------
// findConstDrive
// findDrive
//-----------------------------------------------------------------------------
const castor::tape::tapeserver::daemon::DriveCatalogueEntry
*castor::tape::tapeserver::daemon::DriveCatalogue::findDrive(
const std::string &unitName) const {
castor::tape::tapeserver::daemon::DriveCatalogueEntry
&castor::tape::tapeserver::daemon::DriveCatalogue::findDrive(
const std::string &unitName) {
std::ostringstream task;
task << "find tape drive in catalogue by unit name: unitName=" << unitName;
DriveMap::const_iterator itor = m_drives.find(unitName);
DriveMap::iterator itor = m_drives.find(unitName);
if(m_drives.end() == itor) {
castor::exception::Exception ex;
ex.getMessage() << "Failed to find tape-drive in catalogue: " <<
": No entry for tape-drive " << unitName;
ex.getMessage() << "Failed to " << task.str() << ": Entry does not exist";
throw ex;
}
if(NULL == itor->second) {
// Should never get here
castor::exception::Exception ex;
ex.getMessage() << "Failed to " << task <<
": Pointer to drive entry is unexpectedly NULL";
throw ex;
}
const DriveCatalogueEntry * const drive = itor->second;
const utils::DriveConfig &driveConfig = drive->getConfig();
DriveCatalogueEntry &drive = *(itor->second);
const utils::DriveConfig &driveConfig = drive.getConfig();
// Sanity check
if(unitName != driveConfig.unitName) {
// This should never happen
castor::exception::Exception ex;
ex.getMessage() << "Failed to find tape-drive in catalogue: " <<
ex.getMessage() << "Failed to " << task <<
": Found inconsistent entry in tape-drive catalogue"
": Unit name mismatch: expected=" << unitName <<
" actual=" << driveConfig.unitName;
......@@ -268,16 +240,29 @@ const castor::tape::tapeserver::daemon::DriveCatalogueEntry
}
//-----------------------------------------------------------------------------
// findConstDrive
// findDrive
//-----------------------------------------------------------------------------
const castor::tape::tapeserver::daemon::DriveCatalogueEntry
*castor::tape::tapeserver::daemon::DriveCatalogue::findDrive(
&castor::tape::tapeserver::daemon::DriveCatalogue::findDrive(
const pid_t sessionPid) const {
std::ostringstream task;
task << "find tape drive in catalogue by session pid: sessionPid=" <<
sessionPid;
for(DriveMap::const_iterator itor = m_drives.begin(); itor != m_drives.end();
itor++) {
if(NULL == itor->second) {
// Should never get here
castor::exception::Exception ex;
ex.getMessage() << "Failed to " << task.str() <<
": Encountered NULL drive-entry pointer: unitName=" << itor->first;
throw ex;
}
for(DriveMap::const_iterator i = m_drives.begin(); i!=m_drives.end(); i++) {
const DriveCatalogueEntry * const drive = i->second;
const DriveCatalogueEntry &drive = *(itor->second);
try {
if(sessionPid == drive->getSessionPid()) {
if(sessionPid == drive.getSessionPid()) {
return drive;
}
} catch(...) {
......@@ -286,8 +271,7 @@ const castor::tape::tapeserver::daemon::DriveCatalogueEntry
}
castor::exception::Exception ex;
ex.getMessage() << "Failed to find tape-drive in catalogue: " <<
": No drive associated with session process-ID " << sessionPid;
ex.getMessage() << "Failed to " << task.str() << ": Entry does not exist";
throw ex;
}
......@@ -295,44 +279,26 @@ const castor::tape::tapeserver::daemon::DriveCatalogueEntry
// findDrive
//-----------------------------------------------------------------------------
castor::tape::tapeserver::daemon::DriveCatalogueEntry
*castor::tape::tapeserver::daemon::DriveCatalogue::findDrive(
const std::string &unitName) {
DriveMap::iterator itor = m_drives.find(unitName);
if(m_drives.end() == itor) {
castor::exception::Exception ex;
ex.getMessage() << "Failed to find tape-drive in catalogue: " <<
"No entry for tape-drive " << unitName;
throw ex;
}
DriveCatalogueEntry * drive = itor->second;
const utils::DriveConfig &driveConfig = drive->getConfig();
// Sanity check
if(unitName != driveConfig.unitName) {
// This should never happen
castor::exception::Exception ex;
ex.getMessage() << "Failed to find tape-drive in catalogue" <<
": Found inconsistent entry in tape-drive catalogue"
": Unit name mismatch: expected=" << unitName <<
" actual=" << driveConfig.unitName;
throw ex;
}
&castor::tape::tapeserver::daemon::DriveCatalogue::findDrive(
const pid_t sessionPid) {
std::ostringstream task;
task << "find tape drive in catalogue by session pid: sessionPid=" <<
sessionPid;
return drive;
}
for(DriveMap::iterator itor = m_drives.begin(); itor != m_drives.end();
itor++) {
//-----------------------------------------------------------------------------
// findDrive
//-----------------------------------------------------------------------------
castor::tape::tapeserver::daemon::DriveCatalogueEntry
*castor::tape::tapeserver::daemon::DriveCatalogue::findDrive(
const pid_t sessionPid) {
if(NULL == itor->second) {
// Should never get here
castor::exception::Exception ex;
ex.getMessage() << "Failed to " << task.str() <<
": Encountered NULL drive-entry pointer: unitName=" << itor->first;
throw ex;
}
for(DriveMap::iterator i = m_drives.begin(); i!=m_drives.end(); i++) {
DriveCatalogueEntry * drive = i->second;
DriveCatalogueEntry &drive = *(itor->second);
try {
if(sessionPid == drive->getSessionPid()) {
if(sessionPid == drive.getSessionPid()) {
return drive;
}
} catch(...) {
......@@ -341,7 +307,6 @@ castor::tape::tapeserver::daemon::DriveCatalogueEntry
}
castor::exception::Exception ex;
ex.getMessage() << "Failed to find tape-drive in catalogue: " <<
": No drive associated with session process-ID " << sessionPid;
ex.getMessage() << "Failed to " << task.str() << ": Entry does not exist";
throw ex;
}
......@@ -26,9 +26,12 @@
#include "castor/exception/Exception.hpp"
#include "castor/legacymsg/RtcpJobRqstMsgBody.hpp"
#include "castor/legacymsg/TapeLabelRqstMsgBody.hpp"
#include "castor/legacymsg/VdqmProxy.hpp"
#include "castor/log/Logger.hpp"
#include "castor/tape/utils/DriveConfigMap.hpp"
#include "castor/tape/tapeserver/client/ClientProxy.hpp"
#include "castor/tape/tapeserver/daemon/DriveCatalogueEntry.hpp"
#include "castor/tape/tapeserver/daemon/ProcessForkerProxy.hpp"
#include <map>
#include <string>
......@@ -46,6 +49,23 @@ namespace daemon {
class DriveCatalogue {
public:
/**
* Constructor.
*
* @param log Object representing the API of the CASTOR logging system.
* @param dataTransferConfig The configuration of a data-transfer session.
* @param processForker Proxy object representing the ProcessForker.
* @param vdqm Proxy object representing the vdqmd daemon.
* @param hostName The name of the host on which the daemon is running. This
* name is needed to fill in messages to be sent to the vdqmd daemon.
*/
DriveCatalogue(
log::Logger &log,
const DataTransferSession::CastorConf &dataTransferConfig,
ProcessForkerProxy &processForker,
legacymsg::VdqmProxy &m_vdqm,
const std::string &hostName);
/**
* Destructor.
*
......@@ -69,7 +89,7 @@ public:
*
* @param unitName The unit name of the tape drive.
*/
const DriveCatalogueEntry *findDrive(const std::string &unitName)
const DriveCatalogueEntry &findDrive(const std::string &unitName)
const;
/**
......@@ -80,7 +100,7 @@ public:
*
* @param sessionPid The process ID of the session.
*/
const DriveCatalogueEntry *findDrive(const pid_t sessionPid) const;
const DriveCatalogueEntry &findDrive(const pid_t sessionPid) const;
/**
* Returns a reference to the tape-drive entry corresponding to the tape
......@@ -90,7 +110,7 @@ public:
*
* @param unitName The unit name of the tape drive.
*/
DriveCatalogueEntry *findDrive(const std::string &unitName);
DriveCatalogueEntry &findDrive(const std::string &unitName);
/**
* Returns a reference to the tape-drive entry associated with the
......@@ -100,7 +120,7 @@ public:
*
* @param sessionPid The process ID of the session.
*/
DriveCatalogueEntry *findDrive(const pid_t sessionPid);
DriveCatalogueEntry &findDrive(const pid_t sessionPid);
/**
* Returns an unordered list of the unit names of all of the tape drives
......@@ -116,33 +136,36 @@ public:
*
* @return Unordered list of the unit names.
*/
std::list<std::string> getUnitNames(const DriveCatalogueEntry::DriveState state) const;
std::list<std::string> getUnitNames(const DriveCatalogueEntry::DriveState
state) const;
private:
/**
* Returns an unordered list of the unit names of the tape drives waiting for
* forking a transfer session.
*
* @return Unordered list of the unit names.
* Object representing the API of the CASTOR logging system.
*/
std::list<std::string> getUnitNamesWaitingForTransferFork() const;
log::Logger &m_log;
/**
* Returns an unordered list of the unit names of the tape drives waiting for
* forking a label session.
*
* @return Unordered list of the unit names.
* The configuration of a data-transfer session.
*/
std::list<std::string> getUnitNamesWaitingForLabelFork() const;
const DataTransferSession::CastorConf m_dataTransferConfig;
/**
* Returns an unordered list of the unit names of the tape drives waiting for
* forking a cleaner session.
*
* @return Unordered list of the unit names.
* Proxy object representing the ProcessForker.
*/
std::list<std::string> getUnitNamesWaitingForCleanerFork() const;
ProcessForkerProxy &m_processForker;
private:
/**
* Proxy object representing the vdqmd daemon.
*/
legacymsg::VdqmProxy &m_vdqm;
/**
* The name of the host on which the daemon is running. This name is
* needed to fill in messages to be sent to the vdqmd daemon.
*/
const std::string m_hostName;
/**
* Type that maps the unit name of a tape drive to the catalogue entry of
......
......@@ -21,13 +21,56 @@
* @author Castor Dev team, castor-dev@cern.ch
*****************************************************************************/
#include "castor/exception/Exception.hpp"
#include "castor/tape/tapeserver/daemon/DriveCatalogueCleanerSession.hpp"
#include "h/Ctape_constants.h"
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
castor::tape::tapeserver::daemon::DriveCatalogueCleanerSession::DriveCatalogueCleanerSession(
const castor::tape::tapeserver::daemon::DriveCatalogueSession::SessionState state):
DriveCatalogueSession(state) {
castor::tape::tapeserver::daemon::DriveCatalogueCleanerSession::
DriveCatalogueCleanerSession(const std::string &vid,
const time_t assignmentTime):
m_vid(vid),
m_assignmentTime(assignmentTime) {
}
}
\ No newline at end of file
//------------------------------------------------------------------------------
// getVid
//------------------------------------------------------------------------------
std::string castor::tape::tapeserver::daemon::DriveCatalogueCleanerSession::
getVid() const {
// If the volume identifier of the tape drive is not known
if(m_vid.empty()) {
castor::exception::Exception ex;
ex.getMessage() << "Failed to get VID from cleaner session"