Commit 3a37f9a6 authored by Daniele Kruse's avatar Daniele Kruse
Browse files

added old code for getnextmount for future adaptation

parent 2717feeb
......@@ -171,6 +171,112 @@ std::unique_ptr<SchedulerDatabase::TapeMountDecisionInfo>
return ret;
}
/* Old getMountInfo
std::unique_ptr<SchedulerDatabase::TapeMountDecisionInfo>
OStoreDB::getMountInfo() {
//Allocate the getMountInfostructure to return.
assertAgentSet();
std::unique_ptr<TapeMountDecisionInfo> privateRet (new TapeMountDecisionInfo(
m_objectStore, *m_agent));
TapeMountDecisionInfo & tmdi=*privateRet;
// Get all the tape pools and tapes with queues (potential mounts)
objectstore::RootEntry re(m_objectStore);
objectstore::ScopedSharedLock rel(re);
re.fetch();
// Take an exclusive lock on the scheduling and fetch it.
tmdi.m_schedulerGlobalLock.reset(
new SchedulerGlobalLock(re.getSchedulerGlobalLock(), m_objectStore));
tmdi.m_lockOnSchedulerGlobalLock.lock(*tmdi.m_schedulerGlobalLock);
tmdi.m_lockTaken = true;
tmdi.m_schedulerGlobalLock->fetch();
auto tpl = re.dumpTapePools();
for (auto tpp=tpl.begin(); tpp!=tpl.end(); tpp++) {
// Get the tape pool object
objectstore::TapePool tpool(tpp->address, m_objectStore);
// debug utility variable
std::string __attribute__((__unused__)) poolName = tpp->tapePool;
objectstore::ScopedSharedLock tpl(tpool);
tpool.fetch();
// If there are files queued, we create an entry for this tape pool in the
// mount candidates list.
if (tpool.getJobsSummary().files) {
tmdi.potentialMounts.push_back(SchedulerDatabase::PotentialMount());
auto & m = tmdi.potentialMounts.back();
m.tapePool = tpp->tapePool;
m.type = cta::MountType::ARCHIVE;
m.bytesQueued = tpool.getJobsSummary().bytes;
m.filesQueued = tpool.getJobsSummary().files;
m.oldestJobStartTime = tpool.getJobsSummary().oldestJobStartTime;
m.priority = tpool.getJobsSummary().priority;
m.mountCriteria.maxFilesQueued =
tpool.getMountCriteriaByDirection().archive.maxFilesQueued;
m.mountCriteria.maxBytesQueued =
tpool.getMountCriteriaByDirection().archive.maxBytesQueued;
m.mountCriteria.maxAge =
tpool.getMountCriteriaByDirection().archive.maxAge;
m.mountCriteria.quota =
tpool.getMountCriteriaByDirection().archive.quota;
m.logicalLibrary = "";
}
// For each tape in the pool, list the tapes with work
auto tl = tpool.dumpTapesAndFetchStatus();
for (auto tp = tl.begin(); tp!= tl.end(); tp++) {
objectstore::Tape t(tp->address, m_objectStore);
objectstore::ScopedSharedLock tl(t);
t.fetch();
if (t.getJobsSummary().files) {
tmdi.potentialMounts.push_back(PotentialMount());
auto & m = tmdi.potentialMounts.back();
m.type = cta::MountType::RETRIEVE;
m.bytesQueued = t.getJobsSummary().bytes;
m.filesQueued = t.getJobsSummary().files;
m.oldestJobStartTime = t.getJobsSummary().oldestJobStartTime;
m.priority = t.getJobsSummary().priority;
m.vid = t.getVid();
m.logicalLibrary = t.getLogicalLibrary();
m.mountCriteria.maxFilesQueued =
tpool.getMountCriteriaByDirection().retrieve.maxFilesQueued;
m.mountCriteria.maxBytesQueued =
tpool.getMountCriteriaByDirection().retrieve.maxBytesQueued;
m.mountCriteria.maxAge =
tpool.getMountCriteriaByDirection().retrieve.maxAge;
m.mountCriteria.quota =
tpool.getMountCriteriaByDirection().retrieve.quota;
m.logicalLibrary = t.getLogicalLibrary();
}
}
}
// Dedication information comes here
// TODO
//
// Collect information about the existing mounts
objectstore::DriveRegister dr(re.getDriveRegisterAddress(), m_objectStore);
objectstore::ScopedSharedLock drl(dr);
dr.fetch();
auto dl = dr.dumpDrives();
using common::DriveStatus;
std::set<int> activeDriveStatuses = {
(int)DriveStatus::Starting,
(int)DriveStatus::Mounting,
(int)DriveStatus::Transfering,
(int)DriveStatus::Unloading,
(int)DriveStatus::Unmounting,
(int)DriveStatus::DrainingToDisk };
for (auto d=dl.begin(); d!= dl.end(); d++) {
if (activeDriveStatuses.count((int)d->status)) {
tmdi.existingMounts.push_back(ExistingMount());
tmdi.existingMounts.back().type = d->mountType;
tmdi.existingMounts.back().tapePool = d->currentTapePool;
}
}
std::unique_ptr<SchedulerDatabase::TapeMountDecisionInfo> ret(std::move(privateRet));
return ret;
}
*/
void OStoreDB::createStorageClass(const std::string& name,
const uint16_t nbCopies, const cta::CreationLog& creationLog) {
RootEntry re(m_objectStore);
......
......@@ -265,5 +265,144 @@ std::list<cta::common::dataStructures::DriveState> cta::Scheduler::getDriveState
// getNextMount
//------------------------------------------------------------------------------
std::unique_ptr<cta::TapeMount> cta::Scheduler::getNextMount(const std::string &logicalLibraryName, const std::string &driveName) {
/*
// In order to decide the next mount to do, we have to take a global lock on
// the scheduling, retrieve a list of all running mounts, queues sizes for
// tapes and tape pools, filter the tapes which are actually accessible to
// this drive (by library and dedication), order the candidates by priority
// below threshold, and pick one at a time. In addition, for archives, we
// might not find a suitable tape (by library and dedication). In such a case,
// we should find out if no tape at all is available, and log an error if
// so.
// We then skip to the next candidate, until we find a suitable one and
// return the mount, or exhaust all of them an
// Many steps for this logic are not specific for the database and are hence
// implemented in the scheduler itself.
// First, get the mount-related info from the DB
std::unique_ptr<SchedulerDatabase::TapeMountDecisionInfo> mountInfo;
mountInfo = m_db.getMountInfo();
// We should now filter the potential mounts to keep only the ones we are
// compatible with (match the logical library for retrieves).
// We also only want the potential mounts for which we still have
// We cannot filter the archives yet
for (auto m = mountInfo->potentialMounts.begin(); m!= mountInfo->potentialMounts.end();) {
if (m->type == MountType::RETRIEVE && m->logicalLibrary != logicalLibraryName) {
m = mountInfo->potentialMounts.erase(m);
} else {
m++;
}
}
// With the existing mount list, we can now populate the potential mount list
// with the per tape pool existing mount statistics.
typedef std::pair<std::string, cta::MountType::Enum> tpType;
std::map<tpType, uint32_t> existingMountsSummary;
for (auto em=mountInfo->existingMounts.begin(); em!=mountInfo->existingMounts.end(); em++) {
try {
existingMountsSummary.at(tpType(em->tapePool, em->type))++;
} catch (std::out_of_range &) {
existingMountsSummary[tpType(em->tapePool, em->type)] = 1;
}
}
// We can now filter out the potential mounts for which their mount criteria
// is already met, filter out the potential mounts for which the maximum mount
// quota is already reached, and weight the remaining by how much of their quota
// is reached
for (auto m = mountInfo->potentialMounts.begin(); m!= mountInfo->potentialMounts.end();) {
// Get summary data
uint32_t existingMounts;
try {
existingMounts = existingMountsSummary.at(tpType(m->tapePool, m->type));
} catch (std::out_of_range &) {
existingMounts = 0;
}
bool mountPassesACriteria = false;
if (m->bytesQueued / (1 + existingMounts) >= m->mountCriteria.maxBytesQueued)
mountPassesACriteria = true;
if (m->filesQueued / (1 + existingMounts) >= m->mountCriteria.maxFilesQueued)
mountPassesACriteria = true;
if (!existingMounts && ((time(NULL) - m->oldestJobStartTime) > (int64_t)m->mountCriteria.maxAge))
mountPassesACriteria = true;
if (!mountPassesACriteria || existingMounts >= m->mountCriteria.quota) {
m = mountInfo->potentialMounts.erase(m);
} else {
// populate the mount with a weight
m->ratioOfMountQuotaUsed = 1.0L * existingMounts / m->mountCriteria.quota;
m++;
}
}
// We can now sort the potential mounts in decreasing priority order.
// The ordering is defined in operator <.
// We want the result in descending order or priority so we reverse the vector
std::sort(mountInfo->potentialMounts.begin(), mountInfo->potentialMounts.end());
std::reverse(mountInfo->potentialMounts.begin(), mountInfo->potentialMounts.end());
// We can now simply iterate on the candidates until we manage to create a
// mount for one of them
for (auto m = mountInfo->potentialMounts.begin(); m!=mountInfo->potentialMounts.end(); m++) {
// If the mount is an archive, we still have to find a tape.
if (m->type==cta::MountType::ARCHIVE) {
// We need to find a tape for archiving. It should be both in the right
// tape pool and in the drive's logical library
auto tapesList = m_db.getTapes();
// The first tape matching will go for a prototype.
// TODO: improve to reuse already partially written tapes
for (auto t=tapesList.begin(); t!=tapesList.end(); t++) {
if (t->logicalLibraryName == logicalLibraryName &&
t->tapePoolName == m->tapePool &&
t->status.availableToWrite()) {
// We have our tape. Try to create the session. Prepare a return value
// for it.
std::unique_ptr<ArchiveMount> internalRet(new ArchiveMount(m_ns));
// Get the db side of the session
try {
internalRet->m_dbMount.reset(mountInfo->createArchiveMount(t->vid,
t->tapePoolName,
driveName,
logicalLibraryName,
Utils::getShortHostname(),
time(NULL)).release());
internalRet->m_sessionRunning = true;
internalRet->setDriveStatus(cta::common::DriveStatus::Starting);
return std::unique_ptr<TapeMount> (internalRet.release());
} catch (cta::exception::Exception & ex) {
continue;
}
}
}
} else if (m->type==cta::MountType::RETRIEVE) {
// We know the tape we intend to mount. We have to validate the tape is
// actually available to read, and pass on it if no.
auto tapesList = m_db.getTapes();
for (auto t=tapesList.begin(); t!=tapesList.end(); t++) {
if (t->vid == m->vid && t->status.availableToRead()) {
try {
// create the mount, and populate its DB side.
std::unique_ptr<RetrieveMount> internalRet (
new RetrieveMount(mountInfo->createRetrieveMount(t->vid,
t->tapePoolName,
driveName,
logicalLibraryName,
Utils::getShortHostname(),
time(NULL))));
internalRet->m_sessionRunning = true;
internalRet->m_diskRunning = true;
internalRet->m_tapeRunning = true;
internalRet->setDriveStatus(cta::common::DriveStatus::Starting);
return std::unique_ptr<TapeMount> (internalRet.release());
} catch (cta::exception::Exception & ex) {
std::string debug=ex.getMessageValue();
continue;
}
}
}
} else {
throw std::runtime_error("In Scheduler::getNextMount unexpected mount type");
}
}
*/
return std::unique_ptr<TapeMount>();
}
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