Commit 233e6ee0 authored by Eric Cano's avatar Eric Cano
Browse files

Added support for status and current mount in the objectstore tape.

Started the mount selection logic in the OStoreDB.
parent 90899166
......@@ -41,6 +41,19 @@ void cta::objectstore::Tape::initialize(const std::string &name,
m_payload.set_oldestjobtime(0);
m_payload.set_priority(0);
m_payload.set_retrievejobstotalsize(0);
m_payload.set_busy(false);
m_payload.set_archived(false);
m_payload.set_disabled(false);
m_payload.set_readonly(false);
m_payload.set_full(false);
auto cm = m_payload.mutable_currentmount();
cm->set_drivemodel("");
cm->set_drivename("");
cm->set_driveserial("");
cm->set_drivevendor("");
cm->set_host("");
cm->set_time(0);
m_payload.set_currentmounttype(serializers::MountType::Archive_t);
m_payloadInterpreted = true;
}
......@@ -133,3 +146,75 @@ cta::objectstore::Tape::JobsSummary cta::objectstore::Tape::getJobsSummary() {
ret.priority = m_payload.priority();
return ret;
}
bool cta::objectstore::Tape::isArchived() {
checkPayloadReadable();
return m_payload.archived();
}
void cta::objectstore::Tape::setArchived(bool archived) {
checkPayloadWritable();
m_payload.set_archived(archived);
}
bool cta::objectstore::Tape::isDisabled() {
checkPayloadReadable();
return m_payload.disabled();
}
void cta::objectstore::Tape::setDisabled(bool disabled) {
checkPayloadWritable();
m_payload.set_disabled(disabled);
}
bool cta::objectstore::Tape::isReadOnly() {
checkPayloadReadable();
return m_payload.readonly();
}
void cta::objectstore::Tape::setReadOnly(bool readOnly) {
checkPayloadWritable();
m_payload.set_readonly(readOnly);
}
bool cta::objectstore::Tape::isFull() {
checkPayloadReadable();
return m_payload.full();
}
void cta::objectstore::Tape::setFull(bool full) {
checkPayloadWritable();
m_payload.set_full(full);
}
bool cta::objectstore::Tape::isBusy() {
checkPayloadReadable();
return m_payload.busy();
}
void cta::objectstore::Tape::setBusy(const std::string& drive, MountType mountType,
const std::string & host, time_t startTime, const std::string& agentAddress) {
checkPayloadWritable();
m_payload.set_busy(true);
auto * cm = m_payload.mutable_currentmount();
cm->set_drivemodel("");
cm->set_driveserial("");
cm->set_drivename(drive);
cm->set_host(host);
cm->set_time((uint64_t)time);
switch (mountType) {
case MountType::Archive:
m_payload.set_currentmounttype(objectstore::serializers::MountType::Archive_t);
break;
case MountType::Retrieve:
m_payload.set_currentmounttype(objectstore::serializers::MountType::Retrieve_t);
break;
}
}
void cta::objectstore::Tape::releaseBusy() {
checkPayloadWritable();
m_payload.set_busy(false);
}
......@@ -43,6 +43,24 @@ public:
std::string getLogicalLibrary();
void setLogicalLibrary(const std::string & library);
// Tape status management ====================================================
void setFull(bool full);
bool isFull();
void setArchived(bool archived);
bool isArchived();
void setReadOnly(bool readOnly);
bool isReadOnly();
void setDisabled(bool disabled);
bool isDisabled();
enum class MountType {
Archive, Retrieve
};
void setBusy(const std::string & drive, MountType mountType,
const std::string & host, time_t time, const std::string &agentAddress);
void releaseBusy();
bool isBusy();
// Retrieve jobs management ==================================================
void addJob(const RetrieveToFileRequest::JobDump & job,
const std::string & retrieveToFileAddress, uint64_t size, uint64_t priority,
......
......@@ -15,6 +15,13 @@ enum ObjectType {
GenericObject_t = 1000;
}
// The types of mounts
enum MountType {
NoMount_t = 0;
Archive_t = 1;
Retrieve_t = 2;
}
// The base object header. This will allow introspection and automatic
// "garbage collection", i.e. returning an unprocessed object belonging
// to a dead agent to the right queue or container.
......@@ -215,7 +222,8 @@ message MountInfo {
required string drivevendor = 4201;
required string drivemodel = 4202;
required string driveserial = 4203;
required uint64 time = 4204;
required string drivename = 4204;
required uint64 time = 4205;
}
message Tape {
......@@ -233,6 +241,14 @@ message Tape {
required uint64 oldestjobtime = 4308;
required uint64 priority = 4309;
// There are no per tape mount criteria/quotas (they are per tape pool).
// Tape status
required bool busy = 4310;
required MountType currentmounttype = 4311;
required MountInfo currentmount = 4312;
required bool archived = 4313;
required bool disabled = 4314;
required bool readonly = 4315;
required bool full = 4316;
}
// ------------- Archive Jobs --------------------------------------------------
......@@ -326,11 +342,7 @@ message RetrieveToDirRequest {
// ------------- Drives handling ----------------------------------------------
enum MountType {
NoMount_t = 0;
Archive_t = 1;
Retrieve_t = 2;
}
message DriveInfo {
required string drivename = 5000;
......
......@@ -67,7 +67,9 @@ void OStoreDB::assertAgentSet() {
std::unique_ptr<SchedulerDatabase::TapeMountDecisionInfo>
OStoreDB::getMountInfo() {
//Allocate the getMountInfostructure to return.
std::unique_ptr<TapeMountDecisionInfo> privateRet (new TapeMountDecisionInfo());
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);
......@@ -1042,9 +1044,81 @@ void OStoreDB::deleteRetrieveRequest(const SecurityIdentity& requester,
std::unique_ptr<SchedulerDatabase::ArchiveMount>
OStoreDB::TapeMountDecisionInfo::createArchiveMount(
const std::string& vid, const std::string driveName) {
const std::string& vid, const std::string & tapePool, const std::string driveName,
const std::string& hostName, time_t startTime) {
// In order to create the mount, we have to:
// Check we actually hold the scheduling lock
// Check the tape exists, add it to ownership and set its activity status to
// busy, with the current agent as the current tape user
// Check the drive exists, add the drive to ownership and set its activity
// status to mount starting with the current agent as the drive user
// Prepare the return value
std::unique_ptr<OStoreDB::ArchiveMount> privateRet(
new OStoreDB::ArchiveMount(m_objectStore, m_agent));
auto &am = *privateRet;
// Check we hold the scheduling lock
if (!m_lockTaken)
throw SchedulingLockNotHeld("In OStoreDB::TapeMountDecisionInfo::createArchiveMount: "
"cannot create mount without holding scheduling lock");
// Find the tape
am.m_mountInfo.vid = vid;
am.m_mountInfo.drive = driveName;
am.m_mountInfo.tapePool = tapePool;
{
objectstore::RootEntry re(m_objectStore);
objectstore::ScopedSharedLock rel(re);
re.fetch();
auto tplist = re.dumpTapePools();
std::string tpAdress;
for (auto tpp=tplist.begin(); tpp!=tplist.end(); tpp++)
if (tpp->tapePool == tapePool)
tpAdress = tpp->address;
if (!tpAdress.size())
throw NoSuchTapePool("In OStoreDB::TapeMountDecisionInfo::createArchiveMount:"
" tape pool not found");
objectstore::TapePool tp(tpAdress, m_objectStore);
objectstore::ScopedSharedLock tpl(tp);
tp.fetch();
auto tlist = tp.dumpTapes();
std::string tAddress;
for (auto tptr = tlist.begin(); tptr!=tlist.end(); tptr++) {
if (tptr->vid == vid)
tAddress = tptr->address;
}
if (!tAddress.size())
throw NoSuchTape("In OStoreDB::TapeMountDecisionInfo::createArchiveMount:"
" tape not found");
objectstore::Tape t(tAddress, m_objectStore);
objectstore::ScopedExclusiveLock tlock(t);
t.fetch();
if (t.isFull())
throw TapeNotWritable("In OStoreDB::TapeMountDecisionInfo::createArchiveMount:"
" the tape is not writable (full)");
if (t.isArchived())
throw TapeNotWritable("In OStoreDB::TapeMountDecisionInfo::createArchiveMount:"
" the tape is not writable (archived)");
if (t.isReadOnly())
throw TapeNotWritable("In OStoreDB::TapeMountDecisionInfo::createArchiveMount:"
" the tape is not writable (readonly)");
if (t.isDisabled())
throw TapeNotWritable("In OStoreDB::TapeMountDecisionInfo::createArchiveMount:"
" the tape is not writable (disabled)");
if (t.isBusy())
throw TapeIsBusy("In OStoreDB::TapeMountDecisionInfo::createArchiveMount:"
" the tape is busy");
// This tape seems fine for our purposes. We will set it as an owned object
// so that garbage collection can release the tape in case of a session crash
t.setBusy(driveName, objectstore::Tape::MountType::Archive, hostName, startTime,
m_agent.getAddressIfSet());
}
throw NotImplemented("Not Implemented");
}
}
OStoreDB::TapeMountDecisionInfo::TapeMountDecisionInfo(
objectstore::Backend& os, objectstore::Agent& a):
m_objectStore(os), m_agent(a) {}
std::unique_ptr<SchedulerDatabase::RetrieveMount>
OStoreDB::TapeMountDecisionInfo::createRetrieveMount(
......@@ -1061,5 +1135,13 @@ OStoreDB::TapeMountDecisionInfo::~TapeMountDecisionInfo() {
m_schedulerGlobalLock.reset(NULL);
}
OStoreDB::ArchiveMount::ArchiveMount(objectstore::Backend& os, objectstore::Agent& a):
m_objectStore(os), m_agent(a) {}
const SchedulerDatabase::ArchiveMount::MountInfo& OStoreDB::ArchiveMount::getMountInfo() {
return m_mountInfo;
}
}
......@@ -47,18 +47,37 @@ public:
class TapeMountDecisionInfo: public SchedulerDatabase::TapeMountDecisionInfo {
friend class OStoreDB;
public:
virtual std::unique_ptr<SchedulerDatabase::ArchiveMount> createArchiveMount(const std::string & vid,
const std::string driveName);
CTA_GENERATE_EXCEPTION_CLASS(SchedulingLockNotHeld);
CTA_GENERATE_EXCEPTION_CLASS(TapeNotWritable);
CTA_GENERATE_EXCEPTION_CLASS(TapeIsBusy);
virtual std::unique_ptr<SchedulerDatabase::ArchiveMount> createArchiveMount(
const std::string & vid, const std::string & tapePool,
const std::string driveName, const std::string & hostName, time_t startTime);
virtual std::unique_ptr<SchedulerDatabase::RetrieveMount> createRetrieveMount(const std::string & vid,
const std::string driveName);
virtual ~TapeMountDecisionInfo();
private:
TapeMountDecisionInfo (objectstore::Backend &, objectstore::Agent &);
bool m_lockTaken;
objectstore::ScopedExclusiveLock m_lockOnSchedulerGlobalLock;
std::unique_ptr<objectstore::SchedulerGlobalLock> m_schedulerGlobalLock;
objectstore::Backend & m_objectStore;
objectstore::Agent & m_agent;
};
virtual std::unique_ptr<SchedulerDatabase::TapeMountDecisionInfo> getMountInfo();
/* === Mount handling ===================================================== */
class ArchiveMount: public SchedulerDatabase::ArchiveMount {
friend class TapeMountDecisionInfo;
private:
ArchiveMount(objectstore::Backend &, objectstore::Agent &);
objectstore::Backend & m_objectStore;
objectstore::Agent & m_agent;
MountInfo m_mountInfo;
public:
virtual const MountInfo & getMountInfo();
};
/* === Admin host handling ================================================ */
virtual void createAdminHost(const std::string& hostName,
......
......@@ -150,7 +150,16 @@ public:
/**
* The class used by the scheduler database to track the archive mounts
*/
class ArchiveMount {};
class ArchiveMount {
public:
struct MountInfo {
std::string vid;
std::string tapePool;
std::string drive;
uint64_t mountId;
};
virtual const MountInfo & getMountInfo() = 0;
};
class ArchiveJob {
friend class ArchiveMount;
......@@ -284,7 +293,8 @@ public:
* lock.
*/
virtual std::unique_ptr<ArchiveMount> createArchiveMount(const std::string & vid,
const std::string driveName) = 0;
const std::string & tapePool, const std::string driveName,
const std::string & hostName, time_t startTime) = 0;
/**
* Create a new retrieve mount. This implicitly releases the global scheduling
* lock.
......
......@@ -568,6 +568,40 @@ TEST_P(SchedulerDatabaseTest, getMountInfo) {
}
}
TEST_P(SchedulerDatabaseTest, createArchiveMountAndGetJob) {
using namespace cta;
SchedulerDatabase &db = getDb();
// Populate the database with an archive mount
{
// Log for following creations
cta::CreationLog cl(UserIdentity(789,101112), "client0", time(NULL), "Unit test archive request creation");
// Create tape pools
db.createTapePool("pool0", 5, cl);
db.createTapePool("pool1", 5, cl);
// Add a valid job to the queue
cta::UserIdentity remoteOwner (123,546);
cta::RemoteFileStatus remoteStatus(remoteOwner, 0744, 1234);
cta::RemotePath remotePath ("root://myeos/myfile");
cta::RemotePathAndStatus remoteFile(remotePath, remoteStatus);
std::map<uint16_t, std::string> destinationPoolMap;
destinationPoolMap[0] = "pool0";
destinationPoolMap[1] = "pool1";
cta::ArchiveToFileRequest atfr(remoteFile, "cta://cta/myfile", destinationPoolMap,
10, cl);
std::unique_ptr<cta::SchedulerDatabase::ArchiveToFileRequestCreation> creation(db.queue(atfr));
creation->complete();
}
// The archive mount's unique_ptr
std::unique_ptr<SchedulerDatabase::ArchiveMount> archiveMount;
{
auto mountInfo = db.getMountInfo();
ASSERT_NO_THROW(archiveMount = mountInfo->createArchiveMount("Tape1", "pool1", "drive1",
"host1", time(NULL)));
}
}
#undef TEST_MOCK_DB
#ifdef TEST_MOCK_DB
static cta::MockSchedulerDatabaseFactory mockDbFactory;
......
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