Commit 6c0e3ede authored by Daniele Kruse's avatar Daniele Kruse
Browse files

Integrated the cleaning mechanism within the handling of exited data transfer sessions

parent abda487c
......@@ -41,7 +41,7 @@ castor::tape::tapeserver::daemon::CleanerSession::CleanerSession(
//------------------------------------------------------------------------------
// clean
//------------------------------------------------------------------------------
int castor::tape::tapeserver::daemon::CleanerSession::clean() {
int castor::tape::tapeserver::daemon::CleanerSession::clean(const std::string &vid) {
castor::tape::SCSI::DeviceVector dv(m_sysWrapper);
castor::tape::SCSI::DeviceInfo driveInfo = dv.findBySymlink(m_driveConfig.devFilename);
......@@ -72,6 +72,18 @@ int castor::tape::tapeserver::daemon::CleanerSession::clean() {
drive->rewind();
drive->readExactBlock((void * )&vol1, sizeof(vol1), "[CleanerSession::clean()] - Reading header VOL1");
vol1.verify();
if(vid.empty()) { // vid given is empty
log::Param params[] = {log::Param("vid", vid)};
m_log(LOG_INFO, "Cleaner session received an empty vid.", params);
}
else if(!(vid.compare(vol1.getVSN()))) { // vid provided and vid read on VOL1 correspond
log::Param params[] = {log::Param("vid", vid)};
m_log(LOG_INFO, "Cleaner session received the same vid read on tape.", params);
}
else { // vid provided and vid read on VOL1 don NOT correspond!
log::Param params[] = {log::Param("vid provided", vid), log::Param("vid read on label", vol1.getVSN())};
m_log(LOG_WARNING, "Cleaner session received a different vid from the one read on tape.", params);
}
} catch(castor::exception::Exception &ne) {
castor::exception::Exception ex;
ex.getMessage() << "Cleaner session could not rewind the tape or read its label. Giving up now. Reason: " << ne.getMessage().str();
......
......@@ -60,9 +60,12 @@ namespace daemon {
/**
* Cleans the drive by unloading any tape present and unmounting it
*
* @param vid The identifier of the mounted volume (one can pass the empty string
* in case it is unknown, as it not used except for logging purposes).
*
* @return 0 in case of success (drive can stay UP) or 1 in case of failure (drive needs to be put down by the caller)
*/
int clean();
int clean(const std::string &vid);
private:
/**
......
......@@ -484,9 +484,9 @@ void castor::tape::tapeserver::daemon::DriveCatalogueEntry::receivedLabelJob(
}
//-----------------------------------------------------------------------------
// receivedCleanerJob
// toBeCleaned
//-----------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::DriveCatalogueEntry::receivedCleanerJob() {
void castor::tape::tapeserver::daemon::DriveCatalogueEntry::toBeCleaned() {
std::ostringstream task;
task << "handle cleaner job for tape drive " << m_config.unitName;
......
......@@ -328,7 +328,7 @@ public:
*
* This method will accept any drive state.
*/
void receivedCleanerJob();
void toBeCleaned();
/**
* Moves the state of the tape drive to DRIVE_STATE_RUNNING.
......
......@@ -616,6 +616,7 @@ void castor::tape::tapeserver::daemon::TapeDaemon::mainEventLoop() {
while(handleEvents()) {
forkDataTransferSessions();
forkLabelSessions();
forkCleanerSessions();
}
}
......@@ -795,6 +796,8 @@ void castor::tape::tapeserver::daemon::TapeDaemon::
return handleReapedDataTransferSession(pid, waitpidStat);
case DriveCatalogueEntry::SESSION_TYPE_LABEL:
return handleReapedLabelSession(pid, waitpidStat);
case DriveCatalogueEntry::SESSION_TYPE_CLEANER:
return handleReapedCleanerSession(pid, waitpidStat);
default:
{
castor::exception::Exception ex;
......@@ -822,14 +825,44 @@ void castor::tape::tapeserver::daemon::TapeDaemon::handleReapedDataTransferSessi
m_log(LOG_INFO, "Data-transfer session succeeded", params);
requestVdqmToReleaseDrive(driveConfig, pid);
notifyVdqmTapeUnmounted(driveConfig, vid, pid);
} else {
drive->sessionFailed(); //deletes the session
m_log(LOG_INFO, "Data-transfer session failed. Going to try to clean the drive.", params);
requestVdqmToReleaseDrive(driveConfig, pid);
drive->toBeCleaned();
}
} catch(castor::exception::Exception &ne) {
castor::exception::Exception ex;
ex.getMessage() << "Failed to handle reaped data transfer session: " <<
ne.getMessage().str();
throw ex;
}
}
//------------------------------------------------------------------------------
// handleReapedCleanerSession
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::TapeDaemon::handleReapedCleanerSession(
const pid_t pid, const int waitpidStat) {
try {
std::list<log::Param> params;
params.push_back(log::Param("cleanerPid", pid));
DriveCatalogueEntry *const drive = m_driveCatalogue.findDrive(pid);
const utils::DriveConfig &driveConfig = drive->getConfig();
if(WIFEXITED(waitpidStat) && 0 == WEXITSTATUS(waitpidStat)) {
const std::string vid = drive->getVid();
drive->sessionSucceeded();
m_log(LOG_INFO, "Cleaner session succeeded. Drive will stay UP", params);
notifyVdqmTapeUnmounted(driveConfig, vid, pid);
} else {
drive->sessionFailed();
m_log(LOG_INFO, "Data-transfer session failed", params);
m_log(LOG_INFO, "Cleaner session failed. Drive will go DOWN", params);
setDriveDownInVdqm(pid, drive->getConfig());
}
} catch(castor::exception::Exception &ne) {
castor::exception::Exception ex;
ex.getMessage() << "Failed to handle reaped data transfer session: " <<
ex.getMessage() << "Failed to handle reaped cleaner session: " <<
ne.getMessage().str();
throw ex;
}
......@@ -1244,8 +1277,9 @@ void castor::tape::tapeserver::daemon::TapeDaemon::forkCleanerSession(
const utils::DriveConfig &driveConfig = drive->getConfig();
std::list<log::Param> params;
params.push_back(log::Param("unitName", driveConfig.unitName));
std::string vid = "";
m_processForker->forkCleaner(driveConfig.unitName, "");
m_processForker->forkCleaner(driveConfig.unitName, vid);
m_log.prepareForFork();
const pid_t forkRc = fork();
......@@ -1266,7 +1300,7 @@ void castor::tape::tapeserver::daemon::TapeDaemon::forkCleanerSession(
// file-descriptors owned by the event handlers
m_reactor.clear();
runCleanerSession(drive);
runCleanerSession(drive, vid);
}
}
......@@ -1274,7 +1308,7 @@ void castor::tape::tapeserver::daemon::TapeDaemon::forkCleanerSession(
// runCleanerSession
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::TapeDaemon::runCleanerSession(
DriveCatalogueEntry *drive) throw() {
DriveCatalogueEntry *drive, const std::string &vid) throw() {
const utils::DriveConfig &driveConfig = drive->getConfig();
std::list<log::Param> params;
......@@ -1289,31 +1323,18 @@ void castor::tape::tapeserver::daemon::TapeDaemon::runCleanerSession(
m_log,
driveConfig,
sWrapper);
int ret = cleanerSession.clean(); //clean() returns 0 if drive should be put up or 1 if it should be put down
if(0==ret) {
m_log(LOG_INFO, "Cleaner session cleaned the drive. The drive is going (staying) up", params);
m_vdqm.setDriveUp(m_hostName, driveConfig.unitName, driveConfig.dgn);
drive->configureUp();
}
else if(1==ret) {
m_log(LOG_ERR, "Cleaner session couldn't clean the drive properly. The drive is going down", params);
m_vdqm.setDriveDown(m_hostName, driveConfig.unitName, driveConfig.dgn);
drive->configureDown();
}
exit(0);
exit(cleanerSession.clean(vid)); //clean() returns 0 if drive should be put up or 1 if it should be put down
} catch(castor::exception::Exception &ne) {
castor::exception::Exception ex;
ex.getMessage() << "Aborting cleaner session. Reason: " << ne.getMessage().str();
m_log(LOG_ERR, ex.getMessage().str());
exit(1);
} catch(std::exception &se) {
params.push_back(log::Param("message", se.what()));
m_log(LOG_ERR, "Aborting cleaner session: Caught an unexpected exception",
params);
exit(1);
} catch(...) {
m_log(LOG_ERR,
"Aborting cleaner session: Caught an unexpected and unknown exception");
exit(1);
}
exit(1);
}
......@@ -295,6 +295,15 @@ protected:
*/
void handleReapedDataTransferSession(const pid_t pid,
const int waitpidStat);
/**
* Does the required post processing for the specified reaped session.
*
* @param pid The process ID of the reaped session.
* @param waitpidStat The status information given by a call to waitpid().
*/
void handleReapedCleanerSession(const pid_t pid,
const int waitpidStat);
/**
* Sets the state of the tape drive asscoiated with the specified
......@@ -428,8 +437,10 @@ protected:
*
* @param drive The catalogue entry of the tape drive to be used during the
* session.
* @param vid The identifier of the mounted volume (one can pass the empty string
* in case it is unknown, as it not used except for logging purposes).
*/
void runCleanerSession(DriveCatalogueEntry *drive) throw();
void runCleanerSession(DriveCatalogueEntry *drive, const std::string &vid) throw();
/**
* Catalogue used to keep track of both the initial and current state of
......
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