diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp index fac9acb12b9c11cee2c41bbedd64358ce5d823a6..0da6ca6dbb42233e1d271a11c6d1da8cab210776 100644 --- a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp +++ b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp @@ -334,6 +334,39 @@ drive::positionInfo drive::DriveGeneric::getPositionInfo() return posInfo; } +/** + * Return physical position of the drive. + * + * @return physicalPositionInfo class. This contains the wrap and linear position (LPOS). + */ +drive::physicalPositionInfo drive::DriveGeneric::getPhysicalPositionInfo() +{ + SCSI::Structures::requestSenseCDB_t cdb; + SCSI::Structures::requestSenseData_t requestSenseData; + SCSI::Structures::senseData_t<255> senseBuff; + SCSI::Structures::LinuxSGIO_t sgh; + + // The full Request Sense data record is 96 bytes. However, we are only interested in + // the PHYSICAL WRAP and LPOS fields (bytes 29-33) so we can discard the rest. + cdb.allocationLength = 34; + + sgh.setCDB(&cdb); + sgh.setDataBuffer(&requestSenseData); + sgh.setSenseBuffer(&senseBuff); + sgh.dxfer_direction = SG_DXFER_FROM_DEV; + + // Manage both system error and SCSI errors + cta::exception::Errnum::throwOnMinusOne( + m_sysWrapper.ioctl(m_tapeFD, SG_IO, &sgh), + "Failed SG_IO ioctl in DriveGeneric::getPhysicalPositionInfo"); + SCSI::ExceptionLauncher(sgh, "SCSI error in getPhysicalPositionInfo:"); + + physicalPositionInfo posInfo; + posInfo.wrap = requestSenseData.physicalWrap; + posInfo.lpos = SCSI::Structures::toU32(requestSenseData.relativeLPOSValue); + return posInfo; +} + /** * Get tape alert information from the drive. There is a quite long list of possible tape alerts. * They are described in SSC-4, section 4.2.20: TapeAlert application client interface. diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp index dba963280f5e5766233464862648f6da9f118ce2..f1431d23462aa303e08dff1c58bed149eed8529d 100644 --- a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp +++ b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp @@ -132,7 +132,14 @@ namespace drive { * on the dirty data still in the write buffer. */ virtual positionInfo getPositionInfo() ; - + + /** + * Return physical position of the drive. + * + * @return physicalPositionInfo class. This contains the wrap and linear position (LPOS). + */ + virtual physicalPositionInfo getPhysicalPositionInfo(); + /** * Get tape alert information from the drive. There is a quite long list of possible tape alerts. * They are described in SSC-4, section 4.2.20: TapeAlert application client interface diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp b/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp index 3065307422161f70e1e49e751bab32500c559a70..9dfbdd7ac6075e7b35cc1cf083c287068c9d6c7b 100644 --- a/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp +++ b/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp @@ -111,12 +111,12 @@ namespace drive { uint32_t lpos; /** * FORWARD means the current direction is away from the - * physical beginning of tape. REVERSE means the current + * physical beginning of tape. BACKWARD means the current * direction is towards the physical beginning of tape. */ - enum Direction_t { FORWARD, REVERSE }; + enum Direction_t { FORWARD, BACKWARD }; Direction_t direction() { - return wrap & 1 ? REVERSE : FORWARD; + return wrap & 1 ? BACKWARD : FORWARD; } }; @@ -212,6 +212,7 @@ namespace drive { virtual std::string getSerialNumber() = 0; virtual void positionToLogicalObject(uint32_t blockId) = 0; virtual positionInfo getPositionInfo() = 0; + virtual physicalPositionInfo getPhysicalPositionInfo() = 0; 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; diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp b/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp index a5eea9d290de33831daccc75bce2c68a4c2130cc..cec6b287111811ac7b77aaefc961890a6b403d53 100644 --- a/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp +++ b/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp @@ -113,7 +113,8 @@ TEST(castor_tape_drive_Drive, getPositionInfoAndPositionToLogicalObject) { std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive ( castor::tape::tapeserver::drive::createDrive(*i, sysWrapper)); castor::tape::tapeserver::drive::positionInfo posInfo; - + castor::tape::tapeserver::drive::physicalPositionInfo physicalPosInfo; + EXPECT_CALL(sysWrapper, ioctl(_,_,An<sg_io_hdr_t*>())).Times(1); posInfo = drive->getPositionInfo(); @@ -121,7 +122,13 @@ TEST(castor_tape_drive_Drive, getPositionInfoAndPositionToLogicalObject) { ASSERT_EQ(0x12EFCDABU,posInfo.oldestDirtyObject); ASSERT_EQ(0xABCDEFU,posInfo.dirtyObjectsCount); ASSERT_EQ(0x12EFCDABU,posInfo.dirtyBytesCount); - + + EXPECT_CALL(sysWrapper, ioctl(_,_,An<sg_io_hdr_t*>())).Times(1); + physicalPosInfo = drive->getPhysicalPositionInfo(); + ASSERT_EQ(0x0, physicalPosInfo.wrap); + ASSERT_EQ(0x0, physicalPosInfo.lpos); + ASSERT_EQ(castor::tape::tapeserver::drive::physicalPositionInfo::FORWARD, physicalPosInfo.direction()); + EXPECT_CALL(sysWrapper, ioctl(_,_,An<sg_io_hdr_t*>())).Times(1); drive->positionToLogicalObject(0xABCDEF0); diff --git a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp index a93c10a6dd15c92f2c9cd06c09e23940eea85b02..903fa0ddf20c259739170277b7340e399a1a4978 100644 --- a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp +++ b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp @@ -81,6 +81,7 @@ void castor::tape::tapeserver::drive::FakeDrive::positionToLogicalObject(uint32_ } m_currentPosition = blockId; } + castor::tape::tapeserver::drive::positionInfo castor::tape::tapeserver::drive::FakeDrive::getPositionInfo() { positionInfo pos; pos.currentPosition = m_currentPosition; @@ -90,6 +91,13 @@ castor::tape::tapeserver::drive::positionInfo castor::tape::tapeserver::drive::F return pos; } +castor::tape::tapeserver::drive::physicalPositionInfo castor::tape::tapeserver::drive::FakeDrive::getPhysicalPositionInfo() { + physicalPositionInfo pos; + pos.lpos = 0; + pos.wrap = m_currentPosition; + return pos; +} + std::vector<uint16_t> castor::tape::tapeserver::drive::FakeDrive::getTapeAlertCodes() { std::vector<uint16_t> empty; return empty; diff --git a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp index 4313c41795790b9c67ddd06ac1128d71fb9ab1c6..fbadd76acf29f627ab683e0f33aa066b38a7f64a 100644 --- a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp +++ b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp @@ -71,6 +71,7 @@ namespace drive { virtual std::string getSerialNumber() ; virtual void positionToLogicalObject(uint32_t blockId) ; virtual positionInfo getPositionInfo() ; + virtual physicalPositionInfo getPhysicalPositionInfo(); 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>&) ;