diff --git a/scheduler/Scheduler.cpp b/scheduler/Scheduler.cpp index 78649a9342f9f39f38656e693a5b2307f907b5f4..95555ea3cae19384196424eaa3efe30c7fc28494 100644 --- a/scheduler/Scheduler.cpp +++ b/scheduler/Scheduler.cpp @@ -316,15 +316,20 @@ void Scheduler::queueLabel(const common::dataStructures::SecurityIdentity &cliId throw exception::Exception(std::string("Not implemented: ") + __PRETTY_FUNCTION__); } -void Scheduler::checkTapeFullBeforeRepack(std::string vid){ - std::set<std::string> vidToRepack; - vidToRepack.insert(vid); +void Scheduler::checkTapeCanBeRepacked(const std::string & vid, const SchedulerDatabase::QueueRepackRequest & repackRequest){ + std::set<std::string> vidToRepack({vid}); try{ auto vidToTapesMap = m_catalogue.getTapesByVid(vidToRepack); //throws an exception if the vid is not found on the database cta::common::dataStructures::Tape tapeToCheck = vidToTapesMap.at(vid); if(!tapeToCheck.full){ throw exception::UserError("You must set the tape as full before repacking it."); } + if(tapeToCheck.state == common::dataStructures::Tape::BROKEN){ + throw exception::UserError(std::string("You cannot repack a tape that is ") + common::dataStructures::Tape::stateToString(common::dataStructures::Tape::BROKEN) + "."); + } + if(tapeToCheck.isDisabled() && !repackRequest.m_forceDisabledTape){ + throw exception::UserError(std::string("You cannot repack a ") + common::dataStructures::Tape::stateToString(common::dataStructures::Tape::DISABLED)+ " tape. You can force it by using the flag --disabledtape."); + } } catch(const exception::UserError& userEx){ throw userEx; } catch(const cta::exception::Exception & ex){ @@ -344,7 +349,7 @@ void Scheduler::queueRepack(const common::dataStructures::SecurityIdentity &cliI if (vid.empty()) throw exception::UserError("Empty VID name."); if (repackBufferURL.empty()) throw exception::UserError("Empty buffer URL."); utils::Timer t; - checkTapeFullBeforeRepack(vid); + checkTapeCanBeRepacked(vid,repackRequestToQueue); std::string repackRequestAddress = m_db.queueRepack(repackRequestToQueue, lc); log::TimingList tl; tl.insertAndReset("schedulerDbTime", t); diff --git a/scheduler/Scheduler.hpp b/scheduler/Scheduler.hpp index abe9c70f3d3faa3fbb2e1d7a0615b25e7caec21d..c02a31afff62268830e2d1a708e0f0aa6f2f1b9f 100644 --- a/scheduler/Scheduler.hpp +++ b/scheduler/Scheduler.hpp @@ -300,12 +300,13 @@ private: double & getTapeInfoTime, double & candidateSortingTime, double & getTapeForWriteTime, log::LogContext & lc); /** - * Checks wether the tape is full before repacking + * Checks wether the tape can be repacked of not. + * A tape can be repacked if it exists, it is full, not BROKEN and not DISABLED unless there the --disabledtape flag has been provided by the user. * @param vid the vid of the tape to check - * @throws a UserError exception if the vid does not exist or if - * the tape is not full + * @param repackRequest the associated repackRequest to check the tape can be repacked + * @throws a UserError exception if the tape cannot be repacked */ - void checkTapeFullBeforeRepack(std::string vid); + void checkTapeCanBeRepacked(const std::string & vid, const SchedulerDatabase::QueueRepackRequest & repackRequest); cta::optional<common::dataStructures::LogicalLibrary> getLogicalLibrary(const std::string &libraryName, double &getLogicalLibraryTime); diff --git a/scheduler/SchedulerTest.cpp b/scheduler/SchedulerTest.cpp index aef1a0cc7656ecf523cea68128046e9010f29ced..a9813a819429a74e1d6020027317a7c238f46b2f 100644 --- a/scheduler/SchedulerTest.cpp +++ b/scheduler/SchedulerTest.cpp @@ -2642,9 +2642,10 @@ TEST_P(SchedulerTest, expandRepackRequestDisabledTape) { //one retrieve request scheduler.waitSchedulerDbSubthreadsComplete(); { + bool forceDisableTape = false; cta::SchedulerDatabase::QueueRepackRequest qrr(vid,"file://"+tempDirectory.path(),common::dataStructures::RepackInfo::Type::MoveOnly, - common::dataStructures::MountPolicy::s_defaultMountPolicyForRepack,s_defaultRepackDisabledTapeFlag,s_defaultRepackNoRecall); - scheduler.queueRepack(admin,qrr,lc); + common::dataStructures::MountPolicy::s_defaultMountPolicyForRepack,forceDisableTape,s_defaultRepackNoRecall); + ASSERT_THROW(scheduler.queueRepack(admin,qrr,lc),cta::exception::UserError); scheduler.waitSchedulerDbSubthreadsComplete(); log::TimingList tl; @@ -2654,31 +2655,87 @@ TEST_P(SchedulerTest, expandRepackRequestDisabledTape) { scheduler.waitSchedulerDbSubthreadsComplete(); auto repackRequestToExpand = scheduler.getNextRepackRequestToExpand(); - scheduler.expandRepackRequest(repackRequestToExpand,tl,t,lc); - scheduler.waitSchedulerDbSubthreadsComplete(); - - ASSERT_EQ(vid,repackRequestToExpand->getRepackInfo().vid); - repackRequestToExpand = scheduler.getNextRepackRequestToExpand(); ASSERT_EQ(nullptr,repackRequestToExpand); } + //Queue the repack request with the force disabled tape flag { - //Check that no mount exist because the tape is disabled - std::unique_ptr<cta::TapeMount> mount; - mount.reset(scheduler.getNextMount(s_libraryName, "drive0", lc).release()); - ASSERT_EQ(nullptr, mount.get()); - - //Check that the repack request is failed with 10 failed to retrieve and 0 failed archive files (as they have not been created, these archive jobs are not failed) - objectstore::RootEntry re(schedulerDB.getBackend()); - re.fetchNoLock(); - objectstore::RepackIndex ri(re.getRepackIndexAddress(), schedulerDB.getBackend()); - ri.fetchNoLock(); - - objectstore::RepackRequest rr(ri.getRepackRequestAddress(vid),schedulerDB.getBackend()); - rr.fetchNoLock(); - - ASSERT_EQ(10,rr.getStats().at(objectstore::RepackRequest::StatsType::RetrieveFailure).files); - ASSERT_EQ(0,rr.getStats().at(objectstore::RepackRequest::StatsType::ArchiveFailure).files); - ASSERT_EQ(common::dataStructures::RepackInfo::Status::Failed,rr.getInfo().status); + bool forceDisableTape = true; + cta::SchedulerDatabase::QueueRepackRequest qrr(vid,"file://"+tempDirectory.path(),common::dataStructures::RepackInfo::Type::MoveOnly, + common::dataStructures::MountPolicy::s_defaultMountPolicyForRepack,forceDisableTape,s_defaultRepackNoRecall); + ASSERT_NO_THROW(scheduler.queueRepack(admin,qrr,lc)); + scheduler.waitSchedulerDbSubthreadsComplete(); + + log::TimingList tl; + utils::Timer t; + + scheduler.promoteRepackRequestsToToExpand(lc); + scheduler.waitSchedulerDbSubthreadsComplete(); + + auto repackRequestToExpand = scheduler.getNextRepackRequestToExpand(); + ASSERT_NE(nullptr,repackRequestToExpand); + } +} + +TEST_P(SchedulerTest, expandRepackRequestBrokenTape) { + using namespace cta; + using namespace cta::objectstore; + unitTests::TempDirectory tempDirectory; + auto &catalogue = getCatalogue(); + auto &scheduler = getScheduler(); + auto &schedulerDB = getSchedulerDB(); + + cta::objectstore::Backend& backend = schedulerDB.getBackend(); + setupDefaultCatalogue(); +#ifdef STDOUT_LOGGING + log::StdoutLogger dl("dummy", "unitTest"); +#else + log::DummyLogger dl("", ""); +#endif + log::LogContext lc(dl); + + //Create an agent to represent this test process + cta::objectstore::AgentReference agentReference("expandRepackRequestTest", dl); + cta::objectstore::Agent agent(agentReference.getAgentAddress(), backend); + agent.initialize(); + agent.setTimeout_us(0); + agent.insertAndRegisterSelf(lc); + + cta::common::dataStructures::SecurityIdentity admin; + admin.username = "admin_user_name"; + admin.host = "admin_host"; + + //Create a logical library in the catalogue + const bool logicalLibraryIsDisabled = false; + catalogue.createLogicalLibrary(admin, s_libraryName, logicalLibraryIsDisabled, "Create logical library"); + + std::ostringstream ossVid; + ossVid << s_vid << "_" << 1; + std::string vid = ossVid.str(); + + { + auto tape = getDefaultTape(); + tape.vid = vid; + tape.full = true; + tape.state = common::dataStructures::Tape::BROKEN; + tape.stateReason = "Test"; + catalogue.createTape(s_adminOnAdminHost, tape); + } + + { + bool forceDisableTape = false; + cta::SchedulerDatabase::QueueRepackRequest qrr(vid,"file://"+tempDirectory.path(),common::dataStructures::RepackInfo::Type::MoveOnly, + common::dataStructures::MountPolicy::s_defaultMountPolicyForRepack,forceDisableTape,s_defaultRepackNoRecall); + ASSERT_THROW(scheduler.queueRepack(admin,qrr,lc),cta::exception::UserError); + scheduler.waitSchedulerDbSubthreadsComplete(); + + log::TimingList tl; + utils::Timer t; + + scheduler.promoteRepackRequestsToToExpand(lc); + scheduler.waitSchedulerDbSubthreadsComplete(); + + auto repackRequestToExpand = scheduler.getNextRepackRequestToExpand(); + ASSERT_EQ(nullptr,repackRequestToExpand); } }