diff --git a/catalogue/Catalogue.hpp b/catalogue/Catalogue.hpp index 695eabebfe6c97884d521901eaa82f2ee46c7c1b..e3caf2ed1cfc999cfdf530ce55b08cdfd141006c 100644 --- a/catalogue/Catalogue.hpp +++ b/catalogue/Catalogue.hpp @@ -338,14 +338,6 @@ public: * @param vid The volume identifier of the tape to be reclaimed. */ virtual void reclaimTape(const common::dataStructures::SecurityIdentity &admin, const std::string &vid) = 0; - - /** - * This method should ONLY be used for TESTS. It does exactly the same as the real reclaimTape but it does not verify the - * SUPERSEDED_BY_VID and SUPERSEDED_BY_FSEQ attributes - * @param admin The administrator. - * @param vid The volume identifier of the tape to be reclaimed. - */ - virtual void fakeReclaimTapeForTests(const common::dataStructures::SecurityIdentity& admin, const std::string &vid) = 0; virtual void modifyTapeMediaType(const common::dataStructures::SecurityIdentity &admin, const std::string &vid, const std::string &mediaType) = 0; virtual void modifyTapeVendor(const common::dataStructures::SecurityIdentity &admin, const std::string &vid, const std::string &vendor) = 0; @@ -599,16 +591,6 @@ public: * @return True if the tape exists. */ virtual bool tapeExists(const std::string &vid) const = 0; - - /** - * Returns true if non superseded files exist after fSeq in the tape where vid is passed in parameter - * If there is only superseded files after fSeq, these tape files will be deleted - * - * @param vid the vid of the tape to check if non superseded files exist after fSeq - * @param fSeq the fSeq after which we want to check if non superseded files exist - * @return true if non superseded files exist, false otherwise - */ - virtual bool existNonSupersededFilesAfterFSeqAndDeleteTapeFilesForWriting(const std::string &vid, const uint64_t fSeq) const = 0; }; // class Catalogue diff --git a/catalogue/CatalogueRetryWrapper.hpp b/catalogue/CatalogueRetryWrapper.hpp index b9155d69c4b2ddb531286f31a60550cd144fb03b..65d98eaf85da745baeeed07f636dc4d6bd5f9943 100644 --- a/catalogue/CatalogueRetryWrapper.hpp +++ b/catalogue/CatalogueRetryWrapper.hpp @@ -232,10 +232,6 @@ public: void reclaimTape(const common::dataStructures::SecurityIdentity &admin, const std::string &vid) override { return retryOnLostConnection(m_log, [&]{return m_catalogue->reclaimTape(admin, vid);}, m_maxTriesToConnect); } - - void fakeReclaimTapeForTests(const common::dataStructures::SecurityIdentity &admin, const std::string &vid) override { - return retryOnLostConnection(m_log, [&]{return m_catalogue->fakeReclaimTapeForTests(admin, vid);}, m_maxTriesToConnect); - } void modifyTapeMediaType(const common::dataStructures::SecurityIdentity &admin, const std::string &vid, const std::string &mediaType) override { return retryOnLostConnection(m_log, [&]{return m_catalogue->modifyTapeMediaType(admin, vid, mediaType);}, m_maxTriesToConnect); @@ -388,11 +384,6 @@ public: bool tapeExists(const std::string &vid) const override { return retryOnLostConnection(m_log, [&]{return m_catalogue->tapeExists(vid);}, m_maxTriesToConnect); } - - bool existNonSupersededFilesAfterFSeqAndDeleteTapeFilesForWriting(const std::string& vid, const uint64_t fSeq) const override { - return retryOnLostConnection(m_log,[&]{return m_catalogue->existNonSupersededFilesAfterFSeqAndDeleteTapeFilesForWriting(vid,fSeq);},m_maxTriesToConnect); - } - protected: diff --git a/catalogue/CatalogueTest.cpp b/catalogue/CatalogueTest.cpp index 97000ca464a268a50cb3f91811cc32ff7de48fae..7e98967beab39de7ede5f95c38fcf0d5b27c7309 100644 --- a/catalogue/CatalogueTest.cpp +++ b/catalogue/CatalogueTest.cpp @@ -12151,122 +12151,6 @@ TEST_P(cta_catalogue_CatalogueTest, reclaimTape_full_lastFSeq_1_one_tape_file_su } } -TEST_P(cta_catalogue_CatalogueTest, exist_non_superseded_files_after_fseq) { - using namespace cta; - - const std::string diskInstanceName1 = "disk_instance_1"; - - ASSERT_TRUE(m_catalogue->getTapes().empty()); - - const std::string vid1 = "VID123"; - const std::string vid2 = "VID234"; - const std::string mediaType = "media_type"; - const std::string vendor = "vendor"; - const std::string logicalLibraryName = "logical_library_name"; - const bool logicalLibraryIsDisabled= false; - const std::string tapePoolName = "tape_pool_name"; - const std::string vo = "vo"; - const uint64_t nbPartialTapes = 2; - const bool isEncrypted = true; - const cta::optional<std::string> supply("value for the supply pool mechanism"); - const uint64_t capacityInBytes = (uint64_t)10 * 1000 * 1000 * 1000 * 1000; - const bool disabledValue = true; - const bool fullValue = false; - const std::string createTapeComment = "Create tape"; - - m_catalogue->createLogicalLibrary(m_admin, logicalLibraryName, logicalLibraryIsDisabled, "Create logical library"); - m_catalogue->createTapePool(m_admin, tapePoolName, vo, nbPartialTapes, isEncrypted, supply, "Create tape pool"); - m_catalogue->createTape(m_admin, vid1, mediaType, vendor, logicalLibraryName, tapePoolName, capacityInBytes, - disabledValue, fullValue, createTapeComment); - - //A tape with no tape file have no files after FSeq 0 - ASSERT_FALSE(m_catalogue->existNonSupersededFilesAfterFSeqAndDeleteTapeFilesForWriting(vid1,0)); - - const uint64_t archiveFileId = 1234; - - ASSERT_FALSE(m_catalogue->getArchiveFilesItor().hasMore()); - ASSERT_THROW(m_catalogue->getArchiveFileById(archiveFileId), exception::Exception); - - common::dataStructures::StorageClass storageClass; - storageClass.diskInstance = diskInstanceName1; - storageClass.name = "storage_class"; - storageClass.nbCopies = 1; - storageClass.comment = "Create storage class"; - m_catalogue->createStorageClass(m_admin, storageClass); - - /* - * Insert a file in the tape vid1 - */ - { - const uint64_t archiveFileSize = 1; - const std::string tapeDrive = "tape_drive"; - const std::string checksumType = "checksum_type"; - const std::string checksumValue = "checksum_value"; - - auto file1WrittenUP=cta::make_unique<cta::catalogue::TapeFileWritten>(); - auto & file1Written = *file1WrittenUP; - std::set<cta::catalogue::TapeItemWrittenPointer> file1WrittenSet; - file1WrittenSet.insert(file1WrittenUP.release()); - file1Written.archiveFileId = archiveFileId; - file1Written.diskInstance = storageClass.diskInstance; - file1Written.diskFileId = "5678"; - file1Written.diskFilePath = "/public_dir/public_file"; - file1Written.diskFileUser = "public_disk_user"; - file1Written.diskFileGroup = "public_disk_group"; - file1Written.size = archiveFileSize; - file1Written.checksumType = checksumType; - file1Written.checksumValue = checksumValue; - file1Written.storageClassName = storageClass.name; - file1Written.vid = vid1; - file1Written.fSeq = 1; - file1Written.blockId = 4321; - file1Written.compressedSize = 1; - file1Written.copyNb = 1; - file1Written.tapeDrive = tapeDrive; - m_catalogue->filesWrittenToTape(file1WrittenSet); - } - //One file written : this file is not superseded by another one, existNonSupersededFilesAfterFSeq = true - ASSERT_TRUE(m_catalogue->existNonSupersededFilesAfterFSeqAndDeleteTapeFilesForWriting(vid1,0)); - //No file after the only file inserted, existNonSupersededFilesAfterFseq = false - ASSERT_FALSE(m_catalogue->existNonSupersededFilesAfterFSeqAndDeleteTapeFilesForWriting(vid1,1)); - - //Insert another file in another tape that will supersed the first one in vid1 - { - m_catalogue->createTape(m_admin, vid2, mediaType, vendor, logicalLibraryName, tapePoolName, capacityInBytes, - disabledValue, fullValue, createTapeComment); - const uint64_t archiveFileSize = 1; - const std::string tapeDrive = "tape_drive"; - const std::string checksumType = "checksum_type"; - const std::string checksumValue = "checksum_value"; - - auto file1WrittenUP=cta::make_unique<cta::catalogue::TapeFileWritten>(); - auto & file1Written = *file1WrittenUP; - std::set<cta::catalogue::TapeItemWrittenPointer> file1WrittenSet; - file1WrittenSet.insert(file1WrittenUP.release()); - file1Written.archiveFileId = archiveFileId; - file1Written.diskInstance = storageClass.diskInstance; - file1Written.diskFileId = "5678"; - file1Written.diskFilePath = "/public_dir/public_file"; - file1Written.diskFileUser = "public_disk_user"; - file1Written.diskFileGroup = "public_disk_group"; - file1Written.size = archiveFileSize; - file1Written.checksumType = checksumType; - file1Written.checksumValue = checksumValue; - file1Written.storageClassName = storageClass.name; - file1Written.vid = vid2; - file1Written.fSeq = 1; - file1Written.blockId = 4321; - file1Written.compressedSize = 1; - file1Written.copyNb = 1; - file1Written.tapeDrive = tapeDrive; - m_catalogue->filesWrittenToTape(file1WrittenSet); - } - //The tape files written to tape vid2 are not superseded by any file, but the tape files in vid1 - //are superseded by the tape files in vid2 - ASSERT_FALSE(m_catalogue->existNonSupersededFilesAfterFSeqAndDeleteTapeFilesForWriting(vid1,0)); - ASSERT_TRUE(m_catalogue->existNonSupersededFilesAfterFSeqAndDeleteTapeFilesForWriting(vid2,0)); -} - TEST_P(cta_catalogue_CatalogueTest, ping) { using namespace cta; diff --git a/catalogue/DummyCatalogue.hpp b/catalogue/DummyCatalogue.hpp index a67b479e1710340e5726459b69beefbe4aebda3f..5e83c60901025a45c9803006f015e233617a0311 100644 --- a/catalogue/DummyCatalogue.hpp +++ b/catalogue/DummyCatalogue.hpp @@ -107,7 +107,6 @@ public: const std::string &storageClassName, const common::dataStructures::UserIdentity &user) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } common::dataStructures::RetrieveFileQueueCriteria prepareToRetrieveFile(const std::string& instanceName, const uint64_t archiveFileId, const common::dataStructures::UserIdentity& user, log::LogContext &lc) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } void reclaimTape(const common::dataStructures::SecurityIdentity& admin, const std::string& vid) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } - void fakeReclaimTapeForTests(const common::dataStructures::SecurityIdentity& admin, const std::string& vid) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } void setTapeDisabled(const common::dataStructures::SecurityIdentity& admin, const std::string& vid, const bool disabledValue) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } void setTapeFull(const common::dataStructures::SecurityIdentity& admin, const std::string& vid, const bool fullValue) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } void setTapePoolEncryption(const common::dataStructures::SecurityIdentity& admin, const std::string& name, const bool encryptionValue) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } @@ -116,7 +115,6 @@ public: void tapeMountedForArchive(const std::string& vid, const std::string& drive) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } void tapeMountedForRetrieve(const std::string& vid, const std::string& drive) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } bool tapePoolExists(const std::string& tapePoolName) const { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } - bool existNonSupersededFilesAfterFSeqAndDeleteTapeFilesForWriting(const std::string& vid, const uint64_t fSeq) const { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } // Special functions for unit tests. void addEnabledTape(const std::string & vid) { diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp index 4ad7b64be62195aac45f256293e23f88be420e48..fc5424be8cfd910d457a65f3fc8d045932936a58 100644 --- a/catalogue/RdbmsCatalogue.cpp +++ b/catalogue/RdbmsCatalogue.cpp @@ -1891,47 +1891,6 @@ bool RdbmsCatalogue::tapeExists(rdbms::Conn &conn, const std::string &vid) const } } -bool RdbmsCatalogue::existNonSupersededFilesAfterFSeqAndDeleteTapeFilesForWriting(const std::string& vid, const uint64_t fSeq) const { - try{ - auto conn = m_connPool.getConn(); - const char *const sql = - "SELECT VID " - "FROM TAPE_FILE " - "WHERE " - "VID = :VID AND " - "FSEQ > :FSEQ AND " - "SUPERSEDED_BY_VID IS NULL AND " - "SUPERSEDED_BY_FSEQ IS NULL"; - auto stmt = conn.createStmt(sql); - stmt.bindString(":VID",vid); - stmt.bindUint64(":FSEQ",fSeq); - auto rset = stmt.executeQuery(); - if(!rset.next()){ - //No non-superseded files detected, we can delete the tape files - const char *const sqlDelete = - "DELETE FROM TAPE_FILE " - "WHERE " - "VID =:VID AND " - "FSEQ > :FSEQ AND " - "SUPERSEDED_BY_VID IS NOT NULL AND " - "SUPERSEDED_BY_FSEQ IS NOT NULL"; - auto stmtDelete = conn.createStmt(sqlDelete); - stmtDelete.bindString(":VID",vid); - stmtDelete.bindUint64(":FSEQ",fSeq); - stmtDelete.executeNonQuery(); - return false; - } - //Non superseded files are present - return true; - } catch(exception::UserError &) { - throw; - } catch(exception::Exception &ex) { - ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str()); - throw; - } -} - - //------------------------------------------------------------------------------ // deleteTape //------------------------------------------------------------------------------ @@ -2346,73 +2305,47 @@ common::dataStructures::VidToTapeMap RdbmsCatalogue::getAllTapes() const { } //------------------------------------------------------------------------------ -// reclaimTape +//getNbNonSupersededFilesOnTape //------------------------------------------------------------------------------ -void RdbmsCatalogue::reclaimTape(const common::dataStructures::SecurityIdentity &admin, const std::string &vid) { +uint64_t RdbmsCatalogue::getNbNonSupersededFilesOnTape(rdbms::Conn& conn, const std::string& vid) const { try { - const time_t now = time(nullptr); - const char *const sql = - "UPDATE TAPE SET " - "DATA_IN_BYTES = 0," - "LAST_FSEQ = 0," - "IS_FULL = '0'," - "LAST_UPDATE_USER_NAME = :LAST_UPDATE_USER_NAME," - "LAST_UPDATE_HOST_NAME = :LAST_UPDATE_HOST_NAME," - "LAST_UPDATE_TIME = :LAST_UPDATE_TIME " - "WHERE " - "VID = :UPDATE_VID AND " - "IS_FULL != '0' AND " - "NOT EXISTS (SELECT VID FROM TAPE_FILE WHERE VID = :SELECT_VID " - " AND SUPERSEDED_BY_VID IS NULL " - " AND SUPERSEDED_BY_FSEQ IS NULL)"; - auto conn = m_connPool.getConn(); + const char *const sql = + "SELECT COUNT(*) AS NB_NON_SUPERSEDED_FILES FROM TAPE_FILE " + "WHERE VID = :VID " + "AND SUPERSEDED_BY_VID IS NULL " + "AND SUPERSEDED_BY_FSEQ IS NULL"; auto stmt = conn.createStmt(sql); - stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt.bindUint64(":LAST_UPDATE_TIME", now); - stmt.bindString(":UPDATE_VID", vid); - stmt.bindString(":SELECT_VID", vid); - stmt.executeNonQuery(); - - // If the update failed due to a user error - if(0 == stmt.getNbAffectedRows()) { - // Try to determine the user error - // - // Please note that this is a best effort diagnosis because there is no - // lock on the database to prevent other concurrent updates from taking - // place on the TAPE and TAPE_FILE tables - TapeSearchCriteria searchCriteria; - searchCriteria.vid = vid; - const auto tapes = getTapes(conn, searchCriteria); - - if(tapes.empty()) { - throw exception::UserError(std::string("Cannot reclaim tape ") + vid + " because it does not exist"); - } else { - if(!tapes.front().full) { - throw exception::UserError(std::string("Cannot reclaim tape ") + vid + " because it is not FULL"); - } else { - throw exception::UserError(std::string("Cannot reclaim tape ") + vid + " because there is at least one tape" - " file in the catalogue that is on the tape"); - } - } - } - } catch(exception::UserError &) { - throw; + stmt.bindString(":VID", vid); + auto rset = stmt.executeQuery(); + rset.next(); + return rset.columnUint64("NB_NON_SUPERSEDED_FILES"); } catch(exception::Exception &ex) { ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str()); throw; } } -//------------------------------------------------------------------------------ -//fakeReclaimTapeForTests -//------------------------------------------------------------------------------ -void RdbmsCatalogue::fakeReclaimTapeForTests(const common::dataStructures::SecurityIdentity& admin, const std::string& vid) { +void RdbmsCatalogue::deleteTapeFiles(rdbms::Conn& conn, const std::string& vid) const { + try { + const char * const sql = + "DELETE FROM TAPE_FILE WHERE VID = :VID " + "AND SUPERSEDED_BY_VID IS NOT NULL " + "AND SUPERSEDED_BY_FSEQ IS NOT NULL"; + auto stmt = conn.createStmt(sql); + stmt.bindString(":VID", vid); + stmt.executeNonQuery(); + } catch(exception::Exception &ex) { + ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str()); + throw; + } +} + +void RdbmsCatalogue::resetTapeCounters(rdbms::Conn& conn, const common::dataStructures::SecurityIdentity& admin, const std::string& vid) const { try { const time_t now = time(nullptr); - const char *const sql = - "UPDATE TAPE SET " + const char * const sql = + "UPDATE TAPE SET " "DATA_IN_BYTES = 0," "LAST_FSEQ = 0," "IS_FULL = '0'," @@ -2420,47 +2353,55 @@ void RdbmsCatalogue::fakeReclaimTapeForTests(const common::dataStructures::Secur "LAST_UPDATE_HOST_NAME = :LAST_UPDATE_HOST_NAME," "LAST_UPDATE_TIME = :LAST_UPDATE_TIME " "WHERE " - "VID = :UPDATE_VID AND " - "IS_FULL != '0'"; - auto conn = m_connPool.getConn(); + "VID = :VID"; auto stmt = conn.createStmt(sql); stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); stmt.bindUint64(":LAST_UPDATE_TIME", now); - stmt.bindString(":UPDATE_VID", vid); + stmt.bindString(":VID", vid); stmt.executeNonQuery(); + } catch (exception::Exception &ex){ + ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str()); + throw; + } +} - // If the update failed due to a user error - if(0 == stmt.getNbAffectedRows()) { - // Try to determine the user error - // - // Please note that this is a best effort diagnosis because there is no - // lock on the database to prevent other concurrent updates from taking - // place on the TAPE and TAPE_FILE tables - TapeSearchCriteria searchCriteria; - searchCriteria.vid = vid; - const auto tapes = getTapes(conn, searchCriteria); - - if(tapes.empty()) { - throw exception::UserError(std::string("Cannot reclaim tape ") + vid + " because it does not exist"); - } else { - if(!tapes.front().full) { - throw exception::UserError(std::string("Cannot reclaim tape ") + vid + " because it is not FULL"); - } else { - throw exception::UserError(std::string("Cannot reclaim tape ") + vid + " because there is at least one tape" +//------------------------------------------------------------------------------ +// reclaimTape +//------------------------------------------------------------------------------ +void RdbmsCatalogue::reclaimTape(const common::dataStructures::SecurityIdentity &admin, const std::string &vid) { + try{ + auto conn = m_connPool.getConn(); + + TapeSearchCriteria searchCriteria; + searchCriteria.vid = vid; + const auto tapes = getTapes(conn, searchCriteria); + + if(tapes.empty()) { + throw exception::UserError(std::string("Cannot reclaim tape ") + vid + " because it does not exist"); + } else { + if(!tapes.front().full){ + throw exception::UserError(std::string("Cannot reclaim tape ") + vid + " because it is not FULL"); + } + } + //The tape exists and is full, we can try to reclaim it + if(getNbNonSupersededFilesOnTape(conn,vid) == 0){ + //There is no non-superseded files on the tape, we can reclaim it : delete the files and reset the counters + deleteTapeFiles(conn,vid); + resetTapeCounters(conn,admin,vid); + } else { + throw exception::UserError(std::string("Cannot reclaim tape ") + vid + " because there is at least one tape" " file in the catalogue that is on the tape"); - } - } } - } catch(exception::UserError &) { + } catch (exception::UserError& ue) { throw; - } catch(exception::Exception &ex) { + } + catch (exception::Exception &ex) { ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str()); throw; } } - //------------------------------------------------------------------------------ // getTapeLogFromRset //------------------------------------------------------------------------------ diff --git a/catalogue/RdbmsCatalogue.hpp b/catalogue/RdbmsCatalogue.hpp index 766dca01f7390bd4176adcd2e7535998b8a3431b..584074885cb595fa34ef76c0b16ac1de35f02e9a 100644 --- a/catalogue/RdbmsCatalogue.hpp +++ b/catalogue/RdbmsCatalogue.hpp @@ -332,7 +332,27 @@ public: * @param vid The volume identifier of the tape to be reclaimed. */ void reclaimTape(const common::dataStructures::SecurityIdentity &admin, const std::string &vid) override; - void fakeReclaimTapeForTests(const common::dataStructures::SecurityIdentity& admin, const std::string& vid) override; + /** + * Returns the number of non superseded files contained in the tape identified by its vid + * @param conn the database connection + * @param vid the vid in which we will count non superseded files + * @return the number of non superseded files on the vid + */ + uint64_t getNbNonSupersededFilesOnTape(rdbms::Conn &conn, const std::string &vid) const; + /** + * Delete all the tape files of the VID passed in parameter + * @param conn the database connection + * @param vid the vid in which we want to remove all the tape files + */ + void deleteTapeFiles(rdbms::Conn &conn, const std::string& vid) const; + + /** + * Reset the counters of a tape + * @param conn the database connection + * @param admin the administrator + * @param vid the vid to reset the counters + */ + void resetTapeCounters(rdbms::Conn &conn, const common::dataStructures::SecurityIdentity &admin ,const std::string& vid) const; void modifyTapeMediaType(const common::dataStructures::SecurityIdentity &admin, const std::string &vid, const std::string &mediaType) override; void modifyTapeVendor(const common::dataStructures::SecurityIdentity &admin, const std::string &vid, const std::string &vendor) override; void modifyTapeLogicalLibraryName(const common::dataStructures::SecurityIdentity &admin, const std::string &vid, const std::string &logicalLibraryName) override; @@ -715,17 +735,6 @@ protected: * @return True if the tape exists. */ bool tapeExists(rdbms::Conn &conn, const std::string &vid) const; - - /** - * Returns true if non superseded files exist after fSeq in the tape where vid is passed in parameter - * If there is only superseded files after fSeq, these tape files will be deleted - * - * @param vid the vid of the tape to check if non superseded files exist after fSeq - * @param fSeq the fSeq after which we want to check if non superseded files exist - * @return true if non superseded files exist, false otherwise - */ - bool existNonSupersededFilesAfterFSeqAndDeleteTapeFilesForWriting(const std::string& vid, const uint64_t fSeq) const override; - /** * Returns the list of tapes that meet the specified search criteria. @@ -735,7 +744,7 @@ protected: * @return The list of tapes. */ std::list<common::dataStructures::Tape> getTapes(rdbms::Conn &conn, const TapeSearchCriteria &searchCriteria) const; - + /** * Returns true if the specified logical library exists. * diff --git a/scheduler/ArchiveMount.cpp b/scheduler/ArchiveMount.cpp index 0cb2df62a402ab24b70cb7cce06e6b23592e2fe1..818f703a145990c1c236c4ac53275f12d361a07c 100644 --- a/scheduler/ArchiveMount.cpp +++ b/scheduler/ArchiveMount.cpp @@ -104,16 +104,6 @@ uint32_t cta::ArchiveMount::getNbFiles() const { return m_dbMount->nbFilesCurrentlyOnTape; } -//------------------------------------------------------------------------------ -// checkTapeFSeqForWriting -//------------------------------------------------------------------------------ -void cta::ArchiveMount::checkTapeFSeqAndDeleteTapeFilesForWriting(uint64_t fSeq) const { - if(m_catalogue.existNonSupersededFilesAfterFSeqAndDeleteTapeFilesForWriting(getVid(),fSeq)){ - throw cta::exception::Exception("Non superseded files have been detected in the tape "+getVid() +" after "+std::to_string(fSeq)); - } -} - - //------------------------------------------------------------------------------ // createDiskReporter //------------------------------------------------------------------------------ diff --git a/scheduler/ArchiveMount.hpp b/scheduler/ArchiveMount.hpp index 509895d54031396f1e61b93a7b3cfb8759ca3831..2073545e4d03613f27ddaf10fb90cf96f5407a18 100644 --- a/scheduler/ArchiveMount.hpp +++ b/scheduler/ArchiveMount.hpp @@ -172,14 +172,6 @@ namespace cta { */ uint32_t getNbFiles() const override; - /** - * Checks wether the writing is possible after the FSeq passed in parameter - * If TapeFiles are located after FSeq and are not superseded by other TapeFiles - * we throw an exception : We don't want these files to be lost. - * @param fSeq : The fSeq after which we want to check if the writing is possible - */ - void checkTapeFSeqAndDeleteTapeFilesForWriting(uint64_t fSeq) const; - /** * Creates a disk reporter for the ArchiveJob (this is a wrapper). * @param URL: report address diff --git a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp index 4bd976026c1b9892e871d48d0d9544448af9392c..1326e57d1c8e7d1db82ea51c1747c0ea4fb2dc11 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp @@ -1858,166 +1858,6 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullOnFlushMigration) { "mountTotalReadRetries=\"25\" mountTotalWriteRetries=\"25\" mountWriteTransients=\"10\"")); } -TEST_P(DataTransferSessionTest, WriteDataInTapeWithNonSupersededFilesOnIt) { - // 0) Prepare the logger for everyone - cta::log::StringLogger logger("dummy","tapeServerUnitTest",cta::log::DEBUG); - cta::log::LogContext logContext(logger); - - setupDefaultCatalogue(); - // 1) prepare the fake scheduler - std::string vid = s_vid; - std::string vid2 = s_vid+"2"; - // cta::MountType::Enum mountType = cta::MountType::RETRIEVE; - - // 3) Prepare the necessary environment (logger, plus system wrapper), - castor::tape::System::mockWrapper mockSys; - mockSys.delegateToFake(); - mockSys.disableGMockCallsCounting(); - mockSys.fake.setupForVirtualDriveSLC6(); - - // 4) Create the scheduler - auto & catalogue = getCatalogue(); - auto & scheduler = getScheduler(); - - // Always use the same requester - const cta::common::dataStructures::SecurityIdentity requester("user", "group"); - - // List to remember the path of each remote file so that the existance of the - // files can be tested for at the end of the test - std::list<std::string> remoteFilePaths; - - // 5) Create the environment for the migration to happen (library + tape) - const std::string libraryComment = "Library comment"; - const bool libraryIsDisabled = false; - catalogue.createLogicalLibrary(s_adminOnAdminHost, s_libraryName, - libraryIsDisabled, libraryComment); - { - auto libraries = catalogue.getLogicalLibraries(); - ASSERT_EQ(1, libraries.size()); - ASSERT_EQ(s_libraryName, libraries.front().name); - ASSERT_EQ(libraryComment, libraries.front().comment); - } - const uint64_t capacityInBytes = 12345678; - const std::string tapeComment = "Tape comment"; - bool disabled = false; - bool full = false; - catalogue.createTape(s_adminOnAdminHost, s_vid, s_mediaType, s_vendor, s_libraryName, s_tapePoolName, capacityInBytes, - disabled, full, tapeComment); - catalogue.createTape(s_adminOnAdminHost, vid2, s_mediaType, s_vendor, s_libraryName, s_tapePoolName, capacityInBytes, - disabled, full, tapeComment); - - // Create the mount criteria - catalogue.createMountPolicy(requester, "immediateMount", 1000, 0, 1000, 0, 1, "Policy comment"); - catalogue.createRequesterMountRule(requester, "immediateMount", s_diskInstance, requester.username, "Rule comment"); - - //delete is unnecessary - //pointer with ownership will be passed to the application, - //which will do the delete - mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive(); - - // We can prepare files for writing on the drive. - // Tempfiles are in this scope so they are kept alive - std::vector<std::unique_ptr<unitTests::TempFile>> sourceFiles; - std::list<uint64_t> archiveFileIds; - { - // Label the tape - castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"], s_vid, false); - catalogue.tapeLabelled(s_vid, "T10D6116"); - mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind(); - - // Create the files and schedule the archivals - for(int fseq=1; fseq <= 10 ; fseq ++) { - // Create a source file. - sourceFiles.emplace_back(cta::make_unique<unitTests::TempFile>()); - sourceFiles.back()->randomFill(1000); - remoteFilePaths.push_back(sourceFiles.back()->path()); - // Schedule the archival of the file - cta::common::dataStructures::ArchiveRequest ar; - ar.checksumType="ADLER32"; - ar.checksumValue=sourceFiles.back()->adler32(); - ar.storageClass=s_storageClassName; - ar.srcURL=std::string("file://") + sourceFiles.back()->path(); - ar.requester.name = requester.username; - ar.requester.group = "group"; - ar.fileSize = 1000; - ar.diskFileID = std::to_string(fseq); - ar.diskFileInfo.path = "y"; - ar.diskFileInfo.owner = "z"; - ar.diskFileInfo.group = "g"; - const auto archiveFileId = scheduler.checkAndGetNextArchiveFileId(s_diskInstance, ar.storageClass, ar.requester, logContext); - archiveFileIds.push_back(archiveFileId); - scheduler.queueArchiveWithGivenId(archiveFileId,s_diskInstance,ar,logContext); - } - } - scheduler.waitSchedulerDbSubthreadsComplete(); - // Report the drive's existence and put it up in the drive register. - cta::tape::daemon::TpconfigLine driveConfig("T10D6116", "TestLogicalLibrary", "/dev/tape_T10D6116", "manual"); - cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=driveConfig.unitName; - driveInfo.logicalLibrary=driveConfig.logicalLibrary; - driveInfo.host="host"; - // We need to create the drive in the registry before being able to put it up. - scheduler.reportDriveStatus(driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, logContext); - scheduler.setDesiredDriveState(s_adminOnAdminHost, driveConfig.unitName, true, false, logContext); - - // Create the data transfer session - DataTransferConfig castorConf; - castorConf.bufsz = 1024*1024; // 1 MB memory buffers - castorConf.nbBufs = 10; - castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000; - castorConf.bulkRequestRecallMaxFiles = 1000; - castorConf.bulkRequestMigrationMaxBytes = UINT64_C(100)*1000*1000*1000; - castorConf.bulkRequestMigrationMaxFiles = 1000; - castorConf.nbDiskThreads = 1; - cta::log::DummyLogger dummyLog("dummy", "dummy"); - cta::mediachanger::MediaChangerFacade mc(dummyLog); - cta::server::ProcessCap capUtils; - castor::messages::TapeserverProxyDummy initialProcess; - DataTransferSession sess("tapeHost", logger, mockSys, driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); - sess.execute(); - - catalogue.setTapeFull(requester,vid,true); - //Fake reclaim the tape to reset tape's counters - catalogue.fakeReclaimTapeForTests(requester,vid); - - //Try to write files on tape vid = TstVid - // Create the files and schedule the archivals - { - for(int fseq=1; fseq <= 10 ; fseq ++) { - // Create a source file. - sourceFiles.emplace_back(cta::make_unique<unitTests::TempFile>()); - sourceFiles.back()->randomFill(1000); - remoteFilePaths.push_back(sourceFiles.back()->path()); - // Schedule the archival of the file - cta::common::dataStructures::ArchiveRequest ar; - ar.checksumType="ADLER32"; - ar.checksumValue=sourceFiles.back()->adler32(); - ar.storageClass=s_storageClassName; - ar.srcURL=std::string("file://") + sourceFiles.back()->path(); - ar.requester.name = requester.username; - ar.requester.group = "group"; - ar.fileSize = 1000; - ar.diskFileID = std::to_string(fseq); - ar.diskFileInfo.path = "y"; - ar.diskFileInfo.owner = "z"; - ar.diskFileInfo.group = "g"; - const auto archiveFileId = scheduler.checkAndGetNextArchiveFileId(s_diskInstance, ar.storageClass, ar.requester, logContext); - archiveFileIds.push_back(archiveFileId); - scheduler.queueArchiveWithGivenId(archiveFileId,s_diskInstance,ar,logContext); - } - } - scheduler.waitSchedulerDbSubthreadsComplete(); - { - DataTransferSession sess("tapeHost2", logger, mockSys, driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); - sess.execute(); - } - //The session should fail because of the checking of writing in a tape with files that are not superseded - std::string logToCheck = logger.getLog(); - ASSERT_NE(std::string::npos, logToCheck.find("MSG=\"In MigrationReportPacker::reportEndOfSessionWithErrors(), " - "pushing a report.\" thread=\"TapeWrite\" tapeDrive=\"T10D6116\" tapeVid=\"TstVid\" mountId=\"2\" " - "ErrorMesage=\"Non superseded files have been detected in the tape TstVid after 0\" type=\"ReportEndofSessionWithErrors\"")); -} - #undef TEST_MOCK_DB #ifdef TEST_MOCK_DB static cta::MockSchedulerDatabaseFactory mockDbFactory; diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp b/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp index 3258b2458a4c8f9617bf1e2248af65c3299b82d8..f209e4f0df2568daab19f7731b35653012fc47da 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp @@ -319,8 +319,6 @@ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::run() { params.add("capacityInBytes",m_archiveMount.getCapacityInBytes()); m_logContext.log(cta::log::INFO, "Tape session started"); mountTapeReadWrite(); - currentErrorToCount = "Error_tapeFSeqCheckAndTapeFileCleanup"; - m_archiveMount.checkTapeFSeqAndDeleteTapeFilesForWriting(m_lastFseq); currentErrorToCount = "Error_tapeLoad"; waitForDrive(); currentErrorToCount = "Error_checkingTapeAlert";