Commit 6597daaa authored by Cedric CAFFY's avatar Cedric CAFFY Committed by Eric Cano
Browse files

Added a check while mounting a tape for writing : if some tape files located...

Added a check while mounting a tape for writing : if some tape files located in the writing tape are not superseded by others,
the write session will fail.

Note: The test CatalogueTest.exist_non_superseded_files_after_fseq is supposed to fail.
parent 27d83a93
......@@ -336,6 +336,14 @@ 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;
......@@ -589,6 +597,15 @@ 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
*
* @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 existNonSupersededFilesAfterFSeq(const std::string &vid, const uint64_t fSeq) const = 0;
}; // class Catalogue
......
......@@ -224,6 +224,10 @@ 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);
......@@ -376,6 +380,11 @@ public:
bool tapeExists(const std::string &vid) const override {
return retryOnLostConnection(m_log, [&]{return m_catalogue->tapeExists(vid);}, m_maxTriesToConnect);
}
bool existNonSupersededFilesAfterFSeq(const std::string& vid, const uint64_t fSeq) const override {
return retryOnLostConnection(m_log,[&]{return m_catalogue->existNonSupersededFilesAfterFSeq(vid,fSeq);},m_maxTriesToConnect);
}
protected:
......
......@@ -11512,6 +11512,118 @@ 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 std::string tapePoolName = "tape_pool_name";
const std::string vo = "vo";
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, "Create logical library");
m_catalogue->createTapePool(m_admin, tapePoolName, vo, 2, true, "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->existNonSupersededFilesAfterFSeq(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->existNonSupersededFilesAfterFSeq(vid1,0));
//No file after the only file inserted, existNonSupersededFilesAfterFseq = false
ASSERT_FALSE(m_catalogue->existNonSupersededFilesAfterFSeq(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->existNonSupersededFilesAfterFSeq(vid1,0));
ASSERT_TRUE(m_catalogue->existNonSupersededFilesAfterFSeq(vid2,0));
}
TEST_P(cta_catalogue_CatalogueTest, ping) {
using namespace cta;
......
......@@ -105,6 +105,7 @@ 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"); }
......@@ -113,7 +114,8 @@ 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 existNonSupersededFilesAfterFSeq(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) {
threading::MutexLocker lm(m_tapeEnablingMutex);
......
......@@ -1791,6 +1791,31 @@ bool RdbmsCatalogue::tapeExists(rdbms::Conn &conn, const std::string &vid) const
}
}
bool RdbmsCatalogue::existNonSupersededFilesAfterFSeq(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();
return rset.next();
} catch(exception::UserError &) {
throw;
} catch(exception::Exception &ex) {
ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
throw;
}
}
//------------------------------------------------------------------------------
// deleteTape
//------------------------------------------------------------------------------
......@@ -2263,6 +2288,63 @@ void RdbmsCatalogue::reclaimTape(const common::dataStructures::SecurityIdentity
}
}
//------------------------------------------------------------------------------
//fakeReclaimTapeForTests
//------------------------------------------------------------------------------
void RdbmsCatalogue::fakeReclaimTapeForTests(const common::dataStructures::SecurityIdentity& admin, const std::string& vid) {
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'";
auto conn = m_connPool.getConn();
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.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;
} catch(exception::Exception &ex) {
ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
throw;
}
}
//------------------------------------------------------------------------------
// getTapeLogFromRset
//------------------------------------------------------------------------------
......
......@@ -330,7 +330,7 @@ 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;
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;
......@@ -713,6 +713,16 @@ 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
*
* @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 existNonSupersededFilesAfterFSeq(const std::string& vid, const uint64_t fSeq) const override;
/**
* Returns the list of tapes that meet the specified search criteria.
......
......@@ -104,6 +104,16 @@ uint32_t cta::ArchiveMount::getNbFiles() const {
return m_dbMount->nbFilesCurrentlyOnTape;
}
//------------------------------------------------------------------------------
// checkTapeFSeqForWriting
//------------------------------------------------------------------------------
void cta::ArchiveMount::checkTapeFSeqForWriting(uint64_t fSeq) const {
if(m_catalogue.existNonSupersededFilesAfterFSeq(getVid(),fSeq)){
throw cta::exception::Exception("Non superseded files have been detected in the tape "+getVid() +" after "+std::to_string(fSeq));
}
}
//------------------------------------------------------------------------------
// createDiskReporter
//------------------------------------------------------------------------------
......
......@@ -172,6 +172,14 @@ 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 checkTapeFSeqForWriting(uint64_t fSeq) const;
/**
* Creates a disk reporter for the ArchiveJob (this is a wrapper).
* @param URL: report address
......
......@@ -1848,6 +1848,165 @@ 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";
catalogue.createLogicalLibrary(s_adminOnAdminHost, s_libraryName,
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;
......
......@@ -319,6 +319,8 @@ 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.checkTapeFSeqForWriting(m_lastFseq);
currentErrorToCount = "Error_tapeLoad";
waitForDrive();
currentErrorToCount = "Error_checkingTapeAlert";
......@@ -603,4 +605,3 @@ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::logSCSIMetrics() {
m_logContext.log(cta::log::ERR, "Exception in logging volume statistics");
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment