From 8a1d11873fed2e8cdf70d9868fd252ee14d704e2 Mon Sep 17 00:00:00 2001
From: Jorge Camarero Vera <jorge.camarero@cern.ch>
Date: Wed, 21 Jul 2021 17:06:42 +0200
Subject: [PATCH] Solve problem with tape daemon

---
 catalogue/RdbmsCatalogue.cpp      |  14 ++--
 scheduler/OStoreDB/OStoreDB.cpp   |   4 +-
 scheduler/Scheduler.cpp           |   5 ++
 tapeserver/daemon/DriveConfig.cpp | 121 +++++++++++++++++-------------
 tapeserver/daemon/DriveConfig.hpp |  12 +--
 tapeserver/daemon/TapeDaemon.cpp  |  14 ++--
 6 files changed, 98 insertions(+), 72 deletions(-)

diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp
index 03fc56be46..c8dc39a4d3 100644
--- a/catalogue/RdbmsCatalogue.cpp
+++ b/catalogue/RdbmsCatalogue.cpp
@@ -9286,11 +9286,11 @@ void RdbmsCatalogue::settingSqlTapeDriveValues(cta::rdbms::Stmt *stmt,
   setOptionalString(":NEXT_VO", tapeDrive.nextVo);
   setOptionalString(":USER_COMMENT", tapeDrive.userComment);
 
-  auto setEntryLog = [stmt](const std::string &field, const std::string &username,
+  auto setEntryLog = [stmt, setOptionalString, setOptionalUint64](const std::string &field, const std::string &username,
     const std::string &host, const time_t &time) {
-      stmt->bindString(field + "_USER_NAME", username);
-      stmt->bindString(field + "_HOST_NAME", host);
-      stmt->bindUint64(field + "_TIME", time);
+      setOptionalString(field + "_USER_NAME", username);
+      setOptionalString(field + "_HOST_NAME", host);
+      setOptionalUint64(field + "_TIME", time);
   };
 
   if (tapeDrive.creationLog) {
@@ -9621,7 +9621,11 @@ void RdbmsCatalogue::createDriveConfig(const std::string &tapeDriveName, const s
     stmt.bindString(":DRIVE_NAME", tapeDriveName);
     stmt.bindString(":CATEGORY", category);
     stmt.bindString(":KEY_NAME", keyName);
-    stmt.bindString(":VALUE", value);
+    if (value.empty()) {
+      stmt.bindString(":VALUE", std::string("NULL"));
+    } else {
+      stmt.bindString(":VALUE", value);
+    }
     stmt.bindString(":SOURCE", source);
 
     stmt.executeNonQuery();
diff --git a/scheduler/OStoreDB/OStoreDB.cpp b/scheduler/OStoreDB/OStoreDB.cpp
index ca4161ecd3..95d9c04db2 100644
--- a/scheduler/OStoreDB/OStoreDB.cpp
+++ b/scheduler/OStoreDB/OStoreDB.cpp
@@ -3296,7 +3296,9 @@ void OStoreDB::updateDriveStatus(const common::dataStructures::DriveInfo& driveI
   }
   ds.commit();
   // DataBase NEW
-  auto tapeDriveStatus = m_catalogue.getTapeDrive(driveInfo.driveName).value();
+  auto tapeDriveToUpdate = m_catalogue.getTapeDrive(driveInfo.driveName);
+  if (!tapeDriveToUpdate) return;
+  auto tapeDriveStatus = tapeDriveToUpdate.value();
   tapeDriveStatus.driveName = driveInfo.driveName;
   tapeDriveStatus.host = driveInfo.host;
   tapeDriveStatus.logicalLibrary = driveInfo.logicalLibrary;
diff --git a/scheduler/Scheduler.cpp b/scheduler/Scheduler.cpp
index 891a1beaf5..44b2cbb970 100644
--- a/scheduler/Scheduler.cpp
+++ b/scheduler/Scheduler.cpp
@@ -882,6 +882,11 @@ void Scheduler::createTapeDriveStatus(const common::dataStructures::DriveInfo& d
   const common::dataStructures::DriveStatus& status, const tape::daemon::TpconfigLine& tpConfigLine,
   const common::dataStructures::SecurityIdentity& identity, log::LogContext & lc) {
   const auto tapeDriveStatus = setTapeDriveStatus(driveInfo, desiredState, type, status, tpConfigLine, identity);
+  auto driveNames = m_catalogue.getTapeDriveNames();
+  auto it = std::find(driveNames.begin(), driveNames.end(), tapeDriveStatus.driveName);
+  if (it != driveNames.end()) {
+    m_catalogue.deleteTapeDrive(tapeDriveStatus.driveName);
+  }
   m_catalogue.createTapeDrive(tapeDriveStatus);
   log::ScopedParamContainer spc(lc);
   spc.add("drive", driveInfo.driveName);
diff --git a/tapeserver/daemon/DriveConfig.cpp b/tapeserver/daemon/DriveConfig.cpp
index 904bd1f4ae..0109c5837f 100644
--- a/tapeserver/daemon/DriveConfig.cpp
+++ b/tapeserver/daemon/DriveConfig.cpp
@@ -15,7 +15,9 @@
  *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <algorithm>
 #include <string>
+#include <utility>
 
 #include "DriveConfig.hpp"
 #include "tapeserver/daemon/FetchReportOrFlushLimits.hpp"
@@ -29,75 +31,86 @@ void DriveConfig::setTapedConfiguration(const cta::tape::daemon::TapedConfigurat
   const std::unique_ptr<catalogue::Catalogue>& catalogue, const std::string& tapeDriveName) {
   cta::tape::daemon::TapedConfiguration * config = const_cast<cta::tape::daemon::TapedConfiguration*>(&tapedConfiguration);
 
-  setConfigToDB(config->daemonUserName, catalogue, tapeDriveName);
-  setConfigToDB(config->daemonGroupName, catalogue, tapeDriveName);
-  setConfigToDB(config->logMask, catalogue, tapeDriveName);
-  setConfigToDB(config->tpConfigPath, catalogue, tapeDriveName);
-  setConfigToDB(config->bufferSizeBytes, catalogue, tapeDriveName);
-  setConfigToDB(config->bufferCount, catalogue, tapeDriveName);
-  setConfigToDB(config->archiveFetchBytesFiles, catalogue, tapeDriveName);
-  setConfigToDB(config->archiveFlushBytesFiles, catalogue, tapeDriveName);
-  setConfigToDB(config->retrieveFetchBytesFiles, catalogue, tapeDriveName);
-  setConfigToDB(config->mountCriteria, catalogue, tapeDriveName);
-  setConfigToDB(config->nbDiskThreads, catalogue, tapeDriveName);
-  setConfigToDB(config->useRAO, catalogue, tapeDriveName);
-  setConfigToDB(config->raoLtoAlgorithm, catalogue, tapeDriveName);
-  setConfigToDB(config->raoLtoOptions, catalogue, tapeDriveName);
-  setConfigToDB(config->wdScheduleMaxSecs, catalogue, tapeDriveName);
-  setConfigToDB(config->wdMountMaxSecs, catalogue, tapeDriveName);
-  setConfigToDB(config->wdNoBlockMoveMaxSecs, catalogue, tapeDriveName);
-  setConfigToDB(config->wdIdleSessionTimer, catalogue, tapeDriveName);
-  setConfigToDB(config->backendPath, catalogue, tapeDriveName);
-  setConfigToDB(config->fileCatalogConfigFile, catalogue, tapeDriveName);
-  setConfigToDB(config->authenticationProtocol, catalogue, tapeDriveName);
-  setConfigToDB(config->authenticationSSSKeytab, catalogue, tapeDriveName);
-  setConfigToDB(config->disableRepackManagement, catalogue, tapeDriveName);
-  setConfigToDB(config->disableMaintenanceProcess, catalogue, tapeDriveName);
-  setConfigToDB(config->fetchEosFreeSpaceScript, catalogue, tapeDriveName);
-  setConfigToDB(config->tapeLoadTimeout, catalogue, tapeDriveName);
+  setConfigToDB(&config->daemonUserName, catalogue, tapeDriveName);
+  setConfigToDB(&config->daemonGroupName, catalogue, tapeDriveName);
+  setConfigToDB(&config->logMask, catalogue, tapeDriveName);
+  setConfigToDB(&config->tpConfigPath, catalogue, tapeDriveName);
+  setConfigToDB(&config->bufferSizeBytes, catalogue, tapeDriveName);
+  setConfigToDB(&config->bufferCount, catalogue, tapeDriveName);
+  setConfigToDB(&config->archiveFetchBytesFiles, catalogue, tapeDriveName);
+  setConfigToDB(&config->archiveFlushBytesFiles, catalogue, tapeDriveName);
+  setConfigToDB(&config->retrieveFetchBytesFiles, catalogue, tapeDriveName);
+  setConfigToDB(&config->mountCriteria, catalogue, tapeDriveName);
+  setConfigToDB(&config->nbDiskThreads, catalogue, tapeDriveName);
+  setConfigToDB(&config->useRAO, catalogue, tapeDriveName);
+  setConfigToDB(&config->raoLtoAlgorithm, catalogue, tapeDriveName);
+  setConfigToDB(&config->raoLtoOptions, catalogue, tapeDriveName);
+  setConfigToDB(&config->wdScheduleMaxSecs, catalogue, tapeDriveName);
+  setConfigToDB(&config->wdMountMaxSecs, catalogue, tapeDriveName);
+  setConfigToDB(&config->wdNoBlockMoveMaxSecs, catalogue, tapeDriveName);
+  setConfigToDB(&config->wdIdleSessionTimer, catalogue, tapeDriveName);
+  setConfigToDB(&config->backendPath, catalogue, tapeDriveName);
+  setConfigToDB(&config->fileCatalogConfigFile, catalogue, tapeDriveName);
+  setConfigToDB(&config->authenticationProtocol, catalogue, tapeDriveName);
+  setConfigToDB(&config->authenticationSSSKeytab, catalogue, tapeDriveName);
+  setConfigToDB(&config->disableRepackManagement, catalogue, tapeDriveName);
+  setConfigToDB(&config->disableMaintenanceProcess, catalogue, tapeDriveName);
+  setConfigToDB(&config->fetchEosFreeSpaceScript, catalogue, tapeDriveName);
+  setConfigToDB(&config->tapeLoadTimeout, catalogue, tapeDriveName);
 }
 
-void DriveConfig::setConfigToDB(cta::SourcedParameter<std::string>& sourcedParameter,
-  const std::unique_ptr<catalogue::Catalogue>& catalogue, const std::string& tapeDriveName) {
-  cta::SourcedParameter<std::string> * param = const_cast<cta::SourcedParameter<std::string>*>(&sourcedParameter);
-  catalogue->createDriveConfig(tapeDriveName, param->category(), param->key(),
-    param->value(), param->source());
+void DriveConfig::checkConfigInDB(const std::unique_ptr<catalogue::Catalogue>& catalogue,
+  const std::string& tapeDriveName, const std::string& key) {
+  auto namesAndKeys = catalogue->getDriveConfigNamesAndKeys();
+  auto it = std::find_if(namesAndKeys.begin(), namesAndKeys.end(),
+    [&tapeDriveName, &key](const std::pair<std::string, std::string>& element) {
+      return element.first == tapeDriveName && element.second == key;
+    });
+  if (it != namesAndKeys.end()) {
+    catalogue->deleteDriveConfig(tapeDriveName, key);
+  }
 }
 
-void DriveConfig::setConfigToDB(cta::SourcedParameter<cta::tape::daemon::FetchReportOrFlushLimits>& sourcedParameter,
+void DriveConfig::setConfigToDB(cta::SourcedParameter<std::string>* sourcedParameter,
   const std::unique_ptr<catalogue::Catalogue>& catalogue, const std::string& tapeDriveName) {
-  cta::SourcedParameter<cta::tape::daemon::FetchReportOrFlushLimits> * param = const_cast<cta::SourcedParameter<
-    cta::tape::daemon::FetchReportOrFlushLimits>*>(&sourcedParameter);
+  checkConfigInDB(catalogue, tapeDriveName, sourcedParameter->key());
+  catalogue->createDriveConfig(tapeDriveName, sourcedParameter->category(), sourcedParameter->key(),
+    sourcedParameter->value(), sourcedParameter->source());
+}
 
-  std::string key = param->key();
-  cta::utils::searchAndReplace(key,"Bytes","");
-  cta::utils::searchAndReplace(key,"Files","");
-  catalogue->createDriveConfig(tapeDriveName, param->category(), key.append("Files"),
-    std::to_string(param->value().maxFiles), param->source());
-  cta::utils::searchAndReplace(key,"Files","");
-  catalogue->createDriveConfig(tapeDriveName, param->category(), key.append("Bytes"),
-    std::to_string(param->value().maxBytes), param->source());
+void DriveConfig::setConfigToDB(cta::SourcedParameter<cta::tape::daemon::FetchReportOrFlushLimits>* sourcedParameter,
+  const std::unique_ptr<catalogue::Catalogue>& catalogue, const std::string& tapeDriveName) {
+  std::string key = sourcedParameter->key();
+  cta::utils::searchAndReplace(key, "Bytes", "");
+  cta::utils::searchAndReplace(key, "Files", "");
+  checkConfigInDB(catalogue, tapeDriveName, key.append("Files"));
+  catalogue->createDriveConfig(tapeDriveName, sourcedParameter->category(), key,
+    std::to_string(sourcedParameter->value().maxFiles), sourcedParameter->source());
+  cta::utils::searchAndReplace(key, "Files", "");
+  checkConfigInDB(catalogue, tapeDriveName, key.append("Bytes"));
+  catalogue->createDriveConfig(tapeDriveName, sourcedParameter->category(), key,
+    std::to_string(sourcedParameter->value().maxBytes), sourcedParameter->source());
 }
 
-void DriveConfig::setConfigToDB(cta::SourcedParameter<uint32_t>& sourcedParameter,
+void DriveConfig::setConfigToDB(cta::SourcedParameter<uint32_t>* sourcedParameter,
   const std::unique_ptr<catalogue::Catalogue>& catalogue, const std::string& tapeDriveName) {
-  cta::SourcedParameter<uint32_t> * param = const_cast<cta::SourcedParameter<uint32_t>*>(&sourcedParameter);
-  catalogue->createDriveConfig(tapeDriveName, param->category(), param->key(),
-    std::to_string(param->value()), param->source());
+  checkConfigInDB(catalogue, tapeDriveName, sourcedParameter->key());
+  catalogue->createDriveConfig(tapeDriveName, sourcedParameter->category(), sourcedParameter->key(),
+    std::to_string(sourcedParameter->value()), sourcedParameter->source());
 }
 
-void DriveConfig::setConfigToDB(cta::SourcedParameter<uint64_t>& sourcedParameter,
+void DriveConfig::setConfigToDB(cta::SourcedParameter<uint64_t>* sourcedParameter,
   const std::unique_ptr<catalogue::Catalogue>& catalogue, const std::string& tapeDriveName) {
-  cta::SourcedParameter<uint64_t> * param = const_cast<cta::SourcedParameter<uint64_t>*>(&sourcedParameter);
-  catalogue->createDriveConfig(tapeDriveName, param->category(), param->key(),
-    std::to_string(param->value()), param->source());
+  checkConfigInDB(catalogue, tapeDriveName, sourcedParameter->key());
+  catalogue->createDriveConfig(tapeDriveName, sourcedParameter->category(), sourcedParameter->key(),
+    std::to_string(sourcedParameter->value()), sourcedParameter->source());
 }
 
-void DriveConfig::setConfigToDB(cta::SourcedParameter<time_t>& sourcedParameter,
+void DriveConfig::setConfigToDB(cta::SourcedParameter<time_t>* sourcedParameter,
   const std::unique_ptr<catalogue::Catalogue>& catalogue, const std::string& tapeDriveName) {
-  cta::SourcedParameter<time_t> * param = const_cast<cta::SourcedParameter<time_t>*>(&sourcedParameter);
-  catalogue->createDriveConfig(tapeDriveName, param->category(), param->key(),
-    std::to_string(param->value()), param->source());
+  checkConfigInDB(catalogue, tapeDriveName, sourcedParameter->key());
+  catalogue->createDriveConfig(tapeDriveName, sourcedParameter->category(), sourcedParameter->key(),
+    std::to_string(sourcedParameter->value()), sourcedParameter->source());
 }
 
 }  // namespace daemon
diff --git a/tapeserver/daemon/DriveConfig.hpp b/tapeserver/daemon/DriveConfig.hpp
index 982ad151c0..5e4cc41579 100644
--- a/tapeserver/daemon/DriveConfig.hpp
+++ b/tapeserver/daemon/DriveConfig.hpp
@@ -37,15 +37,17 @@ class DriveConfig {
     const std::unique_ptr<catalogue::Catalogue>& catalogue, const std::string& tapeDriveName);
 
  private:
-  static void setConfigToDB(cta::SourcedParameter<std::string>& sourcedParameter,
+  static void checkConfigInDB(const std::unique_ptr<catalogue::Catalogue>& catalogue, const std::string& tapeDriveName,
+    const std::string& key);
+  static void setConfigToDB(cta::SourcedParameter<std::string>* sourcedParameter,
     const std::unique_ptr<catalogue::Catalogue>& catalogue, const std::string& tapeDriveName);
-  static void setConfigToDB(cta::SourcedParameter<cta::tape::daemon::FetchReportOrFlushLimits>& sourcedParameter,
+  static void setConfigToDB(cta::SourcedParameter<cta::tape::daemon::FetchReportOrFlushLimits>* sourcedParameter,
     const std::unique_ptr<catalogue::Catalogue>& catalogue, const std::string& tapeDriveName);
-  static void setConfigToDB(cta::SourcedParameter<std::uint32_t>& sourcedParameter,
+  static void setConfigToDB(cta::SourcedParameter<std::uint32_t>* sourcedParameter,
     const std::unique_ptr<catalogue::Catalogue>& catalogue, const std::string& tapeDriveName);
-  static void setConfigToDB(cta::SourcedParameter<std::uint64_t>& sourcedParameter,
+  static void setConfigToDB(cta::SourcedParameter<std::uint64_t>* sourcedParameter,
     const std::unique_ptr<catalogue::Catalogue>& catalogue, const std::string& tapeDriveName);
-  static void setConfigToDB(cta::SourcedParameter<std::time_t>& sourcedParameter,
+  static void setConfigToDB(cta::SourcedParameter<std::time_t>* sourcedParameter,
     const std::unique_ptr<catalogue::Catalogue>& catalogue, const std::string& tapeDriveName);
 };  // class DriveConfig
 
diff --git a/tapeserver/daemon/TapeDaemon.cpp b/tapeserver/daemon/TapeDaemon.cpp
index 4b31c39fb0..bc4dbd0b7a 100644
--- a/tapeserver/daemon/TapeDaemon.cpp
+++ b/tapeserver/daemon/TapeDaemon.cpp
@@ -29,13 +29,13 @@
 
 namespace cta { namespace tape { namespace daemon {
 
-TapeDaemon::TapeDaemon(const cta::daemon::CommandLineParams & commandLine, 
-    log::Logger& log, 
-    const TapedConfiguration& globalConfig, 
-    cta::server::ProcessCap& capUtils): 
+TapeDaemon::TapeDaemon(const cta::daemon::CommandLineParams & commandLine,
+    log::Logger& log,
+    const TapedConfiguration& globalConfig,
+    cta::server::ProcessCap& capUtils):
     cta::server::Daemon(log),
     m_globalConfiguration(globalConfig), m_capUtils(capUtils),
-    m_programName("cta-taped"), m_hostName(getHostName()) { 
+    m_programName("cta-taped"), m_hostName(getHostName()) {
   setCommandLineHasBeenParsed(commandLine.foreground);
 }
 
@@ -89,7 +89,7 @@ void  cta::tape::daemon::TapeDaemon::exceptionThrowingMain()  {
   // however the process should still be permitted to perform raw IO in the
   // future
   setProcessCapabilities("cap_sys_rawio+p");
-  
+
   // Set the name of the (unique) thread for easy process identification.
   prctl(PR_SET_NAME, "cta-tpd-master");
   mainEventLoop();
@@ -150,7 +150,7 @@ void cta::tape::daemon::TapeDaemon::setProcessCapabilities(
   const std::string &text) {
   try {
     m_capUtils.setProcText(text);
-    m_log(log::INFO, "Set process capabilities", 
+    m_log(log::INFO, "Set process capabilities",
       {{"capabilities", m_capUtils.getProcText()}});
   } catch(cta::exception::Exception &ne) {
     cta::exception::Exception ex;
-- 
GitLab