diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp index 605de98a1a41cda295d1f7dc859e42e5bbe50477..99f6f3ea051c5254532493727f3f3bb95a30b622 100644 --- a/catalogue/RdbmsCatalogue.cpp +++ b/catalogue/RdbmsCatalogue.cpp @@ -25,6 +25,7 @@ #include "catalogue/SqliteCatalogueSchema.hpp" #include "common/dataStructures/EntryLog.hpp" #include "common/dataStructures/TapeFile.hpp" +#include "common/dataStructures/LabelFormat.hpp" #include "common/exception/Exception.hpp" #include "common/exception/LostDatabaseConnection.hpp" #include "common/exception/UserError.hpp" @@ -4013,6 +4014,8 @@ std::list<common::dataStructures::Tape> RdbmsCatalogue::getTapes(rdbms::Conn &co "TAPE.IS_FROM_CASTOR AS IS_FROM_CASTOR," + "TAPE.LABEL_FORMAT AS LABEL_FORMAT," + "TAPE.LABEL_DRIVE AS LABEL_DRIVE," "TAPE.LABEL_TIME AS LABEL_TIME," @@ -4186,6 +4189,8 @@ std::list<common::dataStructures::Tape> RdbmsCatalogue::getTapes(rdbms::Conn &co tape.dirty = rset.columnBool("DIRTY"); tape.isFromCastor = rset.columnBool("IS_FROM_CASTOR"); + tape.labelFormat = common::dataStructures::Label::validateFormat(rset.columnOptionalUint8("LABEL_FORMAT"), "[RdbmsCatalogue::getTapes()]"); + tape.labelLog = getTapeLogFromRset(rset, "LABEL_DRIVE", "LABEL_TIME"); tape.lastReadLog = getTapeLogFromRset(rset, "LAST_READ_DRIVE", "LAST_READ_TIME"); tape.lastWriteLog = getTapeLogFromRset(rset, "LAST_WRITE_DRIVE", "LAST_WRITE_TIME"); @@ -4246,6 +4251,7 @@ common::dataStructures::VidToTapeMap RdbmsCatalogue::getTapesByVid(const std::st "TAPE.LAST_FSEQ AS LAST_FSEQ," "TAPE.IS_FULL AS IS_FULL," "TAPE.IS_FROM_CASTOR AS IS_FROM_CASTOR," + "TAPE.LABEL_FORMAT AS LABEL_FORMAT," "TAPE.LABEL_DRIVE AS LABEL_DRIVE," "TAPE.LABEL_TIME AS LABEL_TIME," "TAPE.LAST_READ_DRIVE AS LAST_READ_DRIVE," @@ -4387,6 +4393,8 @@ std::string RdbmsCatalogue::getSelectTapesBy100VidsSql() const { "TAPE.IS_FULL AS IS_FULL," "TAPE.IS_FROM_CASTOR AS IS_FROM_CASTOR," + "TAPE.LABEL_FORMAT AS LABEL_FORMAT," + "TAPE.LABEL_DRIVE AS LABEL_DRIVE," "TAPE.LABEL_TIME AS LABEL_TIME," @@ -4456,6 +4464,9 @@ void RdbmsCatalogue::executeGetTapesByVidStmtAndCollectResults(rdbms::Stmt &stmt tape.lastFSeq = rset.columnUint64("LAST_FSEQ"); tape.full = rset.columnBool("IS_FULL"); tape.isFromCastor = rset.columnBool("IS_FROM_CASTOR"); + + tape.labelFormat = common::dataStructures::Label::validateFormat(rset.columnOptionalUint8("LABEL_FORMAT"), "[RdbmsCatalogue::executeGetTapesByVidsStmtAndCollectResults()]"); + tape.labelLog = getTapeLogFromRset(rset, "LABEL_DRIVE", "LABEL_TIME"); tape.lastReadLog = getTapeLogFromRset(rset, "LAST_READ_DRIVE", "LAST_READ_TIME"); tape.lastWriteLog = getTapeLogFromRset(rset, "LAST_WRITE_DRIVE", "LAST_WRITE_TIME"); @@ -9224,7 +9235,8 @@ std::list<TapeForWriting> RdbmsCatalogue::getTapesForWriting(const std::string & "VIRTUAL_ORGANIZATION.VIRTUAL_ORGANIZATION_NAME AS VO," "MEDIA_TYPE.CAPACITY_IN_BYTES AS CAPACITY_IN_BYTES," "TAPE.DATA_IN_BYTES AS DATA_IN_BYTES," - "TAPE.LAST_FSEQ AS LAST_FSEQ " + "TAPE.LAST_FSEQ AS LAST_FSEQ," + "TAPE.LABEL_FORMAT AS LABEL_FORMAT " "FROM " "TAPE " "INNER JOIN TAPE_POOL ON " @@ -9259,6 +9271,7 @@ std::list<TapeForWriting> RdbmsCatalogue::getTapesForWriting(const std::string & tape.capacityInBytes = rset.columnUint64("CAPACITY_IN_BYTES"); tape.dataOnTapeInBytes = rset.columnUint64("DATA_IN_BYTES"); tape.lastFSeq = rset.columnUint64("LAST_FSEQ"); + tape.labelFormat = common::dataStructures::Label::validateFormat(rset.columnOptionalUint8("LABEL_FORMAT"), "[RdbmsCatalogue::getTapesForWriting()]"); tapes.push_back(tape); } diff --git a/catalogue/TapeForWriting.hpp b/catalogue/TapeForWriting.hpp index 6e934f9af073ca28811156c05d1d823197282365..18dcb874a6ac4e7d5378647521d3c92ef8ec1075 100644 --- a/catalogue/TapeForWriting.hpp +++ b/catalogue/TapeForWriting.hpp @@ -18,6 +18,7 @@ #pragma once #include <optional> +#include "common/dataStructures/LabelFormat.hpp" #include <ostream> #include <stdint.h> #include <string> @@ -88,6 +89,10 @@ struct TapeForWriting { * The total amount of data written to the tape in bytes. */ uint64_t dataOnTapeInBytes; + /** + * The format type of the tape. + */ + cta::common::dataStructures::Label::Format labelFormat; }; // struct TapeForWriting diff --git a/common/dataStructures/LabelFormat.hpp b/common/dataStructures/LabelFormat.hpp new file mode 100644 index 0000000000000000000000000000000000000000..631e81ea4ab3d47ba20eb83c2d8e92e5054b622f --- /dev/null +++ b/common/dataStructures/LabelFormat.hpp @@ -0,0 +1,62 @@ +/* + * @project The CERN Tape Archive (CTA) + * @copyright Copyright © 2021-2022 CERN + * @license This program is free software, distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". You can + * redistribute it and/or modify it under the terms of the GPL Version 3, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * In applying this licence, CERN does not waive the privileges and immunities + * granted to it by virtue of its status as an Intergovernmental Organization or + * submit itself to any jurisdiction. + */ + +#pragma once + +#include "common/exception/InvalidArgument.hpp" + +#include <sstream> +#include <iomanip> +#include <optional> + +namespace cta { +namespace common { +namespace dataStructures { + + struct Label { + + enum class Format : std::uint8_t { + CTA = 0x00 + }; + + static Format validateFormat(const std::optional<std::uint8_t>& ouiFormat, const std::string& strContext) { + return validateFormat(ouiFormat.value_or(0x00), strContext); + } + + static Format validateFormat(const std::uint8_t uiFormat, const std::string& strContext) { + Format format = static_cast<Format>(uiFormat); + switch(format) { + case Format::CTA: + return format; + default: + { + std::ostringstream ex_str; + ex_str << strContext << ": Unknown label format " << std::showbase << std::internal << std::setfill('0') << std::hex << std::setw(4) << static_cast<unsigned int>(uiFormat); + throw cta::exception::InvalidArgument(ex_str.str()); + } + } + } + // prevent the generation of default public constructor and destructor + protected: + Label() = default; + virtual ~Label() = default; + + }; + +} // namespace dataStructures +} // namespace common +} // namespace cta diff --git a/common/dataStructures/Tape.hpp b/common/dataStructures/Tape.hpp index 19aaa117172ba8a8d66eb2dd6d0808d566d6ad21..eaade151e03b77fc2dd2695e884d195305a32408 100644 --- a/common/dataStructures/Tape.hpp +++ b/common/dataStructures/Tape.hpp @@ -19,6 +19,7 @@ #include "common/dataStructures/EntryLog.hpp" #include "common/dataStructures/TapeLog.hpp" +#include "common/dataStructures/LabelFormat.hpp" #include <list> #include <map> @@ -85,6 +86,8 @@ struct Tape { uint64_t nbMasterFiles; uint64_t masterDataInBytes; + cta::common::dataStructures::Label::Format labelFormat; + /** * The optional name of the encryption key. * diff --git a/scheduler/ArchiveMount.cpp b/scheduler/ArchiveMount.cpp index f7359da2d6542ca9c61f95e174eb44c414bf8a08..70f739be77a773de58028fd8e14a9b1b7e5244b2 100644 --- a/scheduler/ArchiveMount.cpp +++ b/scheduler/ArchiveMount.cpp @@ -105,6 +105,13 @@ uint32_t cta::ArchiveMount::getNbFiles() const { return m_dbMount->nbFilesCurrentlyOnTape; } +//------------------------------------------------------------------------------ +// getLabelFormat +//------------------------------------------------------------------------------ +cta::common::dataStructures::Label::Format cta::ArchiveMount::getLabelFormat() const { + return m_dbMount->mountInfo.labelFormat; +} + //------------------------------------------------------------------------------ // createDiskReporter //------------------------------------------------------------------------------ diff --git a/scheduler/ArchiveMount.hpp b/scheduler/ArchiveMount.hpp index 22d43278fcc1902f4202430464bbe6a817c309f2..ca589d49b16742c59b4a0497935bd5c2a7a7df95 100644 --- a/scheduler/ArchiveMount.hpp +++ b/scheduler/ArchiveMount.hpp @@ -189,6 +189,12 @@ namespace cta { */ uint32_t getNbFiles() const override; + /** + * Returns the label format of the tape + * @return the label format of the tape + */ + cta::common::dataStructures::Label::Format getLabelFormat() const; + /** * Creates a disk reporter for the ArchiveJob (this is a wrapper). * @param URL: report address diff --git a/scheduler/OStoreDB/OStoreDB.cpp b/scheduler/OStoreDB/OStoreDB.cpp index 99886b233a67a69184e1a84019b26fe944c0c688..89c10f8fa0f7b77eed8728ea9e05c4831a8a670c 100644 --- a/scheduler/OStoreDB/OStoreDB.cpp +++ b/scheduler/OStoreDB/OStoreDB.cpp @@ -419,6 +419,7 @@ void OStoreDB::fetchMountInfo(SchedulerDatabase::TapeMountDecisionInfo& tmdi, Ro m.mediaType = ""; // The logical library is not known here, and will be determined by the caller. m.vo = ""; // The vo is not known here, and will be determined by the caller. m.capacityInBytes = 0; // The capacity is not known here, and will be determined by the caller. + m.labelFormat = vidToTapeMap.at(rqp.vid).labelFormat; m.activity = ac.activity; m.mountPolicyNames = queueMountPolicyNames; // We will display the sleep flag only if it is not expired (15 minutes timeout, hardcoded). @@ -451,6 +452,7 @@ void OStoreDB::fetchMountInfo(SchedulerDatabase::TapeMountDecisionInfo& tmdi, Ro m.mediaType = ""; // The logical library is not known here, and will be determined by the caller. m.vo = ""; // The vo is not known here, and will be determined by the caller. m.capacityInBytes = 0; // The capacity is not known here, and will be determined by the caller. + m.labelFormat = vidToTapeMap.at(rqp.vid).labelFormat; m.mountPolicyNames = queueMountPolicyNames; // We will display the sleep flag only if it is not expired (15 minutes timeout, hardcoded). // This allows having a single decision point instead of implementing is at the consumer levels. @@ -799,7 +801,8 @@ std::unique_ptr<SchedulerDatabase::ArchiveMount> OStoreDB::TapeMountDecisionInfo const std::string& mediaType, const std::string& vendor, const uint64_t capacityInBytes, - time_t startTime) { + time_t startTime, const std::optional<std::string>& activity, + cta::common::dataStructures::Label::Format labelFormat) { throw cta::exception::Exception("In OStoreDB::TapeMountDecisionInfoNoLock::createArchiveMount(): This function should not be called"); } @@ -816,7 +819,8 @@ std::unique_ptr<SchedulerDatabase::RetrieveMount> OStoreDB::TapeMountDecisionInf const std::string& mediaType, const std::string& vendor, const uint64_t capacityInBytes, - time_t startTime, const std::optional<std::string> &activity) { + time_t startTime, const std::optional<std::string> &activity, + cta::common::dataStructures::Label::Format labelFormat) { throw cta::exception::Exception("In OStoreDB::TapeMountDecisionInfoNoLock::createRetrieveMount(): This function should not be called"); } @@ -3168,7 +3172,7 @@ std::unique_ptr<SchedulerDatabase::ArchiveMount> OStoreDB::TapeMountDecisionInfo common::dataStructures::MountType type, const catalogue::TapeForWriting & tape, const std::string& driveName, const std::string& logicalLibrary, const std::string& hostName, const std::string& vo, const std::string& mediaType, - const std::string& vendor, uint64_t capacityInBytes, time_t startTime) { + const std::string& vendor, uint64_t capacityInBytes, time_t startTime, const std::optional<std::string>& activity, cta::common::dataStructures::Label::Format labelFormat) { // In order to create the mount, we have to: // Check we actually hold the scheduling lock // Set the drive status to up, and indicate which tape we use. @@ -3200,6 +3204,7 @@ std::unique_ptr<SchedulerDatabase::ArchiveMount> OStoreDB::TapeMountDecisionInfo am.mountInfo.host = hostName; am.mountInfo.vo = vo; am.mountInfo.mediaType = mediaType; + am.mountInfo.labelFormat = labelFormat; am.mountInfo.vendor = vendor; am.mountInfo.mountId = m_schedulerGlobalLock->getIncreaseCommitMountId(); am.mountInfo.capacityInBytes = capacityInBytes; @@ -3249,7 +3254,7 @@ std::unique_ptr<SchedulerDatabase::RetrieveMount> OStoreDB::TapeMountDecisionInf const std::string& vid, const std::string& tapePool, const std::string& driveName, const std::string& logicalLibrary, const std::string& hostName, const std::string& vo, const std::string& mediaType, const std::string& vendor, const uint64_t capacityInBytes, time_t startTime, - const std::optional<std::string>& activity) { + const std::optional<std::string>& activity, cta::common::dataStructures::Label::Format labelFormat) { // In order to create the mount, we have to: // Check we actually hold the scheduling lock // Check the tape exists, add it to ownership and set its activity status to @@ -3281,6 +3286,7 @@ std::unique_ptr<SchedulerDatabase::RetrieveMount> OStoreDB::TapeMountDecisionInf rm.mountInfo.mediaType = mediaType; rm.mountInfo.vendor = vendor; rm.mountInfo.capacityInBytes = capacityInBytes; + rm.mountInfo.labelFormat = labelFormat; rm.mountInfo.activity = activity; // Update the status of the drive in the registry { diff --git a/scheduler/OStoreDB/OStoreDB.hpp b/scheduler/OStoreDB/OStoreDB.hpp index 8a407d55608832ba62361f96c3383c1a123dc78d..96688c41f86fd26edd44f405f99be6f71218fe03 100644 --- a/scheduler/OStoreDB/OStoreDB.hpp +++ b/scheduler/OStoreDB/OStoreDB.hpp @@ -26,6 +26,7 @@ #include "catalogue/Catalogue.hpp" #include "catalogue/TapeDrivesCatalogueState.hpp" #include "common/dataStructures/JobQueueType.hpp" +#include "common/dataStructures/LabelFormat.hpp" #include "common/log/Logger.hpp" #include "common/threading/BlockingQueue.hpp" #include "common/threading/Thread.hpp" @@ -112,7 +113,9 @@ class OStoreDB: public SchedulerDatabase { const std::string& hostName, const std::string& vo, const std::string& mediaType, const std::string& vendor, uint64_t capacityInBytes, - time_t startTime) override; + time_t startTime, + const std::optional<std::string> &activity, + cta::common::dataStructures::Label::Format labelFormat) override; std::unique_ptr<SchedulerDatabase::RetrieveMount> createRetrieveMount( const std::string& vid, const std::string& tapePool, const std::string& driveName, @@ -121,7 +124,8 @@ class OStoreDB: public SchedulerDatabase { const std::string& vendor, const uint64_t capacityInBytes, time_t startTime, - const std::optional<std::string> &activity) override; + const std::optional<std::string> &activity, + cta::common::dataStructures::Label::Format labelFormat) override; virtual ~TapeMountDecisionInfo(); private: @@ -141,7 +145,9 @@ class OStoreDB: public SchedulerDatabase { const std::string& driveName, const std::string& logicalLibrary, const std::string& hostName, const std::string& vo, const std::string& mediaType, const std::string& vendor, uint64_t capacityInBytes, - time_t startTime) override; + time_t startTime, + const std::optional<std::string> &activity, + cta::common::dataStructures::Label::Format labelFormat) override; std::unique_ptr<SchedulerDatabase::RetrieveMount> createRetrieveMount( const std::string& vid, const std::string & tapePool, const std::string& driveName, @@ -150,7 +156,8 @@ class OStoreDB: public SchedulerDatabase { const std::string& vendor, const uint64_t capacityInBytes, time_t startTime, - const std::optional<std::string> &activity) override; + const std::optional<std::string> &activity, + cta::common::dataStructures::Label::Format labelFormat) override; virtual ~TapeMountDecisionInfoNoLock(); }; diff --git a/scheduler/OStoreDB/OStoreDBTest.cpp b/scheduler/OStoreDB/OStoreDBTest.cpp index ed87cf5e5503930c68a83a42a87f31c402ecb939..d1fce2155065d1e3a3c6b423a9cf4482d18902e9 100644 --- a/scheduler/OStoreDB/OStoreDBTest.cpp +++ b/scheduler/OStoreDB/OStoreDBTest.cpp @@ -172,7 +172,7 @@ TEST_P(OStoreDBTest, getBatchArchiveJob) { tape.tapePool = "Tapepool1"; tape.vid = "tape"; auto mount = mountInfo->createArchiveMount(cta::common::dataStructures::MountType::ArchiveForUser, - tape, "drive", "library", "host", "vo", "mediaType", "vendor", 123456789, ::time(nullptr)); + tape, "drive", "library", "host", "vo", "mediaType", "vendor", 123456789, ::time(nullptr), std::nullopt, cta::common::dataStructures::Label::Format::CTA); auto giveAll = std::numeric_limits<uint64_t>::max(); auto jobs = mount->getNextJobBatch(giveAll, giveAll, lc); ASSERT_EQ(8, jobs.size()); diff --git a/scheduler/RetrieveMount.cpp b/scheduler/RetrieveMount.cpp index 758721689ae0d949acecdd69d145d34a0ecec7a2..ceb8b31ebef02d422ae7b64b8aa0d229c4bd8bf8 100644 --- a/scheduler/RetrieveMount.cpp +++ b/scheduler/RetrieveMount.cpp @@ -146,10 +146,19 @@ std::string cta::RetrieveMount::getDrive() const //------------------------------------------------------------------------------ uint64_t cta::RetrieveMount::getCapacityInBytes() const { if(!m_dbMount.get()) - throw exception::Exception("In cta::RetrieveMount::getVendor(): got NULL dbMount"); + throw exception::Exception("In cta::RetrieveMount::getCapacityInBytes(): got NULL dbMount"); return m_dbMount->mountInfo.capacityInBytes; } +//------------------------------------------------------------------------------ +// getLabelFormat() +//------------------------------------------------------------------------------ +cta::common::dataStructures::Label::Format cta::RetrieveMount::getLabelFormat() const { + if(!m_dbMount.get()) + throw exception::Exception("In cta::RetrieveMount::getLabelFormat(): got NULL dbMount"); + return m_dbMount->mountInfo.labelFormat; +} + //------------------------------------------------------------------------------ // getNextJobBatch() //------------------------------------------------------------------------------ diff --git a/scheduler/RetrieveMount.hpp b/scheduler/RetrieveMount.hpp index 0df67e4d88858e5b7f099afd5ca176acba9695c6..a75fd29d8181e76ccbc1c0c909b47f89fca50001 100644 --- a/scheduler/RetrieveMount.hpp +++ b/scheduler/RetrieveMount.hpp @@ -129,6 +129,12 @@ namespace cta { */ uint64_t getCapacityInBytes() const; + /** + * Returns the media format of the tape + * @return the media format of the tape + */ + virtual cta::common::dataStructures::Label::Format getLabelFormat() const; + /** * Report a drive status change */ diff --git a/scheduler/Scheduler.cpp b/scheduler/Scheduler.cpp index 96499d16018fde382e8cd35aaeb5da264f787887..1b4d91d743799476dc34721498bb3a803ad23125 100644 --- a/scheduler/Scheduler.cpp +++ b/scheduler/Scheduler.cpp @@ -1051,6 +1051,7 @@ void Scheduler::sortAndGetTapesForMountInfo(std::unique_ptr<SchedulerDatabase::T m.mediaType = retrieveTapesInfo[m.vid].mediaType; m.vo = retrieveTapesInfo[m.vid].vo; m.capacityInBytes = retrieveTapesInfo[m.vid].capacityInBytes; + m.labelFormat = retrieveTapesInfo[m.vid].labelFormat; } } } @@ -1533,7 +1534,9 @@ auto logicalLibrary = getLogicalLibrary(logicalLibraryName,getLogicalLibrariesTi t.mediaType, t.vendor, t.capacityInBytes, - time(NULL)).release()); + time(NULL), + std::nullopt, + t.labelFormat).release()); mountCreationTime += timer.secs(utils::Timer::resetCounter); internalRet->m_sessionRunning = true; driveStatusSetTime += timer.secs(utils::Timer::resetCounter); @@ -1602,7 +1605,9 @@ auto logicalLibrary = getLogicalLibrary(logicalLibraryName,getLogicalLibrariesTi m->mediaType, m->vendor, m->capacityInBytes, - time(NULL), m->activity).release()); + time(NULL), + m->activity, + m->labelFormat).release()); mountCreationTime += timer.secs(utils::Timer::resetCounter); internalRet->m_sessionRunning = true; internalRet->m_diskRunning = true; @@ -1619,10 +1624,13 @@ auto logicalLibrary = getLogicalLibrary(logicalLibraryName,getLogicalLibrariesTi } catch(...) {} schedulerDbTime = getMountInfoTime + queueTrimingTime + mountCreationTime + driveStatusSetTime; catalogueTime = getTapeInfoTime + getTapeForWriteTime; + std::ostringstream ossLabelFormat; + ossLabelFormat << std::showbase << std::internal << std::setfill('0') << std::hex << std::setw(4) << static_cast<unsigned int>(m->labelFormat); params.add("tapePool", m->tapePool) .add("tapeVid", m->vid) .add("vo",m->vo) .add("mediaType",m->mediaType) + .add("labelFormat",ossLabelFormat.str()) .add("vendor",m->vendor) .add("mountType", common::dataStructures::toString(m->type)) .add("existingMountsDistinctTypeForThisTapepool", existingMountsDistinctTypeForThisTapepool) diff --git a/scheduler/SchedulerDatabase.hpp b/scheduler/SchedulerDatabase.hpp index bff847fd5a8a3410f76633c9281d4b874fb87654..627ad90f37e1a1c3e164a299f0a534d8a8a9cfe5 100644 --- a/scheduler/SchedulerDatabase.hpp +++ b/scheduler/SchedulerDatabase.hpp @@ -191,6 +191,7 @@ class SchedulerDatabase { std::string host; uint64_t mountId; uint64_t capacityInBytes; + cta::common::dataStructures::Label::Format labelFormat; cta::common::dataStructures::MountType mountType; } mountInfo; virtual const MountInfo & getMountInfo() = 0; @@ -428,6 +429,7 @@ class SchedulerDatabase { uint64_t capacityInBytes; uint64_t mountId; std::optional<std::string> activity; + cta::common::dataStructures::Label::Format labelFormat; } mountInfo; virtual const MountInfo & getMountInfo() = 0; virtual std::list<std::unique_ptr<cta::SchedulerDatabase::RetrieveJob>> getNextJobBatch(uint64_t filesRequested, @@ -651,6 +653,7 @@ class SchedulerDatabase { std::string mediaType; // Media type of the tape std::string vendor; // Vendor of the tape uint64_t capacityInBytes; // Capacity in bytes of the tape + cta::common::dataStructures::Label::Format labelFormat; // Label format of the tape uint64_t priority; /**< The priority for the mount, defined as the highest * priority of all queued jobs */ @@ -764,7 +767,8 @@ class SchedulerDatabase { const std::string& vo, const std::string& mediaType, const std::string& vendor, const uint64_t capacityInBytes, - time_t startTime) = 0; + time_t startTime, const std::optional<std::string> &activity, + cta::common::dataStructures::Label::Format labelFormat) = 0; /** * Create a new retrieve mount. This implicitly releases the global scheduling * lock. @@ -775,7 +779,8 @@ class SchedulerDatabase { const std::string& vo, const std::string& mediaType, const std::string& vendor, const uint64_t capacityInBytes, - time_t startTime, const std::optional<std::string> &activity) = 0; + time_t startTime, const std::optional<std::string> &activity, + cta::common::dataStructures::Label::Format labelFormat) = 0; /** Destructor: releases the global lock if not already done */ virtual ~TapeMountDecisionInfo() {}; }; diff --git a/scheduler/SchedulerDatabaseTest.cpp b/scheduler/SchedulerDatabaseTest.cpp index a158dd94ff338b91a1c71a53a7689276e1875eba..68fba567e0056ced8a4c82a8708b72d2028245da 100644 --- a/scheduler/SchedulerDatabaseTest.cpp +++ b/scheduler/SchedulerDatabaseTest.cpp @@ -207,7 +207,7 @@ TEST_P(SchedulerDatabaseTest, createManyArchiveJobs) { cta::catalogue::TapeForWriting tfw; tfw.tapePool = "tapePool"; tfw.vid = "vid"; - auto am = moutInfo->createArchiveMount(common::dataStructures::MountType::ArchiveForUser, tfw, "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr)); + auto am = moutInfo->createArchiveMount(common::dataStructures::MountType::ArchiveForUser, tfw, "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr), std::nullopt, cta::common::dataStructures::Label::Format::CTA); bool done = false; size_t count = 0; while (!done) { @@ -286,12 +286,12 @@ TEST_P(SchedulerDatabaseTest, createManyArchiveJobs) { cta::catalogue::TapeForWriting tfw; tfw.tapePool = "tapePool"; tfw.vid = "vid"; - auto am = moutInfo->createArchiveMount(tfw, "drive", "library", "host","vo","mediaType", "vendor",123456789, time(nullptr)); + auto am = moutInfo->createArchiveMount(tfw, "drive", "library", "host","vo","mediaType", "vendor",123456789, time(nullptr), cta::common::dataStructures::Label::Format::CTA); auto done = false; auto count = 0; #else moutInfo = db.getMountInfo(lc); - am = moutInfo->createArchiveMount(common::dataStructures::MountType::ArchiveForUser, tfw, "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr)); + am = moutInfo->createArchiveMount(common::dataStructures::MountType::ArchiveForUser, tfw, "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr), std::nullopt, cta::common::dataStructures::Label::Format::CTA); done = false; count = 0; #endif @@ -368,7 +368,7 @@ TEST_P(SchedulerDatabaseTest, putExistingQueueToSleep) { // Create mount. auto moutInfo = db.getMountInfo(lc); - auto rm=moutInfo->createRetrieveMount("vid", "tapePool", "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr), std::nullopt); + auto rm=moutInfo->createRetrieveMount("vid", "tapePool", "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr), std::nullopt, cta::common::dataStructures::Label::Format::CTA); rm->putQueueToSleep(diskSystem.name, diskSystem.sleepTime, lc); @@ -402,7 +402,7 @@ TEST_P(SchedulerDatabaseTest, createQueueAndPutToSleep) { // Create mount. auto moutInfo = db.getMountInfo(lc); - auto rm=moutInfo->createRetrieveMount("vid", "tapePool", "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr), std::nullopt); + auto rm=moutInfo->createRetrieveMount("vid", "tapePool", "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr), std::nullopt, cta::common::dataStructures::Label::Format::CTA); rm->putQueueToSleep(diskSystem.name, diskSystem.sleepTime, lc); @@ -511,7 +511,7 @@ TEST_P(SchedulerDatabaseTest, popAndRequeueArchiveRequests) { cta::catalogue::TapeForWriting tfw; tfw.tapePool = "tapePool"; tfw.vid = "vid"; - auto am = moutInfo->createArchiveMount(common::dataStructures::MountType::ArchiveForUser, tfw, "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr)); + auto am = moutInfo->createArchiveMount(common::dataStructures::MountType::ArchiveForUser, tfw, "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr), std::nullopt, cta::common::dataStructures::Label::Format::CTA); auto ajb = am->getNextJobBatch(filesToDo, 1000 * filesToDo, lc); //Files with successful fetch should be popped ASSERT_EQ(10, ajb.size()); @@ -598,7 +598,7 @@ TEST_P(SchedulerDatabaseTest, popAndRequeueRetrieveRequests) { // Create mount. auto mountInfo = db.getMountInfo(lc); ASSERT_EQ(1, mountInfo->potentialMounts.size()); - auto rm=mountInfo->createRetrieveMount("vid", "tapePool", "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr), std::nullopt); + auto rm=mountInfo->createRetrieveMount("vid", "tapePool", "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr), std::nullopt, cta::common::dataStructures::Label::Format::CTA); { auto rjb = rm->getNextJobBatch(10,20*1000,lc); //Files with successful fetch should be popped @@ -689,7 +689,7 @@ TEST_P(SchedulerDatabaseTest, popRetrieveRequestsWithDisksytem) { // Create mount. auto moutInfo = db.getMountInfo(lc); ASSERT_EQ(1, moutInfo->potentialMounts.size()); - auto rm=moutInfo->createRetrieveMount("vid", "tapePool", "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr), std::nullopt); + auto rm=moutInfo->createRetrieveMount("vid", "tapePool", "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr), std::nullopt, cta::common::dataStructures::Label::Format::CTA); auto rjb = rm->getNextJobBatch(20,20*1000, lc); ASSERT_EQ(filesToDo, rjb.size()); @@ -783,7 +783,7 @@ TEST_P(SchedulerDatabaseTest, popRetrieveRequestsWithBackpressure) { // Create mount. auto moutInfo = db.getMountInfo(lc); ASSERT_EQ(1, moutInfo->potentialMounts.size()); - auto rm=moutInfo->createRetrieveMount("vid", "tapePool", "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr), std::nullopt); + auto rm=moutInfo->createRetrieveMount("vid", "tapePool", "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr), std::nullopt, cta::common::dataStructures::Label::Format::CTA); { //Batch fails and puts the queue to sleep (not enough space in disk system) //leave one job in the queue for the potential mount @@ -877,7 +877,7 @@ TEST_P(SchedulerDatabaseTest, popRetrieveRequestsWithDiskSystemNotFetcheable) { // Create mount. auto mountInfo = db.getMountInfo(lc); ASSERT_EQ(1, mountInfo->potentialMounts.size()); - auto rm=mountInfo->createRetrieveMount("vid", "tapePool", "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr), std::nullopt); + auto rm=mountInfo->createRetrieveMount("vid", "tapePool", "drive", "library", "host", "vo","mediaType", "vendor",123456789,time(nullptr), std::nullopt, cta::common::dataStructures::Label::Format::CTA); { //leave one job in the queue for the potential mount auto rjb = rm->getNextJobBatch(9,20*1000,lc); diff --git a/scheduler/TapeMount.hpp b/scheduler/TapeMount.hpp index 40c15f5038f80445890afd5232b8b17cf8d37f94..7464089ef2e33b12cd5373606071a925b8e52c7c 100644 --- a/scheduler/TapeMount.hpp +++ b/scheduler/TapeMount.hpp @@ -19,6 +19,8 @@ #include "common/dataStructures/MountType.hpp" #include "common/dataStructures/DriveStatus.hpp" + +#include "common/dataStructures/LabelFormat.hpp" #include "common/log/LogContext.hpp" #include "tapeserver/castor/tape/tapeserver/daemon/TapeSessionStats.hpp" @@ -75,6 +77,8 @@ namespace cta { virtual std::string getVendor() const = 0; + virtual cta::common::dataStructures::Label::Format getLabelFormat() const = 0; + /** * Returns the capacity in bytes of the tape * @return the capacity in bytes of the tape diff --git a/scheduler/TapeMountDummy.hpp b/scheduler/TapeMountDummy.hpp index 3074671cfb03eca3adbb25ef08dec102253d4a35..108294366e44798fea51489b3b94fabe26e966ab 100644 --- a/scheduler/TapeMountDummy.hpp +++ b/scheduler/TapeMountDummy.hpp @@ -56,6 +56,11 @@ class TapeMountDummy: public TapeMount { } void setDriveStatus(cta::common::dataStructures::DriveStatus status, const std::optional<std::string> & reason) override {} + + cta::common::dataStructures::Label::Format getLabelFormat() const override { + throw exception::Exception("In DummyTapeMount::getLabelFormat() : not implemented"); + } + void setTapeSessionStats(const castor::tape::tapeserver::daemon::TapeSessionStats &stats) override {}; void setTapeMounted(log::LogContext &logContext) const override {}; }; diff --git a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSession.cpp b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSession.cpp index f4a28c593050df891821e5af761468a1a5c850f7..5c9e9b878bc50281cd69659e3ae7c26fafa42249 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSession.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSession.cpp @@ -194,6 +194,7 @@ castor::tape::tapeserver::daemon::DataTransferSession::execute() { m_volInfo.mountType = tapeMount->getMountType(); m_volInfo.nbFiles = tapeMount->getNbFiles(); m_volInfo.mountId = tapeMount->getMountTransactionId(); + m_volInfo.labelFormat = tapeMount->getLabelFormat(); // 2c) ... and log. // Make the DGN and TPVID parameter permanent. cta::log::ScopedParamContainer params(lc); diff --git a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp index c7c594181efdca1e57bd091c25fc3ae798962dd0..37fde2af8fe4a69675ba991a344a9309c09c76d9 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp @@ -626,7 +626,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayRecall) { logToCheck += ""; ASSERT_NE(std::string::npos, logToCheck.find("MSG=\"Tape session started for read\" thread=\"TapeRead\" tapeDrive=\"T10D6116\" tapeVid=\"TstVid\" " "mountId=\"1\" vo=\"vo\" mediaType=\"LTO7M\" tapePool=\"TestTapePool\" " - "logicalLibrary=\"TestLogicalLibrary\" mountType=\"Retrieve\" vendor=\"TestVendor\" " + "logicalLibrary=\"TestLogicalLibrary\" mountType=\"Retrieve\" labelFormat=\"0000\" vendor=\"TestVendor\" " "capacityInBytes=\"12345678\"")); ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" serialNumber=\"123456\" " "mountTotalCorrectedReadErrors=\"5\" mountTotalReadBytesProcessed=\"4096\" " @@ -822,7 +822,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionWrongChecksumRecall) { logToCheck += ""; ASSERT_NE(std::string::npos,logToCheck.find("MSG=\"Tape session started for read\" thread=\"TapeRead\" tapeDrive=\"T10D6116\" tapeVid=\"TstVid\" " "mountId=\"1\" vo=\"vo\" mediaType=\"LTO7M\" tapePool=\"TestTapePool\" " - "logicalLibrary=\"TestLogicalLibrary\" mountType=\"Retrieve\" vendor=\"TestVendor\" " + "logicalLibrary=\"TestLogicalLibrary\" mountType=\"Retrieve\" labelFormat=\"0000\" vendor=\"TestVendor\" " "capacityInBytes=\"12345678\"")); ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" serialNumber=\"123456\" " "mountTotalCorrectedReadErrors=\"5\" mountTotalReadBytesProcessed=\"4096\" " diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.cpp b/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.cpp index 088232bb9169b3e117f9061cbe91faed72d451d9..e2663015fbb3ec2c31d739edfe6e8c5864b5cb3e 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.cpp @@ -239,12 +239,15 @@ void castor::tape::tapeserver::daemon::TapeReadSingleThread::run() { TapeCleaning tapeCleaner(*this, timer); // Before anything, the tape should be mounted m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Mounting, std::nullopt, m_logContext); + std::ostringstream ossLabelFormat; + ossLabelFormat << std::showbase << std::internal << std::setfill('0') << std::hex << std::setw(4) << static_cast<unsigned int>(m_volInfo.labelFormat); cta::log::ScopedParamContainer params(m_logContext); params.add("vo", m_retrieveMount.getVo()); params.add("mediaType", m_retrieveMount.getMediaType()); params.add("tapePool", m_retrieveMount.getPoolName()); params.add("logicalLibrary", m_drive.config.logicalLibrary); params.add("mountType", toCamelCaseString(m_volInfo.mountType)); + params.add("labelFormat", ossLabelFormat.str()); params.add("vendor", m_retrieveMount.getVendor()); params.add("capacityInBytes", m_retrieveMount.getCapacityInBytes()); m_logContext.log(cta::log::INFO, "Tape session started for read"); diff --git a/tapeserver/castor/tape/tapeserver/daemon/VolumeInfo.hpp b/tapeserver/castor/tape/tapeserver/daemon/VolumeInfo.hpp index c15a9c57a5985a679a68a786eef3139bbfa67fff..91a5ccf2d48398090d933a9e4810ebd938773d1f 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/VolumeInfo.hpp +++ b/tapeserver/castor/tape/tapeserver/daemon/VolumeInfo.hpp @@ -19,6 +19,7 @@ #include <string> #include <common/dataStructures/MountType.hpp> +#include "common/dataStructures/LabelFormat.hpp" namespace castor { namespace tape { @@ -33,6 +34,7 @@ struct VolumeInfo { cta::common::dataStructures::MountType mountType; //!< Mount type: archive or retrieve uint32_t nbFiles; //!< Number of files currently on tape std::string mountId; //!< Mount ID + cta::common::dataStructures::Label::Format labelFormat; //!< Label/Tape format }; } // namespace daemon