Commit 878c7520 authored by Cedric Caffy's avatar Cedric Caffy
Browse files

[lto_rao] Implemented and tested the SLTFRAOAlgorithm

parent 7d314007
......@@ -18,7 +18,6 @@
#include "CTACostHeuristic.hpp"
#include "RAOHelpers.hpp"
#include <cmath>
namespace castor { namespace tape { namespace tapeserver { namespace rao {
......@@ -28,29 +27,18 @@ CTACostHeuristic::CTACostHeuristic() {
CTACostHeuristic::~CTACostHeuristic() {
}
double CTACostHeuristic::getCost(const FilePositionInfos& file1, const FilePositionInfos& file2) const {
double CTACostHeuristic::getCost(const FilePositionInfos & file1, const FilePositionInfos & file2) const {
double cost = 0.0;
Position endFile1Position = file1.getEndPosition();
Position startFile2Position = file2.getStartPosition();
uint64_t endFile1LPos = endFile1Position.getLPos();
uint64_t startFile2LPos = startFile2Position.getLPos();
uint32_t endFile1Wrap = endFile1Position.getWrap();
uint32_t startFile2Wrap = startFile2Position.getWrap();
uint8_t endFile1Band = file1.getEndBand();
uint8_t startFile2Band = file2.getStartBand();
uint8_t endFile1LandingZone = file1.getEndLandingZone();
uint8_t startFile2LandingZone = file2.getStartLandingZone();
uint64_t distance = std::abs(endFile1Position.getLPos() - startFile2Position.getLPos());
uint64_t distance = RAOHelpers::computeLongitudinalDistance(file1,file2);
int wrapChange = RAOHelpers::doesWrapChange(endFile1Wrap,startFile2Wrap);
int bandChange = RAOHelpers::doesBandChange(endFile1Band,startFile2Band);
int landingZoneChange = RAOHelpers::doesLandingZoneChange(endFile1LandingZone,startFile2LandingZone);
int directionChange = RAOHelpers::doesDirectionChange(endFile1Wrap,startFile2Wrap);
int wrapChange = RAOHelpers::doesWrapChange(file1,file2);
int bandChange = RAOHelpers::doesBandChange(file1,file2);
int landingZoneChange = RAOHelpers::doesLandingZoneChange(file1,file2);
int directionChange = RAOHelpers::doesDirectionChange(file1,file2);
int stepBack = RAOHelpers::doesStepBack(endFile1LPos,endFile1Wrap,startFile2Wrap,startFile2LPos);
int stepBack = RAOHelpers::doesStepBack(file1,file2);
cost = 4.29 + wrapChange * 6.69 + bandChange * 3.2 + landingZoneChange * (-6.04) + directionChange * 5.22 + stepBack * 11.32 + distance * 0.0006192;
return cost;
......
......@@ -22,12 +22,20 @@
namespace castor { namespace tape { namespace tapeserver { namespace rao {
/**
* This class implements the CTA CostHeuristic that is documented here:
* https://codimd.web.cern.ch/3adcp34cTqiv7tZJHpdxgA#
*/
class CTACostHeuristic : public CostHeuristic{
public:
CTACostHeuristic();
/**
*
* The coefficients used by this method are
* documented here : https://codimd.web.cern.ch/3adcp34cTqiv7tZJHpdxgA#Cost-Coefficients-calculated-by-Germ%C3%A1n-for-LTO-7M-media
*/
double getCost(const FilePositionInfos & file1, const FilePositionInfos & file2) const override;
virtual ~CTACostHeuristic();
private:
};
......
......@@ -22,8 +22,7 @@
namespace castor { namespace tape { namespace tapeserver { namespace rao {
ConfigurableRAOAlgorithmFactory::ConfigurableRAOAlgorithmFactory(drive::DriveInterface * drive, cta::catalogue::Catalogue * catalogue, const RAOParams & raoParams):m_drive(drive),
m_catalogue(catalogue), m_raoParams(raoParams){}
ConfigurableRAOAlgorithmFactory::ConfigurableRAOAlgorithmFactory(const RAOParams & raoParams):m_raoParams(raoParams){}
ConfigurableRAOAlgorithmFactory::~ConfigurableRAOAlgorithmFactory() {
}
......@@ -32,8 +31,10 @@ std::unique_ptr<RAOAlgorithm> ConfigurableRAOAlgorithmFactory::createRAOAlgorith
std::unique_ptr<RAOAlgorithm> ret;
switch(m_raoParams.getAlgorithmType()){
case RAOParams::RAOAlgorithmType::sltf:{
checkDriveInterfaceSet();
checkCatalogueSet();
SLTFRAOAlgorithm::Builder builder(m_raoParams,m_drive,m_catalogue);
ret.reset(builder.build().release());
ret = builder.build();
break;
}
default:
......@@ -43,5 +44,33 @@ std::unique_ptr<RAOAlgorithm> ConfigurableRAOAlgorithmFactory::createRAOAlgorith
return ret;
}
void ConfigurableRAOAlgorithmFactory::checkDriveInterfaceSet() const {
if(m_drive == nullptr){
throw cta::exception::Exception("In ConfigurableRAOAlgorithmFactory::checkDriveInterfaceSet(), the drive interface has not been set");
}
}
void ConfigurableRAOAlgorithmFactory::checkCatalogueSet() const {
if(m_catalogue == nullptr){
throw cta::exception::Exception("In ConfigurableRAOAlgorithmFactory::checkCatalogueSet(), the catalogue has not been set.");
}
}
ConfigurableRAOAlgorithmFactory::Builder::Builder(const RAOParams& raoParams){
m_configurableRAOAlgoFactory.reset(new ConfigurableRAOAlgorithmFactory(raoParams));
}
void ConfigurableRAOAlgorithmFactory::Builder::setCatalogue(cta::catalogue::Catalogue * catalogue) {
m_configurableRAOAlgoFactory->m_catalogue = catalogue;
}
void ConfigurableRAOAlgorithmFactory::Builder::setDriveInterface(drive::DriveInterface* drive) {
m_configurableRAOAlgoFactory->m_drive = drive;
}
std::unique_ptr<ConfigurableRAOAlgorithmFactory> ConfigurableRAOAlgorithmFactory::Builder::build(){
return std::move(m_configurableRAOAlgoFactory);
}
}}}}
\ No newline at end of file
......@@ -24,15 +24,55 @@
#include "RAOManager.hpp"
namespace castor { namespace tape { namespace tapeserver { namespace rao {
/**
* This factory instanciates a configurable RAO algorithm
* @param raoParams the parameters to configure the RAO algorithm
*/
class ConfigurableRAOAlgorithmFactory : public RAOAlgorithmFactory{
public:
ConfigurableRAOAlgorithmFactory(drive::DriveInterface * drive, cta::catalogue::Catalogue * catalogue, const RAOParams & raoParams);
/**
* Instanciates a configurable RAO algorithm
* @return a unique_ptr to a configurable RAO algorithm
*/
std::unique_ptr<RAOAlgorithm> createRAOAlgorithm() override;
virtual ~ConfigurableRAOAlgorithmFactory();
/**
* Builder class to build the ConfigurableRAOAlgorithmFactory
* @param raoParams the parameters of the Configurable RAOAlgorithm that will be instanciated by this factory
*/
class Builder {
public:
Builder(const RAOParams & raoParams);
/**
* If the factory need to talk to the drive before instanciating
* the RAOAlgorithm, the drive interface should be given by using this method.
* @param drive the drive interface to talk to the drive if necessary
*/
void setDriveInterface(drive::DriveInterface * drive);
/**
* If the factory need to talk to the catalogue before instanciating the RAOAlgorithm,
* the catalogue should be given by using this method
* @param catalogue the catalogue to talk to it
*/
void setCatalogue(cta::catalogue::Catalogue * catalogue);
/**
* Returns the unique pointer to instance of a ConfigurableRAOAlgorithmFactory
* @return the unique pointer to instance of a ConfigurableRAOAlgorithmFactory
*/
std::unique_ptr<ConfigurableRAOAlgorithmFactory> build();
private:
std::unique_ptr<ConfigurableRAOAlgorithmFactory> m_configurableRAOAlgoFactory;
};
private:
drive::DriveInterface * m_drive;
cta::catalogue::Catalogue * m_catalogue;
ConfigurableRAOAlgorithmFactory(const RAOParams & raoParams);
void checkDriveInterfaceSet() const;
void checkCatalogueSet() const;
drive::DriveInterface * m_drive = nullptr;
cta::catalogue::Catalogue * m_catalogue = nullptr;
RAOParams m_raoParams;
};
......
......@@ -20,6 +20,7 @@
#include "EnterpriseRAOAlgorithm.hpp"
#include "castor/tape/tapeserver/SCSI/Structures.hpp"
#include "common/Timer.hpp"
namespace castor { namespace tape { namespace tapeserver { namespace rao {
......@@ -30,6 +31,7 @@ EnterpriseRAOAlgorithm::~EnterpriseRAOAlgorithm() {
}
std::vector<uint64_t> EnterpriseRAOAlgorithm::performRAO(const std::vector<std::unique_ptr<cta::RetrieveJob> >& jobs) {
cta::utils::Timer totalTime;
std::vector<uint64_t> raoOrder;
uint64_t njobs = jobs.size();
uint32_t block_size = c_blockSize;
......@@ -67,8 +69,12 @@ std::vector<uint64_t> EnterpriseRAOAlgorithm::performRAO(const std::vector<std::
raoOrder.push_back(id);
}
files.clear();
m_raoTimings.insertAndReset("totalTime",totalTime);
return raoOrder;
}
std::string EnterpriseRAOAlgorithm::getName() const {
return "enterprise";
}
}}}}
\ No newline at end of file
......@@ -43,6 +43,8 @@ public:
*/
std::vector<uint64_t> performRAO(const std::vector<std::unique_ptr<cta::RetrieveJob>> & jobs) override;
std::string getName() const override;
private:
/**
* Constructs an EnterpriseRAOAlgorithm
......
......@@ -29,6 +29,8 @@ EnterpriseRAOAlgorithmFactory::~EnterpriseRAOAlgorithmFactory() {
}
std::unique_ptr<RAOAlgorithm> EnterpriseRAOAlgorithmFactory::createRAOAlgorithm() {
//For now we only have the EnterpriseRAOAlgorithm, but we could maybe have another one,
//this method should be modified consequently
return std::unique_ptr<RAOAlgorithm>(new EnterpriseRAOAlgorithm(m_drive,m_maxFilesSupported));
}
......
......@@ -23,9 +23,18 @@
namespace castor { namespace tape { namespace tapeserver { namespace rao {
/**
* This abstract class allows its implementations to return the position
* of a file represented by a cta::RetrieveJob
*/
class FilePositionEstimator {
public:
FilePositionEstimator();
/**
* Returns the position of the file corresponding to the RetrieveJob passed in parameter.
* @param job the file corresponding to this job for which the position should be returned
* @return the position of this file
*/
virtual FilePositionInfos getFilePosition(const cta::RetrieveJob & job) const = 0;
virtual ~FilePositionEstimator();
private:
......
......@@ -25,22 +25,22 @@ FilePositionInfos::FilePositionInfos() {
FilePositionInfos::FilePositionInfos(const FilePositionInfos& other){
if(this != &other){
m_startPosition = other.m_startPosition;
m_beginningPosition = other.m_beginningPosition;
m_endPosition = other.m_endPosition;
m_startBand = other.m_startBand;
m_beginningBand = other.m_beginningBand;
m_endBand = other.m_endBand;
m_startLandingZone = other.m_startLandingZone;
m_beginningLandingZone = other.m_beginningLandingZone;
m_endLandingZone = other.m_endLandingZone;
}
}
FilePositionInfos & FilePositionInfos::operator =(const FilePositionInfos& other){
if(this != &other){
m_startPosition = other.m_startPosition;
m_beginningPosition = other.m_beginningPosition;
m_endPosition = other.m_endPosition;
m_startBand = other.m_startBand;
m_beginningBand = other.m_beginningBand;
m_endBand = other.m_endBand;
m_startLandingZone = other.m_startLandingZone;
m_beginningLandingZone = other.m_beginningLandingZone;
m_endLandingZone = other.m_endLandingZone;
}
return *this;
......@@ -49,48 +49,48 @@ FilePositionInfos & FilePositionInfos::operator =(const FilePositionInfos& other
FilePositionInfos::~FilePositionInfos() {
}
void FilePositionInfos::setStartPosition(const Position & startPosition) {
m_startPosition = startPosition;
void FilePositionInfos::setBeginningPosition(const Position & beginningPosition) {
m_beginningPosition = beginningPosition;
}
void FilePositionInfos::setEndPosition(const Position& endPosition) {
m_endPosition = endPosition;
}
Position FilePositionInfos::getStartPosition() const {
return m_startPosition;
Position FilePositionInfos::getBeginningPosition() const {
return m_beginningPosition;
}
Position FilePositionInfos::getEndPosition() const {
return m_endPosition;
}
void FilePositionInfos::setStartBand(const uint8_t startBand){
m_startBand = startBand;
void FilePositionInfos::setBeginningBand(const uint8_t beginningBand){
m_beginningBand = beginningBand;
}
void FilePositionInfos::setEndBand(const uint8_t endBand){
m_endBand = endBand;
}
void FilePositionInfos::setStartLandingZone(const uint8_t startLandingZone){
m_startLandingZone = startLandingZone;
void FilePositionInfos::setBeginningLandingZone(const uint8_t beginningLandingZone){
m_beginningLandingZone = beginningLandingZone;
}
void FilePositionInfos::setEndLandingZone(const uint8_t endLandingZone){
m_endLandingZone = endLandingZone;
}
uint8_t FilePositionInfos::getStartBand() const {
return m_startBand;
uint8_t FilePositionInfos::getBeginningBand() const {
return m_beginningBand;
}
uint8_t FilePositionInfos::getEndBand() const {
return m_endBand;
}
uint8_t FilePositionInfos::getStartLandingZone() const {
return m_startLandingZone;
uint8_t FilePositionInfos::getBeginningLandingZone() const {
return m_beginningLandingZone;
}
uint8_t FilePositionInfos::getEndLandingZone() const {
......
......@@ -23,31 +23,80 @@
namespace castor { namespace tape { namespace tapeserver { namespace rao {
/**
* This class holds the position informations about a file : its physical position (start and end) and
* informations about the band and the landing zone of the beginning and the end of the file.
*/
class FilePositionInfos {
public:
/**
* Default constructor
*/
FilePositionInfos();
FilePositionInfos(const FilePositionInfos & other);
FilePositionInfos & operator=(const FilePositionInfos & other);
void setStartPosition(const Position & startPosition);
/**
* Set the beginning of the file position
* @param beginningPosition the beginning of the file position
*/
void setBeginningPosition(const Position & beginningPosition);
/**
* Set the end of the file position
* @param endPosition the end of the file position
*/
void setEndPosition(const Position & endPosition);
void setStartBand(const uint8_t startBand);
/**
* Set the beginning of the file band
* @param beginningBand the beginning of the file band
*/
void setBeginningBand(const uint8_t beginningBand);
/**
* Set the end of the file band
* @param endBand the end of the file band
*/
void setEndBand(const uint8_t endBand);
void setStartLandingZone(const uint8_t startLandingZone);
/**
* Set the beginning of the file landing zone
* @param startLandingZone
*/
void setBeginningLandingZone(const uint8_t beginningLandingZone);
/**
* Set the end of the file landing zone
* @param endLandingZone
*/
void setEndLandingZone(const uint8_t endLandingZone);
Position getStartPosition() const;
/**
* Get the physical position of the beginning of the file
*/
Position getBeginningPosition() const;
/**
* Get the physical position of the end of the file
*/
Position getEndPosition() const;
uint8_t getStartBand() const;
/**
* Get the beginning of the file band
*/
uint8_t getBeginningBand() const;
/**
* Get the end of the file band
*/
uint8_t getEndBand() const;
uint8_t getStartLandingZone() const;
/**
* Get the beginning of the file landing zone
*/
uint8_t getBeginningLandingZone() const;
/**
* Get the end of the file landing zone
*/
uint8_t getEndLandingZone() const;
virtual ~FilePositionInfos();
private:
Position m_startPosition;
Position m_beginningPosition;
Position m_endPosition;
uint8_t m_startBand;
uint8_t m_endBand;
uint8_t m_startLandingZone;
uint8_t m_endLandingZone;
uint8_t m_beginningBand = 0;
uint8_t m_endBand = 0;
uint8_t m_beginningLandingZone = 0;
uint8_t m_endLandingZone = 0;
};
}}}}
\ No newline at end of file
......@@ -31,20 +31,20 @@ InterpolationFilePositionEstimator::~InterpolationFilePositionEstimator() {
FilePositionInfos InterpolationFilePositionEstimator::getFilePosition(const cta::RetrieveJob& job) const {
FilePositionInfos ret;
//Get the tape file informations
cta::common::dataStructures::TapeFile tapeFile = job.selectedTapeFile();
uint64_t startBlock = tapeFile.blockId;
Position startPosition = getPhysicalPosition(startBlock);
ret.setStartPosition(startPosition);
uint64_t endBlock = determineEndBlock(tapeFile);
Position endPosition = getPhysicalPosition(endBlock);
uint64_t beginningBlockId = tapeFile.blockId;
//Set physical positions
Position beginningPosition = getPhysicalPosition(beginningBlockId);
ret.setBeginningPosition(beginningPosition);
uint64_t endBlockId = determineEndBlockId(tapeFile);
Position endPosition = getPhysicalPosition(endBlockId);
ret.setEndPosition(endPosition);
if(!m_mediaType.nbWraps){
std::string errorMsg = "In InterpolationFilePositionEstimator::getFilePosition(), the media type " + m_mediaType.name+" does not contain any information about the number of wraps the media has.";
throw cta::exception::Exception(errorMsg);
}
ret.setStartBand(RAOHelpers::determineBand(m_mediaType.nbWraps.value(),startPosition.getWrap()));
//Set band informations
ret.setBeginningBand(RAOHelpers::determineBand(m_mediaType.nbWraps.value(),beginningPosition.getWrap()));
ret.setEndBand(RAOHelpers::determineBand(m_mediaType.nbWraps.value(),endPosition.getWrap()));
ret.setStartLandingZone(RAOHelpers::determineLandingZone(m_mediaType.minLPos.value(),m_mediaType.maxLPos.value(),startPosition.getLPos()));
//Set landing zone informations
ret.setBeginningLandingZone(RAOHelpers::determineLandingZone(m_mediaType.minLPos.value(),m_mediaType.maxLPos.value(),beginningPosition.getLPos()));
ret.setEndLandingZone(RAOHelpers::determineLandingZone(m_mediaType.minLPos.value(),m_mediaType.maxLPos.value(),endPosition.getLPos()));
return ret;
}
......@@ -61,6 +61,10 @@ uint64_t InterpolationFilePositionEstimator::determineWrapNb(const uint64_t bloc
std::string errorMsg = "In InterpolationFilePositionEstimator::determineWrapNb(), unable to find the wrap number of the blockId " + std::to_string(blockId) + " because no EOWP informations have been found.";
throw cta::exception::Exception(errorMsg);
}
if(m_endOfWrapPositions.size() == 1){
//We are sure that if we have only 1 wrap, the file will be on the wrap 0
return 0;
}
auto eowpItor = m_endOfWrapPositions.begin();
while(eowpItor != m_endOfWrapPositions.end() && blockId > eowpItor->blockId){
eowpItor++;
......@@ -92,7 +96,7 @@ uint64_t InterpolationFilePositionEstimator::determineLPos(const uint64_t blockI
return retLpos;
}
uint64_t InterpolationFilePositionEstimator::determineEndBlock(const cta::common::dataStructures::TapeFile& file) const{
uint64_t InterpolationFilePositionEstimator::determineEndBlockId(const cta::common::dataStructures::TapeFile& file) const {
return file.blockId + (file.fileSize / c_blockSize) + 1;
}
......@@ -103,7 +107,7 @@ void InterpolationFilePositionEstimator::checkMediaTypeConsistency(){
throw cta::exception::Exception(errorMsg);
}
if(!m_mediaType.nbWraps){
std::string errorMsg = "In InterpolationFilePositionEstimator::checkMediaTypeConsistency(), the media type (" + m_mediaType.name + ") associated to the tape does not give informations about number of wraps the media contains.";
std::string errorMsg = "In InterpolationFilePositionEstimator::checkMediaTypeConsistency(), the media type (" + m_mediaType.name + ") associated to the tape mounted does not give informations about the number of wraps the media contains.";
throw cta::exception::Exception(errorMsg);
}
}
......
......@@ -25,6 +25,13 @@
namespace castor { namespace tape { namespace tapeserver { namespace rao {
/**
* This class implements an interpolation file position estimator.
* The file position is determined by interpolating the position according to the
* tape end of wrap positions and its mediatype.
* @param endOfWrapPositions the end of wrap positions of the mounted tape
* @param mediaType the media type of the mounted tape
*/
class InterpolationFilePositionEstimator : public FilePositionEstimator{
public:
InterpolationFilePositionEstimator(const std::vector<drive::endOfWrapPosition> & endOfWrapPositions, const cta::catalogue::MediaType & mediaType);
......@@ -33,15 +40,39 @@ public:
static const uint64_t c_blockSize = 256000;
private:
std::vector<drive::endOfWrapPosition> m_endOfWrapPositions;
cta::catalogue::MediaType m_mediaType;
/**
* In order for this position estimator to work, we need to check that the mediatype given in the constructor contains
* the information we need.
*/
void checkMediaTypeConsistency();
/**
* Determine the physical position of the blockId passed in parameter
* @param blockId the blockId to determine its physical position
*/
Position getPhysicalPosition(const uint64_t blockId) const;
/**
* Determine the wrap number in which the blockId passed in parameter is located
* @param blockId the blockId to determine its wrap number
*/
uint64_t determineWrapNb(const uint64_t blockId) const;
/**
* This method determine the longitudinal position (LPos) of the blockId
* passed in parameter
* @param blockId the blockId to determine its longitudinal position
* @param wrapNumber the wrapNumber where the blockId is located
* @return the longitudinal position that has a value comprised between mediaType.minLPos and mediaType.maxLPos
*/
uint64_t determineLPos(const uint64_t blockId, const uint64_t wrapNumber) const;
uint64_t determineEndBlock(const cta::common::dataStructures::TapeFile & file) const;
std::vector<drive::endOfWrapPosition> m_endOfWrapPositions;
cta::catalogue::MediaType m_mediaType;
/**
* Determine the blockId of the end of the file passed in parameter
* @param file the file to determine its end blockId
* @return the blockId of the end of the file passed in parameter
*/
uint64_t determineEndBlockId(const cta::common::dataStructures::TapeFile & file) const;
};
}}}}
\ No newline at end of file
......@@ -20,6 +20,7 @@
#include <numeric>
#include "LinearRAOAlgorithm.hpp"
#include "common/Timer.hpp"
namespace castor { namespace tape { namespace tapeserver { namespace rao {
......@@ -32,13 +33,20 @@ LinearRAOAlgorithm::~LinearRAOAlgorithm() {
std::vector<uint64_t> LinearRAOAlgorithm::performRAO(const std::vector<std::unique_ptr<cta::RetrieveJob> >& jobs) {
std::vector<uint64_t> raoIndices(jobs.size());
//Initialize the vector of indices
cta::utils::Timer t;
cta::utils::Timer totalTimer;
std::iota(raoIndices.begin(),raoIndices.end(),0);
m_raoTimings.insertAndReset("vectorInitializationTime",t);
//Sort the indices regarding the fseq of the jobs located in the vector passed in parameter
std::stable_sort(raoIndices.begin(),raoIndices.end(),[&jobs](const uint64_t index1, const uint64_t index2){
return jobs[index1]->selectedTapeFile().fSeq < jobs[index2]->selectedTapeFile().fSeq;
});
m_raoTimings.insertAndReset("vectorSortingTime",t);
m_raoTimings.insertAndReset("totalTime",totalTimer);
return raoIndices;
}
std::string LinearRAOAlgorithm::getName() const {