Commit a08d113d authored by Steven Murray's avatar Steven Murray
Browse files

Acs, Manual and Scsi library slots now inherit from LibrarySlot

parent b1c3768d
...@@ -47,7 +47,7 @@ protected: ...@@ -47,7 +47,7 @@ protected:
ArgcvList m_argsList; ArgcvList m_argsList;
/** /**
* Creates a duplicate string usin the new operator. * Creates a duplicate string using the new operator.
*/ */
char *dupString(const char *str) { char *dupString(const char *str) {
const size_t len = strlen(str); const size_t len = strlen(str);
......
...@@ -58,15 +58,13 @@ void castor::legacymsg::RmcProxyTcpIp::mountTapeReadOnly( ...@@ -58,15 +58,13 @@ void castor::legacymsg::RmcProxyTcpIp::mountTapeReadOnly(
void castor::legacymsg::RmcProxyTcpIp::mountTapeReadWrite( void castor::legacymsg::RmcProxyTcpIp::mountTapeReadWrite(
const std::string &vid, const mediachanger::ScsiLibrarySlot &librarySlot) { const std::string &vid, const mediachanger::ScsiLibrarySlot &librarySlot) {
try { try {
const mediachanger::ScsiLibrarySlot parsedSlot(librarySlot);
RmcMountMsgBody rqstBody; RmcMountMsgBody rqstBody;
rqstBody.uid = geteuid(); rqstBody.uid = geteuid();
rqstBody.gid = getegid(); rqstBody.gid = getegid();
castor::utils::copyString(rqstBody.vid, vid); castor::utils::copyString(rqstBody.vid, vid);
rqstBody.drvOrd = parsedSlot.getDrvOrd(); rqstBody.drvOrd = librarySlot.getDrvOrd();
rmcSendRecvNbAttempts(RMC_MAXATTEMPTS, parsedSlot.getRmcHostName(), rmcSendRecvNbAttempts(RMC_MAXATTEMPTS, librarySlot.getRmcHostName(),
rqstBody); rqstBody);
} catch(castor::exception::Exception &ne) { } catch(castor::exception::Exception &ne) {
castor::exception::Exception ex; castor::exception::Exception ex;
...@@ -84,16 +82,14 @@ void castor::legacymsg::RmcProxyTcpIp::mountTapeReadWrite( ...@@ -84,16 +82,14 @@ void castor::legacymsg::RmcProxyTcpIp::mountTapeReadWrite(
void castor::legacymsg::RmcProxyTcpIp::dismountTape(const std::string &vid, void castor::legacymsg::RmcProxyTcpIp::dismountTape(const std::string &vid,
const mediachanger::ScsiLibrarySlot &librarySlot) { const mediachanger::ScsiLibrarySlot &librarySlot) {
try { try {
const mediachanger::ScsiLibrarySlot parsedSlot(librarySlot);
RmcUnmountMsgBody rqstBody; RmcUnmountMsgBody rqstBody;
rqstBody.uid = geteuid(); rqstBody.uid = geteuid();
rqstBody.gid = getegid(); rqstBody.gid = getegid();
castor::utils::copyString(rqstBody.vid, vid); castor::utils::copyString(rqstBody.vid, vid);
rqstBody.drvOrd = parsedSlot.getDrvOrd(); rqstBody.drvOrd = librarySlot.getDrvOrd();
rqstBody.force = 0; rqstBody.force = 0;
rmcSendRecvNbAttempts(RMC_MAXATTEMPTS, parsedSlot.getRmcHostName(), rmcSendRecvNbAttempts(RMC_MAXATTEMPTS, librarySlot.getRmcHostName(),
rqstBody); rqstBody);
} catch(castor::exception::Exception &ne) { } catch(castor::exception::Exception &ne) {
castor::exception::Exception ex; castor::exception::Exception ex;
......
...@@ -28,111 +28,50 @@ ...@@ -28,111 +28,50 @@
// constructor // constructor
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
castor::mediachanger::AcsLibrarySlot::AcsLibrarySlot() throw(): castor::mediachanger::AcsLibrarySlot::AcsLibrarySlot() throw():
LibrarySlot(TAPE_LIBRARY_TYPE_ACS),
m_acs(0), m_acs(0),
m_lsm(0), m_lsm(0),
m_panel(0), m_panel(0),
m_drive(0) { m_drive(0) {
m_str = librarySlotToString(0, 0, 0, 0);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// constructor // librarySlotToString
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
castor::mediachanger::AcsLibrarySlot::AcsLibrarySlot(const std::string &str) { std::string castor::mediachanger::AcsLibrarySlot::librarySlotToString(
const std::string errMsg("Failed to construct AcsLibrarySlot"); const uint32_t acs, const uint32_t lsm, const uint32_t panel,
std::vector<std::string> components; const uint32_t drive) const {
castor::utils::splitString(str, ',', components); std::ostringstream oss;
if(4 != components.size()) { oss << "acs" << acs << "," << lsm << "," << panel << "," << drive;
castor::exception::InvalidArgument ex; return oss.str();
ex.getMessage() << errMsg << ": Invalid number of components" }
": expected=4, actual=" << components.size();
throw ex;
}
// check for acs in the beginning
const std::string &acsWithACS_NUMBERStr = components[0];
if(0 != acsWithACS_NUMBERStr.find("acs")) {
castor::exception::InvalidArgument ex;
ex.getMessage() << errMsg << ": Invalid tape library-slot format"
": expected=acsACS_NUMBER, actual=" << acsWithACS_NUMBERStr;
throw ex;
}
const std::string::size_type indexOfACS_NUMBER = 3; // skip acs
const std::string &acsStr = acsWithACS_NUMBERStr.substr(indexOfACS_NUMBER);
const std::string &lsmStr = components[1];
const std::string &panStr = components[2];
const std::string &drvStr = components[3];
// Each of the 4 components must be between 1 and than 3 characters long
if(1 > acsStr.length() || 3 < acsStr.length()) {
castor::exception::InvalidArgument ex;
ex.getMessage() << errMsg << ": Invalid ACS_NUMBER string length"
": expected=1..3, actual=" << acsStr.length();
throw ex;
}
if(1 > lsmStr.length() || 3 < lsmStr.length()) {
castor::exception::InvalidArgument ex;
ex.getMessage() << errMsg << ": Invalid LSM_NUMBER string length"
": expected=1..3, actual=" << lsmStr.length();
throw ex;
}
if(1 > panStr.length() || 3 < panStr.length()) {
castor::exception::InvalidArgument ex;
ex.getMessage() << errMsg << ": Invalid PANEL_NUMBER string length"
": expected=1..3, actual=" << panStr.length();
throw ex;
}
if(1 > drvStr.length() || 3 < drvStr.length()) {
castor::exception::InvalidArgument ex;
ex.getMessage() << errMsg << ": Invalid TRANSPORT_NUMBER string length"
": expected=1..3, actual=" << drvStr.length();
throw ex;
}
// Each of the 4 components must only contain numerals //------------------------------------------------------------------------------
if(!onlyContainsNumerals(acsStr)) { // constructor
castor::exception::InvalidArgument ex; //------------------------------------------------------------------------------
ex.getMessage() << errMsg << ": ACS_NUMBER must only contain numerals:" castor::mediachanger::AcsLibrarySlot::AcsLibrarySlot(const uint32_t acs,
" value=" << acsStr; const uint32_t lsm, const uint32_t panel, const uint32_t drive) throw():
throw ex; LibrarySlot(TAPE_LIBRARY_TYPE_ACS),
} m_acs(acs),
if(!onlyContainsNumerals(lsmStr)) { m_lsm(lsm),
castor::exception::InvalidArgument ex; m_panel(panel),
ex.getMessage() << errMsg << ": LSM_NUMBER must only contain numerals:" m_drive(drive) {
" value=" << acsStr; m_str = librarySlotToString(acs, lsm, panel, drive);
throw ex; }
}
if(!onlyContainsNumerals(panStr)) {
castor::exception::InvalidArgument ex;
ex.getMessage() << errMsg << ": PANEL_NUMBER must only contain numerals:"
" value=" << acsStr;
throw ex;
}
if(!onlyContainsNumerals(drvStr)) {
castor::exception::InvalidArgument ex;
ex.getMessage() << errMsg << ": TRANSPORT__NUMBER must only contain "
"numerals: value=" << acsStr;
throw ex;
}
m_acs = atoi(acsStr.c_str()); //------------------------------------------------------------------------------
m_lsm = atoi(lsmStr.c_str()); // destructor
m_panel = atoi(panStr.c_str()); //------------------------------------------------------------------------------
m_drive = atoi(drvStr.c_str()); castor::mediachanger::AcsLibrarySlot::~AcsLibrarySlot() throw() {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// onlyContainsNumerals // clone
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool castor::mediachanger::AcsLibrarySlot::onlyContainsNumerals( castor::mediachanger::LibrarySlot *castor::mediachanger::AcsLibrarySlot::
const std::string &str) const throw() { clone() {
for(std::string::const_iterator itor = str.begin(); itor != str.end(); return new AcsLibrarySlot(*this);
itor++) {
if(*itor < '0' || *itor > '9') {
return false;
}
}
return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -162,14 +101,3 @@ uint32_t castor::mediachanger::AcsLibrarySlot::getPanel() const throw () { ...@@ -162,14 +101,3 @@ uint32_t castor::mediachanger::AcsLibrarySlot::getPanel() const throw () {
uint32_t castor::mediachanger::AcsLibrarySlot::getDrive() const throw () { uint32_t castor::mediachanger::AcsLibrarySlot::getDrive() const throw () {
return m_drive; return m_drive;
} }
//------------------------------------------------------------------------------
// str
//------------------------------------------------------------------------------
std::string castor::mediachanger::AcsLibrarySlot::str() const {
std::ostringstream oss;
oss << "acs=" << m_acs << " lsm=" << m_lsm << " panel=" << m_panel <<
" drive=" << m_drive;
return oss.str();
}
...@@ -22,9 +22,9 @@ ...@@ -22,9 +22,9 @@
#pragma once #pragma once
#include "castor/exception/InvalidArgument.hpp" #include "castor/exception/InvalidArgument.hpp"
#include "castor/mediachanger/LibrarySlot.hpp"
#include <stdint.h> #include <stdint.h>
#include <string>
namespace castor { namespace castor {
namespace mediachanger { namespace mediachanger {
...@@ -32,7 +32,7 @@ namespace mediachanger { ...@@ -32,7 +32,7 @@ namespace mediachanger {
/** /**
* Class reprsenting a slot in an ACS tape-library. * Class reprsenting a slot in an ACS tape-library.
*/ */
class AcsLibrarySlot { class AcsLibrarySlot: public LibrarySlot {
public: public:
/** /**
...@@ -43,53 +43,53 @@ public: ...@@ -43,53 +43,53 @@ public:
/** /**
* Constructor. * Constructor.
* *
* This method throws a castor::exception::InvalidArgument if the specified * @param acs The acs component of the library slot.
* string representation is invalid. * @param lsm The lsm component of the library slot.
* * @param panel The panel component of the library slot.
* @param The string representation of a slot in an ACS tape-library in format * @param drive The drive component of the library slot.
* acsACS_NUMBER,LSM_NUMBER,PANEL_NUMBER,TRANSPORT_NUMBER
*/ */
AcsLibrarySlot(const std::string &str); AcsLibrarySlot(const uint32_t acs, const uint32_t lsm,
const uint32_t panel, const uint32_t drive) throw();
/**
* Destructor.
*/
~AcsLibrarySlot() throw();
/** /**
* Returns true if the specified string only contains numerals else false. * Creates a clone of this object.
* *
* @return True if the specified string only contains numerals else false. * @return The clone.
*/ */
bool onlyContainsNumerals(const std::string &str) const throw(); LibrarySlot *clone();
/** /**
* Gets the acs component of the library slot. * Gets the acs component of the library slot.
* *
* @return the acs component of the library slot. * @return the acs component of the library slot.
*/ */
uint32_t getAcs() const throw (); uint32_t getAcs() const throw();
/** /**
* Gets the lsm component of the library slot. * Gets the lsm component of the library slot.
* *
* @return the lsm component of the library slot. * @return the lsm component of the library slot.
*/ */
uint32_t getLsm() const throw (); uint32_t getLsm() const throw();
/** /**
* Gets the panel component of the library slot. * Gets the panel component of the library slot.
* *
* @return the panel component of the library slot. * @return the panel component of the library slot.
*/ */
uint32_t getPanel() const throw (); uint32_t getPanel() const throw();
/** /**
* Gets the drive component of the library slot. * Gets the drive component of the library slot.
* *
* @return the drive component of the library slot. * @return the drive component of the library slot.
*/ */
uint32_t getDrive() const throw (); uint32_t getDrive() const throw();
/**
* Returns the representation of the slot.
*/
std::string str() const;
private: private:
...@@ -112,9 +112,20 @@ private: ...@@ -112,9 +112,20 @@ private:
* The drive component of the library slot. * The drive component of the library slot.
*/ */
uint32_t m_drive; uint32_t m_drive;
/**
* Returns the string representation of the specified ACS library slot.
*
* @param acs The acs component of the library slot.
* @param lsm The lsm component of the library slot.
* @param panel The panel component of the library slot.
* @param drive The drive component of the library slot.
* @return The string representation.
*/
std::string librarySlotToString(const uint32_t acs, const uint32_t lsm,
const uint32_t panel, const uint32_t drive) const;
}; // class AcsProxy }; // class AcsProxy
} // namespace mediachanger } // namespace mediachanger
} // namespace castor } // namespace castor
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "castor/mediachanger/AcsLibrarySlot.hpp" #include "castor/mediachanger/AcsLibrarySlot.hpp"
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <memory>
namespace unitTests { namespace unitTests {
...@@ -37,45 +38,37 @@ protected: ...@@ -37,45 +38,37 @@ protected:
} }
}; };
TEST_F(castor_mediachanger_AcsLibrarySlotTest, goodDayParsing) { TEST_F(castor_mediachanger_AcsLibrarySlotTest, goodDay) {
using namespace castor::mediachanger; using namespace castor::mediachanger;
AcsLibrarySlot slot(11, 22, 33, 44);
AcsLibrarySlot slot; ASSERT_EQ(TAPE_LIBRARY_TYPE_ACS, slot.getLibraryType());
ASSERT_EQ(std::string("acs=0 lsm=0 panel=0 drive=0"), slot.str()); ASSERT_EQ(std::string("acs11,22,33,44"), slot.str());
ASSERT_EQ((uint32_t)0, slot.getAcs());
ASSERT_EQ((uint32_t)0, slot.getLsm());
ASSERT_EQ((uint32_t)0, slot.getPanel());
ASSERT_EQ((uint32_t)0, slot.getDrive());
const std::string str = "acs11,22,33,44";
ASSERT_NO_THROW(slot = AcsLibrarySlot(str));
ASSERT_EQ(std::string("acs=11 lsm=22 panel=33 drive=44"), slot.str());
ASSERT_EQ((uint32_t)11, slot.getAcs()); ASSERT_EQ((uint32_t)11, slot.getAcs());
ASSERT_EQ((uint32_t)22, slot.getLsm()); ASSERT_EQ((uint32_t)22, slot.getLsm());
ASSERT_EQ((uint32_t)33, slot.getPanel()); ASSERT_EQ((uint32_t)33, slot.getPanel());
ASSERT_EQ((uint32_t)44, slot.getDrive()); ASSERT_EQ((uint32_t)44, slot.getDrive());
} }
TEST_F(castor_mediachanger_AcsLibrarySlotTest, badDayParsing) { TEST_F(castor_mediachanger_AcsLibrarySlotTest, clone) {
using namespace castor::mediachanger; using namespace castor::mediachanger;
const std::string str = "nonsense"; std::auto_ptr<AcsLibrarySlot> slot1;
ASSERT_THROW(AcsLibrarySlot slot(str), castor::exception::InvalidArgument); ASSERT_NO_THROW(slot1.reset(new AcsLibrarySlot(11, 22, 33, 44)));
ASSERT_EQ(TAPE_LIBRARY_TYPE_ACS, slot1->getLibraryType());
const std::string strAcs = "asc0,1,2,3"; ASSERT_EQ(std::string("acs11,22,33,44"), slot1->str());
ASSERT_THROW(AcsLibrarySlot slot(strAcs), castor::exception::InvalidArgument); ASSERT_EQ((uint32_t)11, slot1->getAcs());
ASSERT_EQ((uint32_t)22, slot1->getLsm());
const std::string strACS_NUMBER = "acssd1,1,2,3"; ASSERT_EQ((uint32_t)33, slot1->getPanel());
ASSERT_THROW(AcsLibrarySlot slot(strACS_NUMBER), castor::exception::InvalidArgument); ASSERT_EQ((uint32_t)44, slot1->getDrive());
const std::string strLsm = "acs0,1111,2,3";
ASSERT_THROW(AcsLibrarySlot slot(strLsm), castor::exception::InvalidArgument);
const std::string strPanel = "acs0,111,ABC,3";
ASSERT_THROW(AcsLibrarySlot slot(strPanel), castor::exception::InvalidArgument);
const std::string strDrive = "acs0,111,222,3 "; std::auto_ptr<AcsLibrarySlot> slot2;
ASSERT_THROW(AcsLibrarySlot slot(strDrive), castor::exception::InvalidArgument); ASSERT_NO_THROW(slot2.reset((AcsLibrarySlot*)slot1->clone()));
ASSERT_EQ(TAPE_LIBRARY_TYPE_ACS, slot2->getLibraryType());
ASSERT_EQ(std::string("acs11,22,33,44"), slot2->str());
ASSERT_EQ((uint32_t)11, slot2->getAcs());
ASSERT_EQ((uint32_t)22, slot2->getLsm());
ASSERT_EQ((uint32_t)33, slot2->getPanel());
ASSERT_EQ((uint32_t)44, slot2->getDrive());
} }
} // namespace unitTests } // namespace unitTests
...@@ -21,7 +21,8 @@ cmake_minimum_required (VERSION 2.6) ...@@ -21,7 +21,8 @@ cmake_minimum_required (VERSION 2.6)
set (MEDIA_CHANGER_LIB_SRC_FILES set (MEDIA_CHANGER_LIB_SRC_FILES
AcsLibrarySlot.cpp AcsLibrarySlot.cpp
GenericLibrarySlot.cpp LibrarySlot.cpp
LibrarySlotParser.cpp
ManualLibrarySlot.cpp ManualLibrarySlot.cpp
MediaChangerFacade.cpp MediaChangerFacade.cpp
MmcProxy.cpp MmcProxy.cpp
......
...@@ -32,7 +32,7 @@ namespace mediachanger { ...@@ -32,7 +32,7 @@ namespace mediachanger {
* Class containing the code common to the parsed command-line of the ACS * Class containing the code common to the parsed command-line of the ACS
* command-line tools provided by CASTOR. * command-line tools provided by CASTOR.
*/ */
struct CmdLine { class CmdLine {
protected: protected:
/** /**
......
...@@ -45,10 +45,11 @@ public: ...@@ -45,10 +45,11 @@ public:
* @param inStream Standard input stream. * @param inStream Standard input stream.
* @param outStream Standard output stream. * @param outStream Standard output stream.
* @param errStream Standard error stream. * @param errStream Standard error stream.
* @param mc Object representing the API of the media changer. * @param mc Interface to the media changer.
*/ */
CmdLineTool(std::istream &inStream, std::ostream &outStream, CmdLineTool(std::istream &inStream, std::ostream &outStream,
std::ostream &errStream, MediaChangerFacade &mc) throw(); std::ostream &errStream, MediaChangerFacade &mc)
throw();
/** /**
* Pure-virtual destructor to guarantee this class is abstract. * Pure-virtual destructor to guarantee this class is abstract.
...@@ -73,7 +74,7 @@ protected: ...@@ -73,7 +74,7 @@ protected:
std::ostream &m_err; std::ostream &m_err;
/** /**
* Object representing the API of the media changer. * Interface to the media changer.
*/ */
MediaChangerFacade &m_mc; MediaChangerFacade &m_mc;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <getopt.h> #include <getopt.h>
#include <iostream> #include <iostream>
#include <memory>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// constructor // constructor
...@@ -51,20 +52,22 @@ void castor::mediachanger::DismountCmd::exceptionThrowingMain(const int argc, ...@@ -51,20 +52,22 @@ void castor::mediachanger::DismountCmd::exceptionThrowingMain(const int argc,
// Display the usage message to standard out and exit with success if the // Display the usage message to standard out and exit with success if the
// user requested help // user requested help
if(m_cmdLine.help) { if(m_cmdLine.getHelp()) {
m_out << DismountCmdLine::getUsage(); m_out << m_cmdLine.getUsage();
return; return;
} }
// Setup debug mode to be on or off depending on the command-line arguments // Setup debug mode to be on or off depending on the command-line arguments
m_debugBuf.setDebug(m_cmdLine.debug); m_debugBuf.setDebug(m_cmdLine.getDebug());
m_dbg << "VID = " << m_cmdLine.vid << std::endl; m_dbg << "VID = " << m_cmdLine.getVid() << std::endl;
m_dbg << "DRIVE_SLOT = " << m_cmdLine.driveLibrarySlot.str() << std::endl; m_dbg << "DRIVE_SLOT = " << m_cmdLine.getDriveLibrarySlot().str() <<
std::endl;
if(m_cmdLine.force) { if(m_cmdLine.getForce()) {
m_mc.forceDismountTape(m_cmdLine.vid, m_cmdLine.driveLibrarySlot); m_mc.forceDismountTape(m_cmdLine.getVid(),
m_cmdLine.getDriveLibrarySlot());
} else { } else {
m_mc.dismountTape(m_cmdLine.vid, m_cmdLine.driveLibrarySlot); m_mc.dismountTape(m_cmdLine.getVid(), m_cmdLine.getDriveLibrarySlot());
} }
} }