Commit fba23e8f authored by David COME's avatar David COME
Browse files

ReadFile::Position is now split in 2 smaller functions and the read session is...

ReadFile::Position is now split in 2 smaller functions and the read session is corrupted (when positioning by Feq) if something wrong happens in the ReadFile's constructor or if we are in a bad state in the destructor
parent b68131a7
......@@ -78,22 +78,6 @@ namespace castor {
throw TapeFormatError(ex_str.str());
}
}
ReadFile::ReadFile(ReadSession *rs,
const castor::tape::tapegateway::FileToRecallStruct &fileToRecall)
: m_currentBlockSize(0), m_session(rs)
{
if(m_session->isCorrupted()) {
throw SessionCorrupted();
}
m_session->lock();
position(fileToRecall);
}
ReadFile::~ReadFile() throw() {
m_session->release();
}
bool HeaderChecker::checkHeaderNumericalField(const std::string &headerField,
const uint64_t value, const headerBase base) {
uint64_t res = 0;
......@@ -170,26 +154,73 @@ namespace castor {
ftr.setBlockId2((blockId >> 8) & 0xFF);
ftr.setBlockId3((blockId) & 0xFF);
}
void ReadFile::setBlockSize(const UHL1 &uhl1) {
m_currentBlockSize = (size_t)atol(uhl1.getBlockSize().c_str());
if(m_currentBlockSize<1) {
std::stringstream ex_str;
ex_str << "[ReadFile::setBlockSize] - Invalid block size in uhl1 detected";
throw TapeFormatError(ex_str.str());
ReadFile::ReadFile(ReadSession *rs,
const castor::tape::tapegateway::FileToRecallStruct &fileToRecall)
: m_currentBlockSize(0), m_session(rs), m_positionCommandCode(fileToRecall.positionCommandCode())
{
if(m_session->isCorrupted()) {
throw SessionCorrupted();
}
m_session->lock();
try{
position(fileToRecall);
} catch(...){
if(castor::tape::tapegateway::TPPOSIT_FSEQ==m_positionCommandCode &&
m_session->getCurrentFilePart() != Header){
m_session->setCorrupted();
}
throw;
}
}
void ReadFile::position(
const castor::tape::tapegateway::FileToRecallStruct &fileToRecall) {
if(m_session->getCurrentFilePart() != Header) {
ReadFile::~ReadFile() throw() {
if(castor::tape::tapegateway::TPPOSIT_FSEQ==m_positionCommandCode &&
m_session->getCurrentFilePart() != Header){
m_session->setCorrupted();
throw SessionCorrupted();
}
if(fileToRecall.positionCommandCode()==castor::tape::tapegateway::TPPOSIT_BLKID) {
// if we want the first file on tape (fileInfo.blockId==0) we need to skip the VOL1 header
m_session->release();
}
void ReadFile::positionByFseq(const castor::tape::tapegateway::FileToRecallStruct &fileToRecall) {
if(fileToRecall.fseq()<1) {
std::stringstream err;
err << "Unexpected fileId in ReadFile::position with fSeq expected >=1, got: "
<< fileToRecall.fseq() << ")";
throw castor::exception::InvalidArgument(err.str());
}
int64_t fseq_delta = fileToRecall.fseq() - m_session->getCurrentFseq();
if(fileToRecall.fseq() == 1) {
// special case: we can rewind the tape to be faster
//(TODO: in the future we could also think of a threshold above
//which we rewind the tape anyway and then space forward)
m_session->m_drive.rewind();
VOL1 vol1;
m_session->m_drive.readExactBlock((void * )&vol1, sizeof(vol1), "[ReadFile::position] - Reading VOL1");
try {
vol1.verify();
} catch (std::exception & e) {
throw TapeFormatError(e.what());
}
}
else if(fseq_delta == 0) {
// do nothing we are in the correct place
}
else if(fseq_delta > 0) {
//we need to skip three file marks per file (header, payload, trailer)
m_session->m_drive.spaceFileMarksForward((uint32_t)fseq_delta*3);
}
else { //fseq_delta < 0
//we need to skip three file marks per file
//(trailer, payload, header) + 1 to go on the BOT (beginning of tape) side
//of the file mark before the header of the file we want to read
m_session->m_drive.spaceFileMarksBackwards((uint32_t)abs(fseq_delta)*3+1);
m_session->m_drive.readFileMark("[ReadFile::position] Reading file mark right before the header of the file we want to read");
}
}
void ReadFile::positionByBlockID(const castor::tape::tapegateway::FileToRecallStruct &fileToRecall) {
// if we want the first file on tape (fileInfo.blockId==0) we need to skip the VOL1 header
const uint32_t destination_block = BlockId::extract(fileToRecall) ?
BlockId::extract(fileToRecall) : 1;
/*
......@@ -202,50 +233,33 @@ namespace castor {
//the headers of the desired file, so now let's check the headers...
m_session->m_drive.positionToLogicalObject(destination_block);
}
else if(fileToRecall.positionCommandCode()==castor::tape::tapegateway::TPPOSIT_FSEQ) {
try {
if(fileToRecall.fseq()<1) {
std::stringstream err;
err << "Unexpected fileId in ReadFile::position with fSeq expected >=1, got: "
<< fileToRecall.fseq() << ")";
throw castor::exception::InvalidArgument(err.str());
}
int64_t fseq_delta = fileToRecall.fseq() - m_session->getCurrentFseq();
if(fileToRecall.fseq() == 1) {
// special case: we can rewind the tape to be faster
//(TODO: in the future we could also think of a threshold above
//which we rewind the tape anyway and then space forward)
m_session->m_drive.rewind();
VOL1 vol1;
m_session->m_drive.readExactBlock((void * )&vol1, sizeof(vol1), "[ReadFile::position] - Reading VOL1");
try {
vol1.verify();
} catch (std::exception & e) {
throw TapeFormatError(e.what());
}
}
else if(fseq_delta == 0) {
// do nothing we are in the correct place
}
else if(fseq_delta > 0) {
//we need to skip three file marks per file (header, payload, trailer)
m_session->m_drive.spaceFileMarksForward((uint32_t)fseq_delta*3);
}
else { //fseq_delta < 0
//we need to skip three file marks per file
//(trailer, payload, header) + 1 to go on the BOT (beginning of tape) side
//of the file mark before the header of the file we want to read
m_session->m_drive.spaceFileMarksBackwards((uint32_t)abs(fseq_delta)*3+1);
m_session->m_drive.readFileMark("[ReadFile::position] Reading file mark right before the header of the file we want to read");
}
} catch (...) {
// In fseq positioning mode, any failure to position/read is
// fatal to the session as we lose information about where we are
// positioned
m_session->setCorrupted();
throw;
}
void ReadFile::setBlockSize(const UHL1 &uhl1) {
m_currentBlockSize = (size_t)atol(uhl1.getBlockSize().c_str());
if(m_currentBlockSize<1) {
std::stringstream ex_str;
ex_str << "[ReadFile::setBlockSize] - Invalid block size in uhl1 detected";
throw TapeFormatError(ex_str.str());
}
}
void ReadFile::position(
const castor::tape::tapegateway::FileToRecallStruct &fileToRecall) {
if(m_session->getCurrentFilePart() != Header && fileToRecall.positionCommandCode()!=castor::tape::tapegateway::TPPOSIT_BLKID) {
m_session->setCorrupted();
throw SessionCorrupted();
}
// Make sure the session state is advanced to cover our failures
// and allow next call to position to discover we failed half way
m_session->setCurrentFilePart(HeaderProcessing);
if(castor::tape::tapegateway::TPPOSIT_BLKID==m_positionCommandCode) {
positionByBlockID(fileToRecall);
}
else if(castor::tape::tapegateway::TPPOSIT_FSEQ==m_positionCommandCode) {
positionByFseq(fileToRecall);
}
else {
throw UnsupportedPositioningMode();
......
......@@ -41,6 +41,7 @@ namespace castor {
enum PartOfFile
{
Header,
HeaderProcessing,
Payload,
Trailer
};
......@@ -311,7 +312,8 @@ namespace castor {
size_t read(void *data, const size_t size) ;
private:
void positionByFseq(const castor::tape::tapegateway::FileToRecallStruct &fileToRecall) ;
void positionByBlockID(const castor::tape::tapegateway::FileToRecallStruct &fileToRecall) ;
/**
* Positions the tape for reading the file. Depending on the previous activity,
* it is the duty of this function to determine how to best move to the next
......@@ -339,6 +341,11 @@ namespace castor {
* Session to which we are attached to
*/
ReadSession *m_session;
/**
* What kind of command we use to position ourself on the tape (fseq or blockid)
*/
castor::tape::tapegateway::PositionCommandCode m_positionCommandCode;
};
/**
......
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