From 44b627de918be1bda77e02880e4fb394fcaff03b Mon Sep 17 00:00:00 2001
From: Eric Cano <Eric.Cano@cern.ch>
Date: Tue, 15 Sep 2015 19:02:36 +0200
Subject: [PATCH] Implemented the completion of the archive mount.

---
 scheduler/ArchiveMount.cpp      | 13 ++++++++++---
 scheduler/ArchiveMount.hpp      |  6 ++++++
 scheduler/OStoreDB/OStoreDB.cpp | 31 +++++++++++++++++++++++++++++++
 scheduler/OStoreDB/OStoreDB.hpp |  1 +
 scheduler/Scheduler.cpp         |  1 +
 scheduler/SchedulerDatabase.hpp |  2 ++
 6 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/scheduler/ArchiveMount.cpp b/scheduler/ArchiveMount.cpp
index d9c2ba614d..4c68792b9e 100644
--- a/scheduler/ArchiveMount.cpp
+++ b/scheduler/ArchiveMount.cpp
@@ -21,14 +21,15 @@
 //------------------------------------------------------------------------------
 // constructor
 //------------------------------------------------------------------------------
-cta::ArchiveMount::ArchiveMount(NameServer & ns): m_ns(ns) {
+cta::ArchiveMount::ArchiveMount(NameServer & ns): m_ns(ns), m_sessionRunning(false){
 }
 
 //------------------------------------------------------------------------------
 // constructor
 //------------------------------------------------------------------------------
 cta::ArchiveMount::ArchiveMount(NameServer & ns,
-  std::unique_ptr<SchedulerDatabase::ArchiveMount> dbMount): m_ns(ns) {
+  std::unique_ptr<SchedulerDatabase::ArchiveMount> dbMount): m_ns(ns), 
+    m_sessionRunning(false) {
   m_dbMount.reset(
     dynamic_cast<SchedulerDatabase::ArchiveMount*>(dbMount.release()));
   if(!m_dbMount.get()) {
@@ -83,6 +84,9 @@ std::string cta::ArchiveMount::getMountTransactionId() const throw(){
 // getNextJob
 //------------------------------------------------------------------------------
 std::unique_ptr<cta::ArchiveJob> cta::ArchiveMount::getNextJob() {
+  // Check we are still running the session
+  if (!m_sessionRunning)
+    throw SessionNotRunning("In ArchiveMount::getNextJob(): trying to get job from complete/not started session");
   // try and get a new job from the DB side
   std::unique_ptr<cta::SchedulerDatabase::ArchiveJob> dbJob(m_dbMount->getNextJob().release());
   if (!dbJob.get())
@@ -98,7 +102,10 @@ std::unique_ptr<cta::ArchiveJob> cta::ArchiveMount::getNextJob() {
 // complete
 //------------------------------------------------------------------------------
 void cta::ArchiveMount::complete() {
-  throw NotImplemented(std::string(__FUNCTION__) + ": Not implemented");
+  // Just set the session as complete in the DB.
+  m_dbMount->complete(time(NULL));
+  // and record we are done with the mount
+  m_sessionRunning = false;
 }
 
 //------------------------------------------------------------------------------
diff --git a/scheduler/ArchiveMount.hpp b/scheduler/ArchiveMount.hpp
index 42301a1019..6b70df7901 100644
--- a/scheduler/ArchiveMount.hpp
+++ b/scheduler/ArchiveMount.hpp
@@ -92,6 +92,7 @@ namespace cta {
      */
     virtual void complete();
 
+    CTA_GENERATE_EXCEPTION_CLASS(SessionNotRunning);
     /**
      * Job factory
      *
@@ -131,6 +132,11 @@ namespace cta {
      */
     NameServer & m_ns;
 
+    /**
+     * Internal tracking of the session completion
+     */
+    bool m_sessionRunning;
+    
   }; // class ArchiveMount
 
 } // namespace cta
diff --git a/scheduler/OStoreDB/OStoreDB.cpp b/scheduler/OStoreDB/OStoreDB.cpp
index 5e00119d2e..8a1ac13484 100644
--- a/scheduler/OStoreDB/OStoreDB.cpp
+++ b/scheduler/OStoreDB/OStoreDB.cpp
@@ -1090,6 +1090,7 @@ std::unique_ptr<SchedulerDatabase::ArchiveMount>
   am.mountInfo.vid = vid;
   am.mountInfo.drive = driveName;
   am.mountInfo.tapePool = tapePool;
+  am.mountInfo.logicalLibrary = logicalLibrary;
   am.m_nextFseq = std::numeric_limits<decltype(am.m_nextFseq)>::max();
   objectstore::RootEntry re(m_objectStore);
   objectstore::ScopedSharedLock rel(re);
@@ -1275,6 +1276,36 @@ auto OStoreDB::ArchiveMount::getNextJob() -> std::unique_ptr<SchedulerDatabase::
   return std::unique_ptr<SchedulerDatabase::ArchiveJob> (NULL);
 }
 
+void OStoreDB::ArchiveMount::complete(time_t completionTime) {
+  // When the session is complete, we can reset the status of the tape and the
+  // drive
+  // Reset the drive
+  objectstore::RootEntry re(m_objectStore);
+  objectstore::ScopedSharedLock rel(re);
+  re.fetch();
+  objectstore::DriveRegister dr(re.getDriveRegisterAddress(), m_objectStore);
+  objectstore::ScopedExclusiveLock drl(dr);
+  dr.fetch();
+  // Reset the drive state.
+  dr.reportDriveStatus(mountInfo.drive, mountInfo.logicalLibrary, 
+    objectstore::DriveRegister::DriveStatus::Up, completionTime, 
+    objectstore::DriveRegister::MountType::NoMount, 0,
+    0, 0, 0, "", "");
+  dr.commit();
+  // Find the tape and unbusy it.
+  objectstore::TapePool tp (re.getTapePoolAddress(mountInfo.tapePool), m_objectStore);
+  rel.release();
+  objectstore::ScopedSharedLock tpl(tp);
+  tp.fetch();
+  objectstore::Tape t(tp.getTapeAddress(mountInfo.vid), m_objectStore);
+  objectstore::ScopedExclusiveLock tl(t);
+  tpl.release();
+  t.fetch();
+  t.releaseBusy();
+  t.commit();
+}
+
+
 OStoreDB::ArchiveJob::ArchiveJob(const std::string& jobAddress, 
   objectstore::Backend& os, objectstore::Agent& ag): m_jobOwned(false),
   m_objectStore(os), m_agent(ag), m_atfr(jobAddress, os) {}
diff --git a/scheduler/OStoreDB/OStoreDB.hpp b/scheduler/OStoreDB/OStoreDB.hpp
index eb19459735..8c0e1bf716 100644
--- a/scheduler/OStoreDB/OStoreDB.hpp
+++ b/scheduler/OStoreDB/OStoreDB.hpp
@@ -79,6 +79,7 @@ public:
   public:
     virtual const MountInfo & getMountInfo();
     virtual std::unique_ptr<ArchiveJob> getNextJob();
+    virtual void complete(time_t completionTime);
   };
   
   /* === Archive Job Handling =============================================== */
diff --git a/scheduler/Scheduler.cpp b/scheduler/Scheduler.cpp
index d12fef1840..06c855db49 100644
--- a/scheduler/Scheduler.cpp
+++ b/scheduler/Scheduler.cpp
@@ -857,6 +857,7 @@ std::unique_ptr<cta::TapeMount> cta::Scheduler::getNextMount(
                 logicalLibraryName, 
                 Utils::getShortHostname(), 
                 time(NULL)).release());
+            internalRet->m_sessionRunning = true;
             return std::unique_ptr<TapeMount> (internalRet.release());
           } catch (cta::exception::Exception & ex) {
             continue;
diff --git a/scheduler/SchedulerDatabase.hpp b/scheduler/SchedulerDatabase.hpp
index 30d0ac6dfc..5e5d586e88 100644
--- a/scheduler/SchedulerDatabase.hpp
+++ b/scheduler/SchedulerDatabase.hpp
@@ -162,12 +162,14 @@ public:
   public:
     struct MountInfo {
       std::string vid;
+      std::string logicalLibrary;
       std::string tapePool;
       std::string drive;
       uint64_t mountId;
     } mountInfo;
     virtual const MountInfo & getMountInfo() = 0;
     virtual std::unique_ptr<ArchiveJob> getNextJob() = 0;
+    virtual void complete(time_t completionTime) = 0;
     virtual ~ArchiveMount() {}
   };
   
-- 
GitLab