From dd438e394193b5d850b4924aab05fa99f72d8a72 Mon Sep 17 00:00:00 2001
From: Steven Murray <Steven.Murray@cern.ch>
Date: Mon, 29 Jan 2018 17:27:22 +0100
Subject: [PATCH] cta/CTA#186 CTA should cope with idle database connections
 being dropped by the database server

RdbmsCatalogue::tapeMountedForRetrieve() should re-connect to database if connection lost.
---
 catalogue/RdbmsCatalogue.cpp | 28 ++++++++++++++++++++++++++++
 catalogue/RdbmsCatalogue.hpp | 15 +++++++++++++++
 2 files changed, 43 insertions(+)

diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp
index ce083caed4..b0ede92245 100644
--- a/catalogue/RdbmsCatalogue.cpp
+++ b/catalogue/RdbmsCatalogue.cpp
@@ -2248,6 +2248,32 @@ void RdbmsCatalogue::tapeMountedForArchiveInternal(const std::string &vid, const
 // tapeMountedForRetrieve
 //------------------------------------------------------------------------------
 void RdbmsCatalogue::tapeMountedForRetrieve(const std::string &vid, const std::string &drive) {
+  const uint32_t maxTries = 3;
+
+  for(uint32_t tryNb = 1; tryNb <= maxTries; tryNb++) {
+    try {
+      return tapeMountedForRetrieveInternal(vid, drive);
+    } catch(exception::LostDatabaseConnection &lc) {
+      // Ignore lost connection
+      std::list<log::Param> params = {
+        {"maxTries", maxTries},
+        {"tryNb", tryNb},
+        {"msg", lc.getMessage()}
+      };
+      m_log(cta::log::WARNING, "Lost database connection", params);
+    }
+  }
+
+  exception::Exception ex;
+  ex.getMessage() << std::string(__FUNCTION__) << " failed: Lost the database connection after trying " << maxTries <<
+    " times";
+  throw ex;
+}
+
+//------------------------------------------------------------------------------
+// tapeMountedForRetrieveInternal
+//------------------------------------------------------------------------------
+void RdbmsCatalogue::tapeMountedForRetrieveInternal(const std::string &vid, const std::string &drive) {
   try {
     const time_t now = time(nullptr);
     const char *const sql =
@@ -2266,6 +2292,8 @@ void RdbmsCatalogue::tapeMountedForRetrieve(const std::string &vid, const std::s
     if(0 == stmt.getNbAffectedRows()) {
       throw exception::UserError(std::string("Cannot modify tape ") + vid + " because it does not exist");
     }
+  } catch(exception::LostDatabaseConnection &) {
+    throw;
   } catch(exception::UserError &) {
     throw;
   } catch (exception::Exception &ex) {
diff --git a/catalogue/RdbmsCatalogue.hpp b/catalogue/RdbmsCatalogue.hpp
index c020a25683..391cdea5e7 100644
--- a/catalogue/RdbmsCatalogue.hpp
+++ b/catalogue/RdbmsCatalogue.hpp
@@ -1020,6 +1020,21 @@ protected:
    */
   void tapeMountedForArchiveInternal(const std::string &vid, const std::string &drive);
 
+  /**
+   * Notifies the CTA catalogue that the specified tape has been mounted in
+   * order to retrieve files.
+   *
+   * The purpose of this method is to keep track of which drive mounted a given
+   * tape for retrieving files last.
+   *
+   * This internal method can be re-tried if it throws a LostDatabaseConnection
+   * exception.
+   *
+   * @param vid The volume identifier of the tape.
+   * @param drive The name of the drive where the tape was mounted.
+   */
+  void tapeMountedForRetrieveInternal(const std::string &vid, const std::string &drive);
+
   /**
    * Prepares the catalogue for a new archive file and returns the information
    * required to queue the associated archive request.
-- 
GitLab