diff --git a/tapeserver/castor/tape/tapeserver/SCSI/Constants.cpp b/tapeserver/castor/tape/tapeserver/SCSI/Constants.cpp index 7e45db6bbc714c5cc39d5e762732c86fd9550c2c..02783a21c535a6de067184775c638d9711f59b6f 100644 --- a/tapeserver/castor/tape/tapeserver/SCSI/Constants.cpp +++ b/tapeserver/castor/tape/tapeserver/SCSI/Constants.cpp @@ -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 diff --git a/tapeserver/castor/tape/tapeserver/SCSI/Constants.hpp b/tapeserver/castor/tape/tapeserver/SCSI/Constants.hpp index 77d9e806e4fd9781efcb9f08d6ba0c7cb9c22391..e0f2c7b673248a390b7d8899ca32571784f060a8 100644 --- a/tapeserver/castor/tape/tapeserver/SCSI/Constants.hpp +++ b/tapeserver/castor/tape/tapeserver/SCSI/Constants.hpp @@ -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: diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp b/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp index bab899fa98cfdce81f71b7fa0692ed6fe3e61883..79661cb528e41545d8583953f9c63f9e06f207f3 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp @@ -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(); diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.hpp b/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.hpp index 3b7132be6033499a031489fed14c36aa91be8c68..cc139b27c37a6bead671d446bde8e6c7dd4d234d 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.hpp +++ b/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.hpp @@ -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() ; diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp index 5473d9d679f76360ab17c5f2df9ec8441bf2c9df..965c62fdee5ea6b9801b91648a5d4ead1ef2b19b 100644 --- a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp +++ b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp @@ -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. diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp index 005589621903d4fab770d25db47e17e7229ccd81..025c683e29b8894f4a0fd84bc2d3826acae0935c 100644 --- a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp +++ b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp @@ -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. diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp b/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp index 36ce1d5ef6c72281d7c44ca458b3b8f5c610d653..40c078444f7a70bb0bdf197777d4d21e9961baff 100644 --- a/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp +++ b/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp @@ -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; diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp b/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp index 2bf23d0e71ea09ad19729a11c29ffa4c59087166..dc5f6242eec9dc6d11a2fbb3392246d5ffadda41 100644 --- a/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp +++ b/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp @@ -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); + } + } } } } diff --git a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp index 758756afa7f2a013b962532dd70b784e7cc5a5a3..3e6abebc52702e6175fd4efbd1993c89dcd1ca6b 100644 --- a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp +++ b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp @@ -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"); } diff --git a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp index fa9845f657a72357417b3d277aa0d31020ddde97..1361da388bd28dac58ce35dd7c58bf9996591b82 100644 --- a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp +++ b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp @@ -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() ; diff --git a/tapeserver/castor/tape/tapeserver/system/FileWrappers.cpp b/tapeserver/castor/tape/tapeserver/system/FileWrappers.cpp index b8ce64335ce95f0fc1671c3ac57f38d443c382fe..e226fbfc7218e610092d9d23ac10335c468962e0 100644 --- a/tapeserver/castor/tape/tapeserver/system/FileWrappers.cpp +++ b/tapeserver/castor/tape/tapeserver/system/FileWrappers.cpp @@ -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;