Commit a4776842 authored by Victor Kotlyar's avatar Victor Kotlyar
Browse files

Ported commit 2a14c5d7ef7bb395a37454789abcbfd7266edcc2 from castor/master

CASTOR-4982: tapeserverd should tolerate some non-fatal tape alerts
before writing

Fixed.

Add logic to the TapeWriteSingleThread to skip not-fatal tape
alerts before writing to the tape. Only "Lost statistics"
tapeAlertLostStatistics 0x32 tolerated as non-fatal.
parent adfd407e
......@@ -290,6 +290,18 @@ std::string castor::tape::SCSI::tapeAlertToCompactString(uint16_t parameterCode)
}
}
//------------------------------------------------------------------------------
// isTapeAlertCriticalForWrite
//------------------------------------------------------------------------------
bool castor::tape::SCSI::isTapeAlertCriticalForWrite(const uint16_t code) {
switch(code) {
case 0x32: // tapeAlertLostStatistics
return false;
default:
return true;
}
}
/**
* Turn a SCSI status code into a string
* @param status
......
......@@ -215,6 +215,13 @@ namespace SCSI {
* Helper function turning tape alerts to mixed case compact strings.
*/
std::string tapeAlertToCompactString(uint16_t parameterCode);
/**
* Checks if the tape alert is critical for the writing session.
* @param code The tape alert parameter code.
* @return True if it is critical for the writing session or true otherwise.
*/
bool isTapeAlertCriticalForWrite(const uint16_t code);
class Status {
public:
......
......@@ -107,6 +107,37 @@ tapeFlush(const std::string& message,uint64_t bytes,uint64_t files,
m_reportPacker.reportFlush(m_drive.getCompression());
m_drive.clearCompressionStats();
}
//------------------------------------------------------------------------
// logAndCheckTapeAlertsForWrite
//------------------------------------------------------------------------------
bool castor::tape::tapeserver::daemon::TapeWriteSingleThread::
logAndCheckTapeAlertsForWrite() {
std::vector<uint16_t> tapeAlertCodes = m_drive.getTapeAlertCodes();
if (tapeAlertCodes.empty()) return false;
size_t alertNumber = 0;
// Log tape alerts in the logs.
std::vector<std::string> tapeAlerts = m_drive.getTapeAlerts(tapeAlertCodes);
for (std::vector<std::string>::iterator ta=tapeAlerts.begin();
ta!=tapeAlerts.end();ta++)
{
cta::log::ScopedParamContainer params(m_logContext);
params.add("tapeAlert",*ta)
.add("tapeAlertNumber", alertNumber++)
.add("tapeAlertCount", tapeAlerts.size());
m_logContext.log(cta::log::WARNING, "Tape alert detected");
}
// Add tape alerts in the tape log parameters
std::vector<std::string> tapeAlertsCompact =
m_drive.getTapeAlertsCompact(tapeAlertCodes);
for (std::vector<std::string>::iterator tac=tapeAlertsCompact.begin();
tac!=tapeAlertsCompact.end();tac++)
{
countTapeLogError(std::string("Error_")+*tac);
}
return(m_drive.tapeAlertsCriticalForWrite(tapeAlertCodes));
}
//------------------------------------------------------------------------------
// isTapeWritable
//-----------------------------------------------------------------------------
......@@ -179,9 +210,11 @@ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::run() {
currentErrorToCount = "Error_tapeLoad";
waitForDrive();
currentErrorToCount = "Error_checkingTapeAlert";
if (logTapeAlerts()) {
throw cta::exception::Exception("Aborting migration session in presence of tape alerts");
if(logAndCheckTapeAlertsForWrite()) {
throw cta::exception::Exception("Aborting migration session in"
" presence of critical tape alerts");
}
currentErrorToCount = "Error_tapeNotWriteable";
isTapeWritable();
......
......@@ -213,6 +213,12 @@ private:
void tapeFlush(const std::string& message,uint64_t bytes,uint64_t files,
cta::utils::Timer & timer);
/**
* After waiting for the drive, we will dump the tape alert log content, if it
* is not empty
* @return true if any critical for write alert was detected
*/
bool logAndCheckTapeAlertsForWrite();
virtual void run() ;
......
......@@ -350,6 +350,20 @@ std::vector<std::string> drive::DriveGeneric::getTapeAlertsCompact(const std::ve
return ret;
}
//------------------------------------------------------------------------------
// tapeAlertsCriticalForWrite
//------------------------------------------------------------------------------
bool drive::DriveGeneric::tapeAlertsCriticalForWrite(
const std::vector<uint16_t> & codes) {
for (std::vector<uint16_t>::const_iterator code = codes.begin();
code!= codes.end(); code++) {
if(SCSI::isTapeAlertCriticalForWrite(*code)) {
return true;
}
}
return false;
}
/**
* Set the tape density and compression.
* We use MODE SENSE/SELECT Device Configuration (10h) mode page.
......
......@@ -149,6 +149,15 @@ namespace drive {
*/
virtual std::vector<std::string> getTapeAlertsCompact(const std::vector<uint16_t> & codes);
/**
* Checks if there are tape alerts critical for the writing session present.
* @param codes The vector of the tape alert codes returned by drive.
* @return True if there are tape alerts critical for the writing session
* present and false otherwise.
*/
virtual bool tapeAlertsCriticalForWrite(
const std::vector<uint16_t> & codes);
/**
* Set the tape density and compression.
* We use MODE SENSE/SELECT Device Configuration (10h) mode page.
......
......@@ -186,6 +186,7 @@ namespace drive {
virtual std::vector<uint16_t> getTapeAlertCodes() = 0;
virtual std::vector<std::string> getTapeAlerts(const std::vector<uint16_t>&) = 0;
virtual std::vector<std::string> getTapeAlertsCompact (const std::vector<uint16_t>&) = 0;
virtual bool tapeAlertsCriticalForWrite(const std::vector<uint16_t> & codes) = 0;
virtual void setDensityAndCompression(bool compression = true,
unsigned char densityCode = 0) = 0;
virtual void enableCRC32CLogicalBlockProtectionReadOnly() = 0;
......
......@@ -839,8 +839,9 @@ TEST(castor_tape_drive_Drive, getTapeAlerts) {
std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive (
castor::tape::tapeserver::drive::createDrive(*i, sysWrapper));
EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(1);
std::vector<std::string> alerts = drive->getTapeAlerts(drive->getTapeAlertCodes());
ASSERT_EQ(3U, alerts.size());
std::vector<uint16_t> tapeAlertCodes = drive->getTapeAlertCodes();
std::vector<std::string> alerts = drive->getTapeAlerts(tapeAlertCodes);
ASSERT_EQ(4U, alerts.size());
ASSERT_FALSE(alerts.end() ==
find(alerts.begin(), alerts.end(),
std::string("Unexpected tapeAlert code: 0x41")));
......@@ -848,6 +849,18 @@ TEST(castor_tape_drive_Drive, getTapeAlerts) {
std::string("Obsolete tapeAlert code: 0x28")));
ASSERT_FALSE(alerts.end() == find(alerts.begin(), alerts.end(),
std::string("Forced eject")));
ASSERT_FALSE(alerts.end() == find(alerts.begin(), alerts.end(),
std::string("Lost statistics")));
ASSERT_TRUE(drive->tapeAlertsCriticalForWrite(tapeAlertCodes));
for (std::vector<uint16_t>::const_iterator code =
tapeAlertCodes.begin(); code!= tapeAlertCodes.end(); code++) {
if(castor::tape::SCSI::isTapeAlertCriticalForWrite(*code)) {
ASSERT_NE(0x32U, *code);
} else {
ASSERT_EQ(0x32U, *code);
}
}
}
}
}
......
......@@ -101,6 +101,10 @@ std::vector<std::string> castor::tape::tapeserver::drive::FakeDrive::getTapeAler
std::vector<std::string> empty;
return empty;
}
bool castor::tape::tapeserver::drive::FakeDrive::tapeAlertsCriticalForWrite(
const std::vector<uint16_t> & codes) {
return false;
}
void castor::tape::tapeserver::drive::FakeDrive::setDensityAndCompression(bool compression, unsigned char densityCode) {
throw cta::exception::Exception("FakeDrive::setDensityAndCompression Not implemented");
}
......
......@@ -73,6 +73,7 @@ namespace drive {
virtual std::vector<uint16_t> getTapeAlertCodes();
virtual std::vector<std::string> getTapeAlerts(const std::vector<uint16_t>&) ;
virtual std::vector<std::string> getTapeAlertsCompact(const std::vector<uint16_t>&) ;
virtual bool tapeAlertsCriticalForWrite(const std::vector<uint16_t> & codes);
virtual void setDensityAndCompression(bool compression = true,
unsigned char densityCode = 0) ;
virtual void enableCRC32CLogicalBlockProtectionReadOnly() ;
......
......@@ -943,6 +943,7 @@ int System::stDeviceFile::logSenseTapeAlerts(sg_io_hdr_t* sgio_h) {
case 0x28:
case 0x10:
case 65:
case 0x32: // tapeAlertLostStatistics
data[4] |= 1; /* Set flag */
}
i++; data += 5; remaining -=5;
......
Markdown is supported
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