diff --git a/tapeserver/castor/tape/tapeserver/SCSI/Structures.hpp b/tapeserver/castor/tape/tapeserver/SCSI/Structures.hpp index c5d1edbc1f817b42f6825be9998e9440c1c98ab0..55ba6fe6ce242ff5024d0dc9ccaeec505bd6e3a8 100644 --- a/tapeserver/castor/tape/tapeserver/SCSI/Structures.hpp +++ b/tapeserver/castor/tape/tapeserver/SCSI/Structures.hpp @@ -1224,6 +1224,10 @@ namespace SCSI { unsigned char reserved[2]; // Reserved unsigned char logicalObjectIdentifier[6]; // The logical object identifier of the object at the end of the above wrap } wrapDescriptor[maxLTOTapeWraps]; // Array of wrap descriptiors + + uint16_t getNbWrapsReturned(){ + return (SCSI::Structures::toU16(responseDataLength) / sizeof(wrapDescriptor)); + } }; /** diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp index 0da6ca6dbb42233e1d271a11c6d1da8cab210776..f05f526943fc753d3873551a7f51a61cae05e6c8 100644 --- a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp +++ b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp @@ -118,6 +118,44 @@ void drive::DriveLTO::clearCompressionStats() { SCSI::ExceptionLauncher(sgh, "SCSI error in clearCompressionStats:"); } +std::vector<castor::tape::tapeserver::drive::endOfWrapPosition> drive::DriveLTO::getEndOfWrapPositions() { + std::vector<castor::tape::tapeserver::drive::endOfWrapPosition> ret; + + SCSI::Structures::readEndOfWrapPositionCDB_t cdb; + //WrapNumbeValid = 0, ReportAll = 1 and WrapNumber = 0 as we want all the end of wraps positions + cdb.WNV = 0; + cdb.RA = 1; + cdb.wrapNumber = 0; + //Each wrap descriptor is 12 bytes + SCSI::Structures::setU32(cdb.allocationLength,12 * castor::tape::SCSI::maxLTOTapeWraps); + + SCSI::Structures::readEndOfWrapPositionDataLongForm_t data; + + SCSI::Structures::LinuxSGIO_t sgh; + sgh.setCDB(&cdb); + sgh.setDataBuffer(&data); + 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 DriveLTO::getEndOfWrapPositions"); + SCSI::ExceptionLauncher(sgh, "SCSI error in getEndOfWrapPositions:"); + + int nbWrapReturned = data.getNbWrapsReturned(); + //Loop over the list of wraps of the tape returned by the drive + for(int i = 0; i < nbWrapReturned; ++i){ + castor::tape::tapeserver::drive::endOfWrapPosition position; + auto wrapDescriptor = data.wrapDescriptor[i]; + position.wrapNumber = SCSI::Structures::toU16(wrapDescriptor.wrapNumber); + position.partition = SCSI::Structures::toU16(wrapDescriptor.partition); + //blockId returned is 6*8 = 48 bytes, so we need to store it into a uint64_t + position.blockId = SCSI::Structures::toU64(wrapDescriptor.logicalObjectIdentifier); + ret.push_back(position); + } + return ret; +} + /** * Information about the drive. The vendor id is used in the user labels of the files. * @return The deviceInfo structure with the information about the drive. @@ -367,6 +405,15 @@ drive::physicalPositionInfo drive::DriveGeneric::getPhysicalPositionInfo() return posInfo; } +/** +* Returns all the end of wrap positions of the mounted tape +* +* @return a vector of endOfWrapsPositions. +*/ +std::vector<drive::endOfWrapPosition> drive::DriveGeneric::getEndOfWrapPositions() { + return std::vector<drive::endOfWrapPosition>(); +} + /** * 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 f1431d23462aa303e08dff1c58bed149eed8529d..2702ba46200139084eaa9fe80113717dca8a2398 100644 --- a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp +++ b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp @@ -139,6 +139,14 @@ namespace drive { * @return physicalPositionInfo class. This contains the wrap and linear position (LPOS). */ virtual physicalPositionInfo getPhysicalPositionInfo(); + + /** + * Returns all the end of wrap positions of the mounted tape + * + * @return a vector of endOfWrapsPositions. + */ + virtual std::vector<endOfWrapPosition> getEndOfWrapPositions(); + /** * Get tape alert information from the drive. There is a quite long list of possible tape alerts. @@ -583,6 +591,7 @@ namespace drive { virtual compressionStats getCompression(); virtual void clearCompressionStats(); + virtual std::vector<castor::tape::tapeserver::drive::endOfWrapPosition> getEndOfWrapPositions(); }; class DriveIBM3592 : public DriveGeneric { diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp b/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp index 9dfbdd7ac6075e7b35cc1cf083c287068c9d6c7b..8ed49e4497512e203ab0a720e1a62616764a6b31 100644 --- a/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp +++ b/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp @@ -120,6 +120,18 @@ namespace drive { } }; + /** + * End of wraps position infos + * + * It is used by the getEndOfWrapPositions() method + */ + class endOfWrapPosition{ + public: + uint16_t wrapNumber; + uint64_t blockId; + uint16_t partition; + }; + /** * Logical block protection nformation, returned by getLBPInfo() */ @@ -213,6 +225,7 @@ namespace drive { virtual void positionToLogicalObject(uint32_t blockId) = 0; virtual positionInfo getPositionInfo() = 0; virtual physicalPositionInfo getPhysicalPositionInfo() = 0; + virtual std::vector<endOfWrapPosition> getEndOfWrapPositions() = 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/FakeDrive.cpp b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp index 903fa0ddf20c259739170277b7340e399a1a4978..d37e78c47bde9a9d13816ed346d1617622da0422 100644 --- a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp +++ b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp @@ -98,6 +98,10 @@ castor::tape::tapeserver::drive::physicalPositionInfo castor::tape::tapeserver:: return pos; } +std::vector<castor::tape::tapeserver::drive::endOfWrapPosition> castor::tape::tapeserver::drive::FakeDrive::getEndOfWrapPositions() { + return std::vector<castor::tape::tapeserver::drive::endOfWrapPosition>(); +} + 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 fbadd76acf29f627ab683e0f33aa066b38a7f64a..cdcf6e104b4060f5f318c072a5b16eb5eadfc754 100644 --- a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp +++ b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp @@ -72,6 +72,7 @@ namespace drive { virtual void positionToLogicalObject(uint32_t blockId) ; virtual positionInfo getPositionInfo() ; virtual physicalPositionInfo getPhysicalPositionInfo(); + virtual std::vector<endOfWrapPosition> getEndOfWrapPositions(); 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>&) ;