Commit 9cd7d8c7 authored by Eric Cano's avatar Eric Cano
Browse files

Added a unit test scenario reproducing the case when we fail to position.

The unit test showed a bug with the stopping of the watchdog thread in case of error.
The watchdog thread is now handled at the same level as all thread, at the session level.
parent c5a3e836
......@@ -213,6 +213,7 @@ int castor::tape::tapeserver::daemon::DataTransferSession::executeRead(log::LogC
if (rti.synchronousInjection()) {
// We got something to recall. Time to start the machinery
trst.setWaitForInstructionsTime(timer.secs());
watchdog.startThread();
trst.startThreads();
dwtp.startThreads();
rrp.startThreads();
......@@ -227,6 +228,7 @@ int castor::tape::tapeserver::daemon::DataTransferSession::executeRead(log::LogC
dwtp.waitThreads();
trst.waitThreads();
tsr.waitThreads();
watchdog.stopAndWaitThread();
return trst.getHardwareStatus();
} else {
// Just log this was an empty mount and that's it. The memory management
......
......@@ -173,7 +173,110 @@ TEST(tapeServer, DataTransferSessionGooddayRecall) {
temp += "";
ASSERT_EQ("V12345", sess.getVid());
}
TEST(tapeServer, DataTransferSessionWrongRecall) {
// This test is the same as the previous one, with
// wrong parameters set for the recall, so that we fail
// to recall the first file and cancel the second.
castor::log::StringLogger logger("tapeServerUnitTest");
// 1) prepare the client and run it in another thread
uint32_t volReq = 0xBEEF;
std::string vid = "V12345";
std::string density = "8000GC";
client::ClientSimulator sim(volReq, vid, density,
castor::tape::tapegateway::TAPE_GATEWAY,
castor::tape::tapegateway::READ);
client::ClientSimulator::ipPort clientAddr = sim.getCallbackAddress();
clientRunner simRun(sim);
simRun.start();
// 2) Prepare the VDQM request
castor::legacymsg::RtcpJobRqstMsgBody VDQMjob;
snprintf(VDQMjob.clientHost, CA_MAXHOSTNAMELEN+1, "%d.%d.%d.%d",
clientAddr.a, clientAddr.b, clientAddr.c, clientAddr.d);
snprintf(VDQMjob.driveUnit, CA_MAXUNMLEN+1, "T10D6116");
snprintf(VDQMjob.dgn, CA_MAXDGNLEN+1, "LIBXX");
VDQMjob.clientPort = clientAddr.port;
VDQMjob.volReqId = volReq;
// 3) Prepare the necessary environment (logger, plus system wrapper),
// construct and run the session.
castor::tape::System::mockWrapper mockSys;
mockSys.delegateToFake();
mockSys.disableGMockCallsCounting();
mockSys.fake.setupForVirtualDriveSLC6();
//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::drives::FakeDrive;
// We can prepare files for reading on the drive
{
// Label the tape
castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"],
"V12345", true);
mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind();
// And write to it
castor::tape::tapeserver::client::ClientInterface::VolumeInfo volInfo;
volInfo.vid="V12345";
volInfo.clientType=castor::tape::tapegateway::READ_TP;
castor::tape::tapeFile::WriteSession ws(*mockSys.fake.m_pathToDrive["/dev/nst0"],
volInfo , 0, true);
// Write a few files on the virtual tape
// Prepare the data
uint8_t data[1000];
castor::tape::SCSI::Structures::zeroStruct(&data);
for (int fseq=1; fseq <= 10 ; fseq ++) {
castor::tape::tapegateway::FileToRecallStruct ftr;
castor::tape::tapegateway::FileToMigrateStruct ftm_temp;
ftr.setFseq(fseq);
ftm_temp.setFseq(fseq);
ftr.setFileid(1000 + fseq);
ftm_temp.setFileid(1000 + fseq);
castor::tape::tapeFile::WriteFile wf(&ws, ftm_temp, 256*1024);
// Cut up the position into the old-style BlockId0-3
ftr.setBlockId0(wf.getPosition() >> 24);
ftr.setBlockId1( (wf.getPosition() >> 16) & 0xFF);
ftr.setBlockId2( (wf.getPosition() >> 8) & 0xFF);
ftr.setBlockId3(wf.getPosition() & 0xFF);
// Set the recall destination (/dev/null)
ftr.setPath("/dev/null");
// Write the data (one block)
wf.write(data, sizeof(data));
// Close the file
wf.close();
// Record the file for recall, with an out of tape fSeq
ftr.setFseq(ftr.fseq() + 1000);
sim.addFileToRecall(ftr, sizeof(data));
}
}
castor::tape::utils::DriveConfig driveConfig;
driveConfig.unitName = "T10D6116";
driveConfig.dgn = "T10KD6";
driveConfig.devFilename = "/dev/tape_T10D6116";
driveConfig.densities.push_back("8000GC");
driveConfig.densities.push_back("5000GC");
driveConfig.librarySlot = "manual";
driveConfig.devType = "T10000";
DataTransferSession::CastorConf castorConf;
castorConf.rtcopydBufsz = 1024*1024; // 1 MB memory buffers
castorConf.rtcopydNbBufs = 10;
castorConf.tapebridgeBulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000;
castorConf.tapebridgeBulkRequestRecallMaxFiles = 1000;
castorConf.tapeserverdDiskThreads = 1;
castor::legacymsg::RmcProxyDummy rmc;
castor::server::ProcessCap capUtils;
castor::messages::TapeserverProxyDummy initialProcess;
DataTransferSession sess("tapeHost", VDQMjob, logger, mockSys,
driveConfig, rmc, initialProcess, capUtils, castorConf);
sess.execute();
simRun.wait();
std::string temp = logger.getLog();
temp += "";
ASSERT_EQ("V12345", sess.getVid());
}
TEST(tapeServer, DataTransferSessionNoSuchDrive) {
// TpcpClients only supports 32 bits session number
......
......@@ -207,10 +207,6 @@ private:
}
m_tsr.tapeMountedForRead();
m_stats.waitReportingTime += timer.secs(utils::Timer::resetCounter);
//start the threading and ask to initiate the protocol with the tapeserverd
// TODO: move up so this thread is the same as others (if we still need it)
m_watchdog.startThread();
// Then we will loop on the tasks as they get from
// the task injector
std::auto_ptr<TapeReadTask> task;
......@@ -231,7 +227,6 @@ private:
throw castor::exception::Exception ("Session corrupted: exiting task execution loop in TapeReadSingleThread. Cleanup will follow.");
}
}
m_watchdog.stopThread();
}
// The session completed successfully, and the cleaner (unmount) executed
// at the end of the previous block. Log the results.
......
......@@ -98,7 +98,7 @@ template <class placeHolder> class TaskWatchDog : private castor::tape::threadin
void startThread(){
start();
}
void stopThread(){
void stopAndWaitThread(){
m_stopFlag.set();
wait();
}
......
......@@ -903,7 +903,7 @@ void drives::FakeDrive::spaceFileMarksForward(size_t count) {
if(!m_tape[i].compare(filemark)) countdown--;
}
if(countdown) {
throw Exception("Failed FakeDrive::spaceFileMarksForward");
throw castor::exception::Errnum(EIO, "Failed FakeDrive::spaceFileMarksForward");
}
m_current_position = i; //EOT side of the filemark
}
......
......@@ -101,7 +101,7 @@ namespace castor {
/**
* Checks the hdr1
* @param hdr1: the hdr1 header of the current file
* @param fileInfo: the Information structure of the current file
* @param filetoRecall: the Information structure of the current file
* @param volId: the volume id of the tape in the drive
*/
static void checkHDR1(const HDR1 &hdr1,
......@@ -111,7 +111,7 @@ namespace castor {
/**
* Checks the uhl1
* @param uhl1: the uhl1 header of the current file
* @param fileInfo: the Information structure of the current file
* @param fileToRecall: the Information structure of the current file
*/
static void checkUHL1(const UHL1 &uhl1,
const castor::tape::tapegateway::FileToRecallStruct &fileToRecall)
......
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