diff --git a/catalogue/CMakeLists.txt b/catalogue/CMakeLists.txt
index 1e3f20791e90d677d07028b7c736c8ded21786a7..4b077a5654d72b159dc0ec08c21b55be5a1480d0 100644
--- a/catalogue/CMakeLists.txt
+++ b/catalogue/CMakeLists.txt
@@ -25,8 +25,10 @@ set (CATALOGUE_LIB_SRC_FILES
   ArchiveFileItor.cpp
   ArchiveFileItorImpl.cpp
   Catalogue.cpp
+  CatalogueFactory.cpp
   CmdLineTool.cpp
   InMemoryCatalogue.cpp
+  OracleCatalogue.cpp
   SqliteCatalogueSchema.cpp
   TapeFileWritten.cpp
   RdbmsArchiveFileItorImpl.cpp
@@ -35,11 +37,6 @@ set (CATALOGUE_LIB_SRC_FILES
   SqliteCatalogue.cpp
   TapeForWriting.cpp)
 
-set (CATALOGUE_LIB_SRC_FILES
-  ${CATALOGUE_LIB_SRC_FILES}
-  CatalogueFactory.cpp
-  OracleCatalogue.cpp)
-
 add_library (ctacatalogue SHARED
    ${CATALOGUE_LIB_SRC_FILES})
 set_property(TARGET ctacatalogue PROPERTY SOVERSION "${CTA_SOVERSION}")
diff --git a/catalogue/Catalogue.cpp b/catalogue/Catalogue.cpp
index b958c14715ea9db3cfd5120fc646a7bd485a1536..a0866c30ba3a4f2894d03a13d37c25d1b4c554b3 100644
--- a/catalogue/Catalogue.cpp
+++ b/catalogue/Catalogue.cpp
@@ -21,12 +21,6 @@
 namespace cta {
 namespace catalogue {
 
-//------------------------------------------------------------------------------
-// constructor
-//------------------------------------------------------------------------------
-Catalogue::Catalogue(log::Logger &log): m_log(log) {
-}
-
 //------------------------------------------------------------------------------
 // destructor
 //------------------------------------------------------------------------------
diff --git a/catalogue/Catalogue.hpp b/catalogue/Catalogue.hpp
index bdddd9746c18c8be659fda82ebe079d2f6f1cc5a..49502f95771f9f161f039e93bc88dc43ed83d98f 100644
--- a/catalogue/Catalogue.hpp
+++ b/catalogue/Catalogue.hpp
@@ -77,12 +77,6 @@ namespace catalogue {
  */
 class Catalogue {
 public:
-  /**
-   * Constructor.
-   *
-   * @param log Object representing the API to the CTA logging system.
-   */
-  Catalogue(log::Logger &log);
 
   /**
    * Destructor.
@@ -128,6 +122,7 @@ public:
    * disabled, not full and are in the specified logical library.
    *
    * @param logicalLibraryName The name of the logical library.
+   * @return The list of tapes for writing.
    */
   virtual std::list<TapeForWriting> getTapesForWriting(const std::string &logicalLibraryName) const = 0;
 
@@ -585,13 +580,6 @@ public:
    */
   virtual bool tapeExists(const std::string &vid) const = 0;
 
-protected:
-
-  /**
-   * Object representing the API to the CTA logging system.
-   */
-  log::Logger &m_log;
-
 }; // class Catalogue
 
 } // namespace catalogue
diff --git a/catalogue/CatalogueFactory.cpp b/catalogue/CatalogueFactory.cpp
index 7f16fb1228a589c0d126a1d51bb1cc190eb77fbd..5cceb8b39eb412ede3b2429784ecac86303b03f2 100644
--- a/catalogue/CatalogueFactory.cpp
+++ b/catalogue/CatalogueFactory.cpp
@@ -33,16 +33,18 @@ std::unique_ptr<Catalogue> CatalogueFactory::create(
   log::Logger &log,
   const rdbms::Login &login,
   const uint64_t nbConns,
-  const uint64_t nbArchiveFileListingConns) {
+  const uint64_t nbArchiveFileListingConns,
+  const uint32_t maxTriesToConnect) {
   try {
     switch(login.dbType) {
     case rdbms::Login::DBTYPE_IN_MEMORY:
-      return cta::make_unique<InMemoryCatalogue>(log, nbConns, nbArchiveFileListingConns);
+      return cta::make_unique<InMemoryCatalogue>(log, nbConns, nbArchiveFileListingConns, maxTriesToConnect);
     case rdbms::Login::DBTYPE_ORACLE:
       return cta::make_unique<OracleCatalogue>(log, login.username, login.password, login.database, nbConns,
-        nbArchiveFileListingConns);
+        nbArchiveFileListingConns, maxTriesToConnect);
     case rdbms::Login::DBTYPE_SQLITE:
-      return cta::make_unique<SqliteCatalogue>(log, login.database, nbConns, nbArchiveFileListingConns);
+      return cta::make_unique<SqliteCatalogue>(log, login.database, nbConns, nbArchiveFileListingConns,
+         maxTriesToConnect);
     case rdbms::Login::DBTYPE_NONE:
       throw exception::Exception("Cannot create a catalogue without a database type");
     default:
diff --git a/catalogue/CatalogueFactory.hpp b/catalogue/CatalogueFactory.hpp
index d76d19461b68cc181f8ba81d70c9590cf9aa47e7..7c0cae56b3d15e3852be295900318deb5f8dc7de 100644
--- a/catalogue/CatalogueFactory.hpp
+++ b/catalogue/CatalogueFactory.hpp
@@ -51,12 +51,16 @@ public:
    * listing archive files.
    * @return The newly created CTA catalogue object.  Please note that it is the
    * responsibility of the caller to delete the returned CTA catalogue object.
+   * @param maxTriesToConnext The maximum number of times a single method should
+   * try to connect to the database in the event of LostDatabaseConnection
+   * exceptions being thrown.
    */
   static std::unique_ptr<Catalogue> create(
     log::Logger &log,
     const rdbms::Login &login,
     const uint64_t nbConns,
-    const uint64_t nbArchiveFileListingConns);
+    const uint64_t nbArchiveFileListingConns,
+    const uint32_t maxTriesToConnect = 3);
 
 }; // class CatalogueFactory
 
diff --git a/catalogue/DummyCatalogue.hpp b/catalogue/DummyCatalogue.hpp
index 1e84cf92ad86f38bf87a15faa58e339c9838da4f..008c80c32863c8c744eed87370a5c7b72bb501ec 100644
--- a/catalogue/DummyCatalogue.hpp
+++ b/catalogue/DummyCatalogue.hpp
@@ -31,7 +31,7 @@ namespace catalogue {
  */
 class DummyCatalogue: public Catalogue {
 public:
-  DummyCatalogue(log::Logger &l): Catalogue(l) {}
+  DummyCatalogue() {}
   virtual ~DummyCatalogue() { }
   void createAdminHost(const common::dataStructures::SecurityIdentity& admin, const std::string& hostName, const std::string& comment) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
 
diff --git a/catalogue/InMemoryCatalogue.cpp b/catalogue/InMemoryCatalogue.cpp
index 69eeb195103a9fff734d880278768a63f91c97d6..03af6576982ec2b04ea022c2308ba3cb6340659d 100644
--- a/catalogue/InMemoryCatalogue.cpp
+++ b/catalogue/InMemoryCatalogue.cpp
@@ -27,8 +27,10 @@ namespace catalogue {
 InMemoryCatalogue::InMemoryCatalogue(
   log::Logger &log,
   const uint64_t nbConns,
-  const uint64_t nbArchiveFileListingConns):
-  SchemaCreatingSqliteCatalogue(log, "file::memory:?cache=shared", nbConns, nbArchiveFileListingConns) {
+  const uint64_t nbArchiveFileListingConns,
+  const uint32_t maxTriesToConnect):
+  SchemaCreatingSqliteCatalogue(log, "file::memory:?cache=shared", nbConns, nbArchiveFileListingConns,
+    maxTriesToConnect) {
 }
 
 //------------------------------------------------------------------------------
diff --git a/catalogue/InMemoryCatalogue.hpp b/catalogue/InMemoryCatalogue.hpp
index 6605647dcbc0cde497d75e1ff22c2a29f4a04bdc..06376bd981f3843afb3cd46ca91eebbd4533017a 100644
--- a/catalogue/InMemoryCatalogue.hpp
+++ b/catalogue/InMemoryCatalogue.hpp
@@ -41,11 +41,15 @@ public:
    * @param nbArchiveFileListingConns The maximum number of concurrent
    * connections to the underlying relational database for the sole purpose of
    * listing archive files.
+   * @param maxTriesToConnext The maximum number of times a single method should
+   * try to connect to the database in the event of LostDatabaseConnection
+   * exceptions being thrown.
    */
   InMemoryCatalogue(
     log::Logger &log,
     const uint64_t nbConns,
-    const uint64_t nbArchiveFileListingConns);
+    const uint64_t nbArchiveFileListingConns,
+    const uint32_t maxTriesToConnect);
 
   /**
    * Destructor.
diff --git a/catalogue/InMemoryCatalogueTest.cpp b/catalogue/InMemoryCatalogueTest.cpp
index 51372829814ce52e91bce7ec0f61af8a39b3dca5..24f58e9e0ab47df8a676c100a85c64ba7d2a4156 100644
--- a/catalogue/InMemoryCatalogueTest.cpp
+++ b/catalogue/InMemoryCatalogueTest.cpp
@@ -39,15 +39,16 @@ TEST_F(cta_catalogue_InMemoryCatalogue, createSameSchemaInTwoSeparateInMemoryDat
   log::DummyLogger dummyLog("dummy");
   const uint64_t nbConns = 1;
   const uint64_t nbArchiveFileListingConns = 0;
+  const uint32_t maxTriesToConnect = 1;
 
   // First in-memory database
   {
-    catalogue::InMemoryCatalogue inMemoryCatalogue(dummyLog, nbConns, nbArchiveFileListingConns);
+    catalogue::InMemoryCatalogue inMemoryCatalogue(dummyLog, nbConns, nbArchiveFileListingConns, maxTriesToConnect);
   }
 
   // Second in-memory database
   {
-    catalogue::InMemoryCatalogue inMemoryCatalogue(dummyLog, nbConns, nbArchiveFileListingConns);
+    catalogue::InMemoryCatalogue inMemoryCatalogue(dummyLog, nbConns, nbArchiveFileListingConns, maxTriesToConnect);
   }
 }
 
diff --git a/catalogue/OracleCatalogue.cpp b/catalogue/OracleCatalogue.cpp
index 308baaea692a8ca488bdffec41bd9d66736218c1..d8b6d840bfebf4b61bec5d89eb3968a075a0c2b8 100644
--- a/catalogue/OracleCatalogue.cpp
+++ b/catalogue/OracleCatalogue.cpp
@@ -18,8 +18,10 @@
 
 #include "catalogue/ArchiveFileRow.hpp"
 #include "catalogue/OracleCatalogue.hpp"
-#include "common/exception/UserError.hpp"
+#include "catalogue/retryOnLostConnection.hpp"
 #include "common/exception/Exception.hpp"
+#include "common/exception/LostDatabaseConnection.hpp"
+#include "common/exception/UserError.hpp"
 #include "common/make_unique.hpp"
 #include "common/threading/MutexLocker.hpp"
 #include "common/Timer.hpp"
@@ -118,13 +120,14 @@ OracleCatalogue::OracleCatalogue(
   const std::string &password,
   const std::string &database,
   const uint64_t nbConns,
-  const uint64_t nbArchiveFileListingConns):
+  const uint64_t nbArchiveFileListingConns,
+  const uint32_t maxTriesToConnect):
   RdbmsCatalogue(
     log,
     rdbms::Login(rdbms::Login::DBTYPE_ORACLE, username, password, database),
     nbConns,
-    nbArchiveFileListingConns) {
-
+    nbArchiveFileListingConns,
+    maxTriesToConnect) {
 }
 
 //------------------------------------------------------------------------------
@@ -137,6 +140,15 @@ OracleCatalogue::~OracleCatalogue() {
 // deleteArchiveFile
 //------------------------------------------------------------------------------
 void OracleCatalogue::deleteArchiveFile(const std::string &diskInstanceName, const uint64_t archiveFileId,
+  log::LogContext &lc) {
+  return retryOnLostConnection(m_log, [&]{return deleteArchiveFileInternal(diskInstanceName, archiveFileId, lc);},
+    m_maxTriesToConnect);
+}
+
+//------------------------------------------------------------------------------
+// deleteArchiveFileInternal
+//------------------------------------------------------------------------------
+void OracleCatalogue::deleteArchiveFileInternal(const std::string &diskInstanceName, const uint64_t archiveFileId,
   log::LogContext &lc) {
   try {
     const char *selectSql =
@@ -169,6 +181,7 @@ void OracleCatalogue::deleteArchiveFile(const std::string &diskInstanceName, con
       "FOR UPDATE";
     utils::Timer t;
     auto conn = m_connPool.getConn();
+    rdbms::AutoRollback autoRollback(conn);
     const auto getConnTime = t.secs(utils::Timer::resetCounter);
     auto selectStmt = conn.createStmt(selectSql, rdbms::AutocommitMode::OFF);
     const auto createStmtTime = t.secs();
@@ -315,6 +328,8 @@ void OracleCatalogue::deleteArchiveFile(const std::string &diskInstanceName, con
       spc.add("TAPE FILE", tapeCopyLogStream.str());
     }
     lc.log(log::INFO, "Archive file deleted from CTA catalogue");
+  } catch(exception::LostDatabaseConnection &le) {
+    throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str());
   } catch(exception::UserError &) {
     throw;
   } catch(exception::Exception &ex) {
@@ -327,8 +342,17 @@ void OracleCatalogue::deleteArchiveFile(const std::string &diskInstanceName, con
 //------------------------------------------------------------------------------
 void OracleCatalogue::deleteArchiveFileByDiskFileId(const std::string &diskInstanceName, const std::string &diskFileId,
   log::LogContext &lc) {
+  return retryOnLostConnection(m_log, [&]{return deleteArchiveFileByDiskFileIdInternal(diskInstanceName, diskFileId,
+    lc);}, m_maxTriesToConnect);
+}
+
+//------------------------------------------------------------------------------
+// deleteArchiveFileByDiskFileIdInternal
+//------------------------------------------------------------------------------
+void OracleCatalogue::deleteArchiveFileByDiskFileIdInternal(const std::string &diskInstanceName,
+  const std::string &diskFileId, log::LogContext &lc) {
   try {
-    const char *selectSql =
+    const char *const selectSql =
       "SELECT "
         "ARCHIVE_FILE.ARCHIVE_FILE_ID AS ARCHIVE_FILE_ID,"
         "ARCHIVE_FILE.DISK_INSTANCE_NAME AS DISK_INSTANCE_NAME,"
@@ -465,6 +489,8 @@ void OracleCatalogue::deleteArchiveFileByDiskFileId(const std::string &diskInsta
       spc.add("TAPE FILE", tapeCopyLogStream.str());
     }
     lc.log(log::INFO, "Archive file deleted from CTA catalogue");
+  } catch(exception::LostDatabaseConnection &le) {
+    throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str());
   } catch(exception::UserError &) {
     throw;
   } catch(exception::Exception &ex) {
@@ -591,6 +617,13 @@ common::dataStructures::Tape OracleCatalogue::selectTapeForUpdate(rdbms::Conn &c
 // filesWrittenToTape
 //------------------------------------------------------------------------------
 void OracleCatalogue::filesWrittenToTape(const std::set<TapeFileWritten> &events) {
+  return retryOnLostConnection(m_log, [&]{return filesWrittenToTapeInternal(events);}, m_maxTriesToConnect);
+}
+
+//------------------------------------------------------------------------------
+// filesWrittenToTapeInternal
+//------------------------------------------------------------------------------
+void OracleCatalogue::filesWrittenToTapeInternal(const std::set<TapeFileWritten> &events) {
   try {
     if (events.empty()) {
       return;
@@ -692,6 +725,8 @@ void OracleCatalogue::filesWrittenToTape(const std::set<TapeFileWritten> &events
 
     conn.commit();
 
+  } catch(exception::LostDatabaseConnection &le) {
+    throw exception::LostDatabaseConnection(std::string(__FUNCTION__) +  " failed: " + le.getMessage().str());
   } catch(exception::Exception &ex) {
     throw exception::Exception(std::string(__FUNCTION__) +  " failed: " + ex.getMessage().str());
   } catch(std::exception &se) {
diff --git a/catalogue/OracleCatalogue.hpp b/catalogue/OracleCatalogue.hpp
index 99a404752a8cb398e46e9fb007840298676dc9ce..3823ce0b423bf999ee8bd6a6751545128f81b763 100644
--- a/catalogue/OracleCatalogue.hpp
+++ b/catalogue/OracleCatalogue.hpp
@@ -21,14 +21,9 @@
 #include "catalogue/RdbmsCatalogue.hpp"
 #include "rdbms/Conn.hpp"
 
-#include <occi.h>
-#include <string.h>
-
 namespace cta {
 namespace catalogue {
 
-class CatalogueFactory;
-
 /**
  * An Oracle based implementation of the CTA catalogue.
  */
@@ -48,6 +43,9 @@ public:
    * @param nbArchiveFileListingConns The maximum number of concurrent
    * connections to the underlying relational database for the sole purpose of
    * listing archive files.
+   * @param maxTriesToConnext The maximum number of times a single method should
+   * try to connect to the database in the event of LostDatabaseConnection
+   * exceptions being thrown.
    */
   OracleCatalogue(
     log::Logger       &log,
@@ -55,7 +53,8 @@ public:
     const std::string &password,
     const std::string &database,
     const uint64_t nbConns,
-    const uint64_t nbArchiveFileListingConns);
+    const uint64_t nbArchiveFileListingConns,
+    const uint32_t maxTriesToConnect = 3);
 
   /**
    * Destructor.
@@ -127,6 +126,64 @@ public:
 
 private:
 
+  /**
+   * Deletes the specified archive file and its associated tape copies from the
+   * catalogue.
+   *
+   * Please note that the name of the disk instance is specified in order to
+   * prevent a disk instance deleting an archive file that belongs to another
+   * disk instance.
+   *
+   * Please note that this method is idempotent.  If the file to be deleted does
+   * not exist in the CTA catalogue then this method returns without error.
+   *
+   * This internal method can be re-tried if it throws a LostDatabaseConnection
+   * exception.
+   *
+   * @param instanceName The name of the instance from where the deletion request
+   * originated
+   * @param archiveFileId The unique identifier of the archive file.
+   * @param lc The log context.
+   * @return The metadata of the deleted archive file including the metadata of
+   * the associated and also deleted tape copies.
+   */
+  void deleteArchiveFileInternal(const std::string &diskInstanceName, const uint64_t archiveFileId,
+    log::LogContext &lc);
+
+  /**
+   * Deletes the specified archive file and its associated tape copies from the
+   * catalogue.
+   *
+   * Please note that this method is idempotent.  If the file to be deleted does
+   * not exist in the CTA catalogue then this method returns without error.
+   *
+   * This internal method can be re-tried if it throws a LostDatabaseConnection
+   * exception.
+   *
+   * @param diskInstanceName The name of the instance from where the deletion
+   * request originated
+   * @param diskFileId The identifier of the source disk file which is unique
+   * within it's host disk system.  Two files from different disk systems may
+   * have the same identifier.  The combination of diskInstanceName and
+   * diskFileId must be globally unique, in other words unique within the CTA
+   * catalogue.
+   * @param lc The log context.
+   * @return The metadata of the deleted archive file including the metadata of
+   * the associated and also deleted tape copies.
+   */
+  void deleteArchiveFileByDiskFileIdInternal(const std::string &diskInstanceName, const std::string &diskFileId,
+    log::LogContext &lc);
+
+  /**
+   * Notifies the catalogue that the specified files have been written to tape.
+   *
+   * This internal method can be re-tried if it throws a LostDatabaseConnection
+   * exception.
+   *
+   * @param events The tape file written events.
+   */
+  void filesWrittenToTapeInternal(const std::set<TapeFileWritten> &events);
+
   /**
    * Selects the specified tape within the Tape table for update.
    *
diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp
index 39415e5cc38048cadfcd2f4df3b861df856d6901..cdea6a3a304c45e5ad1722d23782b59c99166e58 100644
--- a/catalogue/RdbmsCatalogue.cpp
+++ b/catalogue/RdbmsCatalogue.cpp
@@ -19,6 +19,7 @@
 #include "catalogue/ArchiveFileRow.hpp"
 #include "catalogue/RdbmsArchiveFileItorImpl.hpp"
 #include "catalogue/RdbmsCatalogue.hpp"
+#include "catalogue/retryOnLostConnection.hpp"
 #include "catalogue/SqliteCatalogueSchema.hpp"
 #include "common/dataStructures/TapeFile.hpp"
 #include "common/exception/Exception.hpp"
@@ -32,6 +33,7 @@
 #include <ctype.h>
 #include <memory>
 #include <time.h>
+#include <common/exception/LostDatabaseConnection.hpp>
 
 namespace cta {
 namespace catalogue {
@@ -43,10 +45,12 @@ RdbmsCatalogue::RdbmsCatalogue(
   log::Logger &log,
   const rdbms::Login &login,
   const uint64_t nbConns,
-  const uint64_t nbArchiveFileListingConns):
-  Catalogue(log),
+  const uint64_t nbArchiveFileListingConns,
+  const uint32_t maxTriesToConnect):
+  m_log(log),
   m_connPool(login, nbConns),
-  m_archiveFileListingConnPool(login, nbArchiveFileListingConns) {
+  m_archiveFileListingConnPool(login, nbArchiveFileListingConns),
+  m_maxTriesToConnect(maxTriesToConnect) {
 }
 
 //------------------------------------------------------------------------------
@@ -2190,6 +2194,13 @@ void RdbmsCatalogue::modifyTapeEncryptionKey(const common::dataStructures::Secur
 // tapeMountedForArchive
 //------------------------------------------------------------------------------
 void RdbmsCatalogue::tapeMountedForArchive(const std::string &vid, const std::string &drive) {
+  return retryOnLostConnection(m_log, [&]{return tapeMountedForArchiveInternal(vid, drive);}, m_maxTriesToConnect);
+}
+
+//------------------------------------------------------------------------------
+// tapeMountedForArchiveInternal
+//------------------------------------------------------------------------------
+void RdbmsCatalogue::tapeMountedForArchiveInternal(const std::string &vid, const std::string &drive) {
   try {
     const time_t now = time(nullptr);
     const char *const sql =
@@ -2205,9 +2216,11 @@ void RdbmsCatalogue::tapeMountedForArchive(const std::string &vid, const std::st
     stmt.bindString(":VID", vid);
     stmt.executeNonQuery();
 
-    if(0 == stmt.getNbAffectedRows()) {
+    if (0 == stmt.getNbAffectedRows()) {
       throw exception::UserError(std::string("Cannot modify tape ") + vid + " because it does not exist");
     }
+  } catch(exception::LostDatabaseConnection &le) {
+    throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + "failed: " + le.getMessage().str());
   } catch(exception::UserError &) {
     throw;
   } catch (exception::Exception &ex) {
@@ -2219,6 +2232,13 @@ void RdbmsCatalogue::tapeMountedForArchive(const std::string &vid, const std::st
 // tapeMountedForRetrieve
 //------------------------------------------------------------------------------
 void RdbmsCatalogue::tapeMountedForRetrieve(const std::string &vid, const std::string &drive) {
+  return retryOnLostConnection(m_log, [&]{return tapeMountedForRetrieveInternal(vid, drive);}, m_maxTriesToConnect);
+}
+
+//------------------------------------------------------------------------------
+// tapeMountedForRetrieveInternal
+//------------------------------------------------------------------------------
+void RdbmsCatalogue::tapeMountedForRetrieveInternal(const std::string &vid, const std::string &drive) {
   try {
     const time_t now = time(nullptr);
     const char *const sql =
@@ -2237,6 +2257,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 &le) {
+    throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + "failed: " + le.getMessage().str());
   } catch(exception::UserError &) {
     throw;
   } catch (exception::Exception &ex) {
@@ -2282,6 +2304,13 @@ void RdbmsCatalogue::setTapeFull(const common::dataStructures::SecurityIdentity
 // noSpaceLeftOnTape
 //------------------------------------------------------------------------------
 void RdbmsCatalogue::noSpaceLeftOnTape(const std::string &vid) {
+  return retryOnLostConnection(m_log, [&]{return noSpaceLeftOnTapeInternal(vid);}, m_maxTriesToConnect);
+}
+
+//------------------------------------------------------------------------------
+// noSpaceLeftOnTapeInternal
+//------------------------------------------------------------------------------
+void RdbmsCatalogue::noSpaceLeftOnTapeInternal(const std::string &vid) {
   try {
     const char *const sql =
       "UPDATE TAPE SET "
@@ -2293,9 +2322,11 @@ void RdbmsCatalogue::noSpaceLeftOnTape(const std::string &vid) {
     stmt.bindString(":VID", vid);
     stmt.executeNonQuery();
 
-    if(0 == stmt.getNbAffectedRows()) {
+    if (0 == stmt.getNbAffectedRows()) {
       throw exception::Exception(std::string("Tape ") + vid + " does not exist");
     }
+  } catch (exception::LostDatabaseConnection &le) {
+    throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str());
   } catch (exception::Exception &ex) {
     throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str());
   }
@@ -3747,6 +3778,13 @@ common::dataStructures::ArchiveFile RdbmsCatalogue::getArchiveFileById(const uin
 // tapeLabelled
 //------------------------------------------------------------------------------
 void RdbmsCatalogue::tapeLabelled(const std::string &vid, const std::string &drive, const bool lbpIsOn) {
+  return retryOnLostConnection(m_log, [&]{return tapeLabelledInternal(vid, drive, lbpIsOn);}, m_maxTriesToConnect);
+}
+
+//------------------------------------------------------------------------------
+// tapeLabelledInternal
+//------------------------------------------------------------------------------
+void RdbmsCatalogue::tapeLabelledInternal(const std::string &vid, const std::string &drive, const bool lbpIsOn) {
   try {
     const time_t now = time(nullptr);
     const char *const sql =
@@ -3767,6 +3805,8 @@ void RdbmsCatalogue::tapeLabelled(const std::string &vid, const std::string &dri
     if(0 == stmt.getNbAffectedRows()) {
       throw exception::UserError(std::string("Cannot modify tape ") + vid + " because it does not exist");
     }
+  } catch(exception::LostDatabaseConnection &le) {
+    throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str());
   } catch(exception::UserError &) {
     throw;
   } catch (exception::Exception &ex) {
@@ -3779,6 +3819,16 @@ void RdbmsCatalogue::tapeLabelled(const std::string &vid, const std::string &dri
 //------------------------------------------------------------------------------
 common::dataStructures::ArchiveFileQueueCriteria RdbmsCatalogue::prepareForNewFile(const std::string &diskInstanceName,
   const std::string &storageClassName, const common::dataStructures::UserIdentity &user) {
+  return retryOnLostConnection( m_log, [&]{return prepareForNewFileInternal(diskInstanceName, storageClassName, user);},
+    m_maxTriesToConnect);
+}
+
+//------------------------------------------------------------------------------
+// prepareForNewFileInternal
+//------------------------------------------------------------------------------
+common::dataStructures::ArchiveFileQueueCriteria RdbmsCatalogue::prepareForNewFileInternal(
+  const std::string &diskInstanceName, const std::string &storageClassName,
+  const common::dataStructures::UserIdentity &user) {
   try {
     auto conn = m_connPool.getConn();
     const common::dataStructures::TapeCopyToPoolMap copyToPoolMap = getTapeCopyToPoolMap(conn, diskInstanceName,
@@ -3816,10 +3866,12 @@ common::dataStructures::ArchiveFileQueueCriteria RdbmsCatalogue::prepareForNewFi
     }
 
     // Now that we have both the archive routes and the mount policy it's safe to
-    // consume an archive file identifierarchiveFileId
+    // consume an archive file identifier
     const uint64_t archiveFileId = getNextArchiveFileId(conn);
 
     return common::dataStructures::ArchiveFileQueueCriteria(archiveFileId, copyToPoolMap, mountPolicy);
+  } catch(exception::LostDatabaseConnection &le) {
+    throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str());
   } catch(exception::UserError &) {
     throw;
   } catch(exception::Exception &ex) {
@@ -3922,6 +3974,18 @@ void RdbmsCatalogue::updateTape(
 // prepareToRetrieveFile
 //------------------------------------------------------------------------------
 common::dataStructures::RetrieveFileQueueCriteria RdbmsCatalogue::prepareToRetrieveFile(
+  const std::string &diskInstanceName,
+  const uint64_t archiveFileId,
+  const common::dataStructures::UserIdentity &user,
+  log::LogContext &lc) {
+  return retryOnLostConnection( m_log, [&]{return prepareToRetrieveFileInternal(diskInstanceName, archiveFileId, user,
+    lc);}, m_maxTriesToConnect);
+}
+
+//------------------------------------------------------------------------------
+// prepareToRetrieveFileInternal
+//------------------------------------------------------------------------------
+common::dataStructures::RetrieveFileQueueCriteria RdbmsCatalogue::prepareToRetrieveFileInternal(
   const std::string &diskInstanceName,
   const uint64_t archiveFileId,
   const common::dataStructures::UserIdentity &user,
@@ -3975,6 +4039,8 @@ common::dataStructures::RetrieveFileQueueCriteria RdbmsCatalogue::prepareToRetri
     criteria.archiveFile = *archiveFile;
     criteria.mountPolicy = mountPolicy;
     return criteria;
+  } catch(exception::LostDatabaseConnection &le) {
+    throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str());
   } catch(exception::UserError &) {
     throw;
   } catch(exception::Exception &ex) {
@@ -3986,6 +4052,18 @@ common::dataStructures::RetrieveFileQueueCriteria RdbmsCatalogue::prepareToRetri
 // prepareToRetrieveFileByDiskFileId
 //------------------------------------------------------------------------------
 common::dataStructures::RetrieveFileQueueCriteria RdbmsCatalogue::prepareToRetrieveFileByDiskFileId(
+  const std::string &diskInstanceName,
+  const std::string &diskFileId,
+  const common::dataStructures::UserIdentity &user,
+  log::LogContext &lc) {
+  return retryOnLostConnection( m_log, [&]{return prepareToRetrieveFileByDiskFileIdInternal(diskInstanceName,
+    diskFileId, user, lc);}, m_maxTriesToConnect);
+}
+
+//------------------------------------------------------------------------------
+// prepareToRetrieveFileByDiskFileIdInternal
+//------------------------------------------------------------------------------
+common::dataStructures::RetrieveFileQueueCriteria RdbmsCatalogue::prepareToRetrieveFileByDiskFileIdInternal(
   const std::string &diskInstanceName,
   const std::string &diskFileId,
   const common::dataStructures::UserIdentity &user,
@@ -4033,6 +4111,8 @@ common::dataStructures::RetrieveFileQueueCriteria RdbmsCatalogue::prepareToRetri
     criteria.archiveFile = *archiveFile;
     criteria.mountPolicy = mountPolicy;
     return criteria;
+  } catch(exception::LostDatabaseConnection &le) {
+    throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str());
   } catch(exception::UserError &) {
     throw;
   } catch(exception::Exception &ex) {
@@ -4146,8 +4226,23 @@ RequesterAndGroupMountPolicies RdbmsCatalogue::getMountPolicies(
 // isAdmin
 //------------------------------------------------------------------------------
 bool RdbmsCatalogue::isAdmin(const common::dataStructures::SecurityIdentity &admin) const {
-  auto conn = m_connPool.getConn();
-  return userIsAdmin(conn, admin.username) && hostIsAdmin(conn, admin.host);
+  return retryOnLostConnection(m_log, [&]{return isAdminInternal(admin);}, m_maxTriesToConnect);
+}
+
+//------------------------------------------------------------------------------
+// isAdminInternal
+//------------------------------------------------------------------------------
+bool RdbmsCatalogue::isAdminInternal(const common::dataStructures::SecurityIdentity &admin) const {
+  try {
+    auto conn = m_connPool.getConn();
+    return userIsAdmin(conn, admin.username) && hostIsAdmin(conn, admin.host);
+  } catch(exception::LostDatabaseConnection &le) {
+    throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str());
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str());
+  }
 }
 
 //------------------------------------------------------------------------------
@@ -4188,6 +4283,13 @@ bool RdbmsCatalogue::hostIsAdmin(rdbms::Conn &conn, const std::string &hostName)
 // getTapesForWriting
 //------------------------------------------------------------------------------
 std::list<TapeForWriting> RdbmsCatalogue::getTapesForWriting(const std::string &logicalLibraryName) const {
+  return retryOnLostConnection(m_log, [&]{return getTapesForWritingInternal(logicalLibraryName);}, m_maxTriesToConnect);
+}
+
+//------------------------------------------------------------------------------
+// getTapesForWritingInternal
+//------------------------------------------------------------------------------
+std::list<TapeForWriting> RdbmsCatalogue::getTapesForWritingInternal(const std::string &logicalLibraryName) const {
   try {
     std::list<TapeForWriting> tapes;
     const char *const sql =
@@ -4197,15 +4299,16 @@ std::list<TapeForWriting> RdbmsCatalogue::getTapesForWriting(const std::string &
         "CAPACITY_IN_BYTES AS CAPACITY_IN_BYTES,"
         "DATA_IN_BYTES AS DATA_IN_BYTES,"
         "LAST_FSEQ AS LAST_FSEQ "
-      "FROM "
+        "FROM "
         "TAPE "
-      "WHERE "
+        "WHERE "
 //      "LBP_IS_ON IS NOT NULL AND "   // Set when the tape has been labelled
 //      "LABEL_DRIVE IS NOT NULL AND " // Set when the tape has been labelled
 //      "LABEL_TIME IS NOT NULL AND "  // Set when the tape has been labelled
         "IS_DISABLED = 0 AND "
         "IS_FULL = 0 AND "
         "LOGICAL_LIBRARY_NAME = :LOGICAL_LIBRARY_NAME";
+
     auto conn = m_connPool.getConn();
     auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
     stmt.bindString(":LOGICAL_LIBRARY_NAME", logicalLibraryName);
@@ -4220,8 +4323,9 @@ std::list<TapeForWriting> RdbmsCatalogue::getTapesForWriting(const std::string &
 
       tapes.push_back(tape);
     }
-
     return tapes;
+  } catch(exception::LostDatabaseConnection &le) {
+    throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str());
   } catch(exception::Exception &ex) {
     throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str());
   }
diff --git a/catalogue/RdbmsCatalogue.hpp b/catalogue/RdbmsCatalogue.hpp
index 738b78b4b8cc7060ec8b37226dd2e5ca1f2835b1..d15b4dfefd207f53c3019edce2857362eca98364 100644
--- a/catalogue/RdbmsCatalogue.hpp
+++ b/catalogue/RdbmsCatalogue.hpp
@@ -70,12 +70,16 @@ protected:
    * @param nbArchiveFileListingConns The maximum number of concurrent
    * connections to the underlying relational database for the sole purpose of
    * listing archive files.
+   * @param maxTriesToConnext The maximum number of times a single method should
+   * try to connect to the database in the event of LostDatabaseConnection
+   * exceptions being thrown.
    */
   RdbmsCatalogue(
     log::Logger &log,
     const rdbms::Login &login,
     const uint64_t nbConns,
-    const uint64_t nbArchiveFileListingConns);
+    const uint64_t nbArchiveFileListingConns,
+    const uint32_t maxTriesToConnect);
 
 public:
 
@@ -123,6 +127,7 @@ public:
    * disabled, not full and are in the specified logical library.
    *
    * @param logicalLibraryName The name of the logical library.
+   * @return The list of tapes for writing.
    */
   std::list<TapeForWriting> getTapesForWriting(const std::string &logicalLibraryName) const override;
 
@@ -529,6 +534,11 @@ public:
 
 protected:
 
+  /**
+   * Object representing the API to the CTA logging system.
+   */
+  log::Logger &m_log;
+
   /**
    * Mutex to be used to a take a global lock on the database.
    */
@@ -547,6 +557,12 @@ protected:
    */
   mutable rdbms::ConnPool m_archiveFileListingConnPool;
 
+  /**
+   * The maximum number of times a single method should try to connect to the
+   * database in the event of LostDatabaseConnection exceptions being thrown.
+   */
+  uint32_t m_maxTriesToConnect;
+
   /**
    * Returns true if the specified admin user exists.
    *
@@ -969,6 +985,155 @@ protected:
    */
   void checkTapeFileWrittenFieldsAreSet(const TapeFileWritten &event);
 
+  /**
+   * Returns true if the specified user running the CTA command-line tool on
+   * the specified host has administrator privileges.
+   *
+   * This internal method can be re-tried if it throws a LostDatabaseConnection
+   * exception.
+   *
+   * @param admin The administrator.
+   * @return True if the specified user running the CTA command-line tool on
+   * the specified host has administrator privileges.
+   */
+  bool isAdminInternal(const common::dataStructures::SecurityIdentity &admin) const;
+
+  /**
+   * Notifies the catalogue that the specified tape was labelled.
+   *
+   * @param vid The volume identifier of the tape.
+   * @param drive The name of tape drive that was used to label the tape.
+   * @param lbpIsOn Set to true if Logical Block Protection (LBP) was enabled.
+   */
+  void tapeLabelledInternal(const std::string &vid, const std::string &drive, const bool lbpIsOn);
+
+  /**
+   * Returns the list of tapes that can be written to by a tape drive in the
+   * specified logical library, in other words tapes that are labelled, not
+   * disabled, not full and are in the specified logical library.
+   *
+   * This internal method can be re-tried if it throws a LostDatabaseConnection
+   * exception.
+   *
+   * @param logicalLibraryName The name of the logical library.
+   * @return The list of tapes for writing.
+   */
+  std::list<TapeForWriting> getTapesForWritingInternal(const std::string &logicalLibraryName) const;
+
+  /**
+   * Notifies the CTA catalogue that the specified tape has been mounted in
+   * order to archive files.
+   *
+   * The purpose of this method is to keep track of which drive mounted a given
+   * tape for archiving 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 tapeMountedForArchiveInternal(const std::string &vid, const std::string &drive);
+
+  /**
+   * Prepares for a file retrieval by returning the information required to
+   * queue the associated retrieve request(s).
+   *
+   * This internal method can be re-tried if it throws a LostDatabaseConnection
+   * exception.
+   *
+   * @param diskInstanceName The name of the instance from where the retrieval
+   * request originated
+   * @param archiveFileId The unique identifier of the archived file that is
+   * to be retrieved.
+   * @param user The user for whom the file is to be retrieved.  This will be
+   * used by the Catalogue to determine the mount policy to be used when
+   * retrieving the file.
+   * @param lc The log context.
+   *
+   * @return The information required to queue the associated retrieve request(s).
+   */
+  common::dataStructures::RetrieveFileQueueCriteria prepareToRetrieveFileInternal(
+    const std::string &diskInstanceName,
+    const uint64_t archiveFileId,
+    const common::dataStructures::UserIdentity &user,
+    log::LogContext &lc);
+
+  /**
+   * Prepares for a file retrieval by returning the information required to
+   * queue the associated retrieve request(s).
+   *
+   * This internal method can be re-tried if it throws a LostDatabaseConnection
+   * exception.
+   *
+   * @param diskInstanceName The name of the instance from where the retrieval
+   * request originated
+   * @param diskFileId The identifier of the source disk file which is unique
+   * within it's host disk system.  Two files from different disk systems may
+   * have the same identifier.  The combination of diskInstanceName and
+   * diskFileId must be globally unique, in other words unique within the CTA
+   * catalogue.
+   * @param archiveFileId The unique identifier of the archived file that is
+   * to be retrieved.
+   * @param user The user for whom the file is to be retrieved.  This will be
+   * used by the Catalogue to determine the mount policy to be used when
+   * retrieving the file.
+   * @param lc The log context.
+   *
+   * @return The information required to queue the associated retrieve request(s).
+   */
+  common::dataStructures::RetrieveFileQueueCriteria prepareToRetrieveFileByDiskFileIdInternal(
+    const std::string &diskInstanceName,
+    const std::string &diskFileId,
+    const common::dataStructures::UserIdentity &user,
+    log::LogContext &lc);
+
+  /**
+   * 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);
+
+  /**
+   * This method notifies the CTA catalogue that there is no more free space on
+   * the specified tape.
+   *
+   * @param vid The volume identifier of the tape.
+   */
+  void noSpaceLeftOnTapeInternal(const std::string &vid);
+
+  /**
+   * Prepares the catalogue for a new archive file and returns the information
+   * required to queue the associated archive request.
+   *
+   * This internal method can be re-tried if it throws a LostDatabaseConnection
+   * exception.
+   *
+   * @param diskInstanceName The name of the disk instance to which the
+   * storage class belongs.
+   * @param storageClassName The name of the storage class of the file to be
+   * archived.  The storage class name is only guaranteed to be unique within
+   * its disk instance.  The storage class name will be used by the Catalogue
+   * to determine the destination tape pool for each tape copy.
+   * @param user The user for whom the file is to be archived.  This will be
+   * used by the Catalogue to determine the mount policy to be used when
+   * archiving the file.
+   * @return The information required to queue the associated archive request.
+   */
+  common::dataStructures::ArchiveFileQueueCriteria prepareForNewFileInternal(
+    const std::string &diskInstanceName,
+    const std::string &storageClassName,
+    const common::dataStructures::UserIdentity &user);
+
 }; // class RdbmsCatalogue
 
 } // namespace catalogue
diff --git a/catalogue/SchemaCreatingSqliteCatalogue.cpp b/catalogue/SchemaCreatingSqliteCatalogue.cpp
index e492e78fb9e7146f972d76535482cdc3e4c7d8d0..dd236e42d373c2a62657a325dd3cbe84dc2a291d 100644
--- a/catalogue/SchemaCreatingSqliteCatalogue.cpp
+++ b/catalogue/SchemaCreatingSqliteCatalogue.cpp
@@ -29,8 +29,9 @@ SchemaCreatingSqliteCatalogue::SchemaCreatingSqliteCatalogue(
   log::Logger &log,
   const std::string &filename,
   const uint64_t nbConns,
-  const uint64_t nbArchiveFileListingConns):
-  SqliteCatalogue(log, filename, nbConns, nbArchiveFileListingConns) {
+  const uint64_t nbArchiveFileListingConns,
+  const uint32_t maxTriesToConnect):
+  SqliteCatalogue(log, filename, nbConns, nbArchiveFileListingConns, maxTriesToConnect) {
   try {
     createCatalogueSchema();
   } catch(exception::Exception &ex) {
diff --git a/catalogue/SchemaCreatingSqliteCatalogue.hpp b/catalogue/SchemaCreatingSqliteCatalogue.hpp
index fe265c3932deb6fb38d00a91ba58f33e23c9b368..790f1bafd3ae0766c4b6319b84f2022af6927f8b 100644
--- a/catalogue/SchemaCreatingSqliteCatalogue.hpp
+++ b/catalogue/SchemaCreatingSqliteCatalogue.hpp
@@ -42,12 +42,16 @@ public:
    * @param nbArchiveFileListingConns The maximum number of concurrent
    * connections to the underlying relational database for the sole purpose of
    * listing archive files.
+   * @param maxTriesToConnext The maximum number of times a single method should
+   * try to connect to the database in the event of LostDatabaseConnection
+   * exceptions being thrown.
    */
   SchemaCreatingSqliteCatalogue(
     log::Logger &log,
     const std::string &filename,
     const uint64_t nbConns,
-    const uint64_t nbArchiveFileListingConns);
+    const uint64_t nbArchiveFileListingConns,
+    const uint32_t maxTriesToConnect);
 
   /**
    * Destructor.
diff --git a/catalogue/SqliteCatalogue.cpp b/catalogue/SqliteCatalogue.cpp
index b923e49f71facba47e5d335dcf51427718d1487e..6ed110590118180bcbb7efbefccb6ff867891f3c 100644
--- a/catalogue/SqliteCatalogue.cpp
+++ b/catalogue/SqliteCatalogue.cpp
@@ -37,12 +37,14 @@ SqliteCatalogue::SqliteCatalogue(
   log::Logger &log,
   const std::string &filename,
   const uint64_t nbConns,
-  const uint64_t nbArchiveFileListingConns):
+  const uint64_t nbArchiveFileListingConns,
+  const uint32_t maxTriesToConnect):
   RdbmsCatalogue(
     log,
     rdbms::Login(rdbms::Login::DBTYPE_SQLITE, "", "", filename),
     nbConns,
-    nbArchiveFileListingConns) {
+    nbArchiveFileListingConns,
+    maxTriesToConnect) {
 }
 
 //------------------------------------------------------------------------------
diff --git a/catalogue/SqliteCatalogue.hpp b/catalogue/SqliteCatalogue.hpp
index a1d8d966d7f856f39ab7fb123f1deb3026e976ee..db78c06be4dba1f88b040968caa942be48556548 100644
--- a/catalogue/SqliteCatalogue.hpp
+++ b/catalogue/SqliteCatalogue.hpp
@@ -42,12 +42,16 @@ public:
    * @param nbArchiveFileListingConns The maximum number of concurrent
    * connections to the underlying relational database for the sole purpose of
    * listing archive files.
+   * @param maxTriesToConnext The maximum number of times a single method should
+   * try to connect to the database in the event of LostDatabaseConnection
+   * exceptions being thrown.
    */
   SqliteCatalogue(
     log::Logger &log,
     const std::string &filename,
     const uint64_t nbConns,
-    const uint64_t nbArchiveFileListingConns);
+    const uint64_t nbArchiveFileListingConns,
+    const uint32_t maxTriesToConnect);
 
 public:
 
diff --git a/catalogue/retryOnLostConnection.hpp b/catalogue/retryOnLostConnection.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..d3be72926099eed8bb98fd3319df33398691caa2
--- /dev/null
+++ b/catalogue/retryOnLostConnection.hpp
@@ -0,0 +1,74 @@
+/*
+ * The CERN Tape Archive(CTA) project
+ * Copyright(C) 2015  CERN
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ *(at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "common/exception/Exception.hpp"
+#include "common/exception/LostDatabaseConnection.hpp"
+#include "common/log/Logger.hpp"
+
+#include <list>
+#include <stdint.h>
+#include <type_traits>
+
+namespace cta {
+namespace catalogue {
+
+/**
+ * Retries calling the specified callable if it throws a LostDatabaseConnection
+ * exception.
+ *
+ * @tparam T The type of the callable.
+ * @param log Object representing the API to the CTA logging system.
+ * @param callable The callable.
+ * @param maxTriesToConnect The maximum number of times the callable should be called in the event of a
+ * LostDatbaseConnection exception.
+ * @return The result of calling the callable.
+ */
+template<typename T>
+typename std::result_of<T()>::type retryOnLostConnection(log::Logger &log, const T &callable,
+  const uint32_t maxTriesToConnect) {
+  try {
+    for (uint32_t tryNb = 1; tryNb <= maxTriesToConnect; tryNb++) {
+      try {
+        return callable();
+      } catch (exception::LostDatabaseConnection &le) {
+        // Log lost connection
+        std::list<log::Param> params = {
+          {"maxTriesToConnect", maxTriesToConnect},
+          {"tryNb", tryNb},
+          {"msg", le.getMessage()}
+        };
+        log(cta::log::WARNING, "Lost database connection", params);
+      }
+    }
+
+    exception::Exception ex;
+    ex.getMessage() << "Lost the database connection after trying " << maxTriesToConnect << " times";
+    throw ex;
+  } catch (exception::UserError &) {
+    throw;
+  } catch (exception::Exception &) {
+    throw;
+  } catch (std::exception &se) {
+    throw exception::Exception(se.what());
+  }
+}
+
+} // namespace catalogue
+} // namespace cta
diff --git a/cmdline/CMakeLists.txt b/cmdline/CMakeLists.txt
index ba6bdddc409bd3b0568e0f12943077c779367c1e..37a98021394d2ca7a44bbf0d917eca98ad42cf4e 100644
--- a/cmdline/CMakeLists.txt
+++ b/cmdline/CMakeLists.txt
@@ -19,34 +19,16 @@ cmake_minimum_required (VERSION 2.6)
 find_package(xrootdclient REQUIRED)
 find_package(xrootd REQUIRED)
 find_package(Protobuf3 REQUIRED)
-# Cryptopp can be dropped when we get rid of eoscta_stub
-find_package(cryptopp REQUIRED)
 
-#
 # XRootD SSI
-#
 include_directories(${XROOTD_INCLUDE_DIR} ${XROOTD_INCLUDE_DIR}/private)
 
-#
 # XRootD SSI Protocol Buffer bindings
-#
 include_directories(${XRD_SSI_PB_DIR}/include ${XRD_SSI_PB_DIR}/eos_cta/include)
 
-#
 # Compiled protocol buffers
-#
 include_directories(${CMAKE_BINARY_DIR}/eos_cta ${PROTOBUF3_INCLUDE_DIRS})
 
-#
-# eoscta_stub is a drop-in replacement for "cta archive|retrieve|delete"
-#
-add_executable(eoscta_stub EosCtaStub.cpp Configuration.cpp)
-target_link_libraries(eoscta_stub cryptopp ctacommon XrdSsiPbEosCta XrdSsi-4 XrdSsiLib)
-set_property (TARGET eoscta_stub APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH})
-# Get some extra debug messages on stdout
-#target_compile_definitions(eoscta_stub PUBLIC XRDSSI_DEBUG)
-install(TARGETS eoscta_stub DESTINATION usr/bin)
-
 #
 # cta-admin <admin_command> is the SSI version of "cta <admin_command>"
 #
@@ -55,10 +37,21 @@ target_link_libraries(cta-admin XrdSsiPbEosCta XrdSsi-4 XrdSsiLib)
 set_property (TARGET cta-admin APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH})
 # Get some extra debug messages on stdout
 #target_compile_definitions(cta-admin PUBLIC XRDSSI_DEBUG)
-install(TARGETS cta-admin DESTINATION usr/bin)
 
-add_executable(cta.deprecated CTACmdMain.cpp Configuration.cpp)
-target_link_libraries(cta.deprecated ${XROOTD_XRDCL_LIB} cryptopp)
-install(TARGETS cta.deprecated DESTINATION usr/bin)
-INSTALL(FILES cta-cli.conf DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/cta)
+#
+# cta-wfe-test archive|retrieve|delete <options> allows testing of the SSI WorkFlow Engine hooks
+# without invoking EOS.
+#
+# Previously this was the eoscta_stub which was called by a script invoked by the EOS WFE.
+#
+find_package(cryptopp REQUIRED)
+add_executable(cta-wfe-test EosCtaStub.cpp Configuration.cpp)
+target_link_libraries(cta-wfe-test cryptopp ctacommon XrdSsiPbEosCta XrdSsi-4 XrdSsiLib)
+set_property (TARGET cta-wfe-test APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH})
+# Get some extra debug messages on stdout
+#target_compile_definitions(eoscta_stub PUBLIC XRDSSI_DEBUG)
+
+install(TARGETS cta-admin DESTINATION usr/bin)
+install(TARGETS cta-wfe-test DESTINATION usr/bin)
+install(FILES cta-cli.conf DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/cta)
 
diff --git a/cmdline/CTACmdMain.cpp b/cmdline/CTACmdMain.cpp
deleted file mode 100644
index b7eb084c79e1f7139d8193b983b37f85fe0b1441..0000000000000000000000000000000000000000
--- a/cmdline/CTACmdMain.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * The CERN Tape Archive (CTA) project
- * Copyright (C) 2015  CERN
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "cmdline/Configuration.hpp"
-#include "common/Configuration.hpp"
-#include "common/dataStructures/FrontendReturnCode.hpp"
-
-#include "XrdCl/XrdClCopyProcess.hh"
-#include "XrdCl/XrdClEnv.hh"
-#include "XrdCl/XrdClDefaultEnv.hh"
-
-#include <cryptopp/base64.h>
-#include <cryptopp/osrng.h>
-
-#include <iostream>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdexcept>
-#include <xrootd/XrdCl/XrdClFile.hh>
-
-/**
- * Returns true if --stderr is on the command-line.
- *
- * @param argc The number of command-line arguments.
- * @param argv The command-line arguments.
- */
-static bool stderrIsOnTheCmdLine(const int argc, const char *const *const argv) {
-  for(int i = 1; i < argc; i++) {
-    const std::string arg = argv[i];
-
-    if(arg == "--stderr") {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-/**
- * Replaces all occurrences in a string "str" of a substring "from" with the string "to"
- * 
- * @param str  The original string
- * @param from The substring to replace
- * @param to   The replacement string
- */
-void replaceAll(std::string& str, const std::string& from, const std::string& to){
-  if(from.empty() || str.empty())
-    return;
-  size_t start_pos = 0;
-  while((start_pos = str.find(from, start_pos)) != std::string::npos) {
-    str.replace(start_pos, from.length(), to);
-    start_pos += to.length();
-  }
-}
-
-/**
- * Encodes a string in base 64 and replaces slashes ('/') in the result
- * with underscores ('_').
- * 
- * @param msg string to encode
- * @return encoded string
- */
-std::string encode(const std::string msg) {
-  std::string ret;
-  const bool noNewLineInBase64Output = false;
-  CryptoPP::StringSource ss1(msg, true, new CryptoPP::Base64Encoder(new CryptoPP::StringSink(ret), noNewLineInBase64Output));
-
-  // need to replace slashes ('/') with underscores ('_') because xroot removes
-  // consecutive slashes, and the cryptopp base64 algorithm may produce
-  // consecutive slashes. This is solved in cryptopp-5.6.3 (using
-  // Base64URLEncoder instead of Base64Encoder) but we currently have
-  // cryptopp-5.6.2. To be changed in the future...
-  replaceAll(ret, "/", "_");
-
-  return ret;
-}
-
-/**
- * Formats the command path string
- *
- * @param argc The number of command-line arguments.
- * @param argv The command-line arguments. 
- * @return the command string
- */
-std::string formatCommandPath(const int argc, const char **argv) {
-  cta::cmdline::Configuration cliConf("/etc/cta/cta-cli.conf");
-  std::string cmdPath = "root://"+cliConf.getFrontendHostAndPort()+"//";
-
-  for(int i=0; i<argc; i++) {
-    if(i) cmdPath += "&";
-    cmdPath += encode(std::string(argv[i]));
-  }
-  return cmdPath;
-}
-
-/**
- * Sends the command and waits for the reply
- *
- * @param argc The number of command-line arguments.
- * @param argv The command-line arguments. 
- * @return the return code
- */
-int sendCommand(const int argc, const char **argv) {
-  int rc = 0;
-  const bool writeToStderr = stderrIsOnTheCmdLine(argc, argv);
-  const std::string cmdPath = formatCommandPath(argc, argv);
-  XrdCl::File xrootFile;
-
-  // Open the xroot file reprsenting the execution of the command
-  {
-    const XrdCl::Access::Mode openMode = XrdCl::Access::None;
-    const uint16_t openTimeout = 15; // Timeout in seconds that is rounded up to the nearest 15 seconds
-    const XrdCl::XRootDStatus openStatus = xrootFile.Open(cmdPath, XrdCl::OpenFlags::Read, openMode, openTimeout);
-    if(!openStatus.IsOK()) {
-      throw std::runtime_error(std::string("Failed to open ") + cmdPath + ": " + openStatus.ToStr());
-    }
-  }
-
-  // The cta frontend return code is the first char of the answer
-  {
-    uint64_t readOffset = 0;
-    uint32_t bytesRead = 0;
-    char rc_char = '0';
-    const XrdCl::XRootDStatus readStatus = xrootFile.Read(readOffset, 1, &rc_char, bytesRead);
-    if(!readStatus.IsOK()) {
-      throw std::runtime_error(std::string("Failed to read first byte from ") + cmdPath + ": " +
-        readStatus.ToStr());
-    }
-    if(bytesRead != 1) {
-      throw std::runtime_error(std::string("Failed to read first byte from ") + cmdPath +
-        ": Expected to read exactly 1 byte, actually read " +
-        std::to_string((long long unsigned int)bytesRead) + " bytes");
-    }
-    rc = rc_char - '0';
-  }
-
-  // Read and print the command result
-  {
-    uint64_t readOffset = 1; // The first character at offset 0 has already been read
-    uint32_t bytesRead = 0;
-    const size_t bufSize = 20480;
-    std::unique_ptr<char []> buf(new char[bufSize]);
-    do {
-      bytesRead = 0;
-      memset(buf.get(), 0, bufSize);
-      const XrdCl::XRootDStatus readStatus = xrootFile.Read(readOffset, bufSize - 1, buf.get(), bytesRead);
-      if(!readStatus.IsOK()) {
-        throw std::runtime_error(std::string("Failed to read ") + cmdPath + ": " + readStatus.ToStr());
-      }
-
-      if(bytesRead > 0) {
-        std::cout << buf.get();
-
-        if(writeToStderr) {
-          std::cerr << buf.get();
-        }
-      }
-
-      readOffset += bytesRead;
-    } while(bytesRead > 0);
-  }
-
-  // Close the xroot file reprsenting the execution of the command
-  {
-    const XrdCl::XRootDStatus closeStatus = xrootFile.Close();
-    if(!closeStatus.IsOK()) {
-      throw std::runtime_error(std::string("Failed to close ") + cmdPath + ": " + closeStatus.ToStr());
-    }
-  }
-
-  return rc;
-}
-
-/**
- * The entry function of the command.
- *
- * @param argc The number of command-line arguments.
- * @param argv The command-line arguments.
- */
-int main(const int argc, const char **argv) {
-  try {    
-    return sendCommand(argc, argv);
-  } catch (std::exception &ex) {
-    std::cerr << "Failed to execute the command. Reason: " << ex.what() << std::endl;
-    return cta::common::dataStructures::FrontendReturnCode::ctaErrorNoRetry;
-  } catch (...) {
-    std::cerr << "Failed to execute the command for an unknown reason" << std::endl;
-    return cta::common::dataStructures::FrontendReturnCode::ctaErrorNoRetry;
-  }
-}
diff --git a/cmdline/EosCtaStub.cpp b/cmdline/EosCtaStub.cpp
index 73be6dc73e49b301d58fbd43e1658d1011c8c52e..3014a72eda20feb27cdecd07b62d1b2187a0af57 100644
--- a/cmdline/EosCtaStub.cpp
+++ b/cmdline/EosCtaStub.cpp
@@ -53,7 +53,7 @@ void RequestCallback<cta::xrd::Alert>::operator()(const cta::xrd::Alert &alert)
 
 //! Usage exception
 
-const std::runtime_error Usage("Usage: eoscta_stub archive|retrieve|deletearchive [options] [--stderr]");
+const std::runtime_error Usage("Usage: cta-wfe-test archive|retrieve|deletearchive [options] [--stderr]");
 
 
 
diff --git a/cmdline/cta.1cta b/cmdline/cta.1cta
deleted file mode 100644
index 9daef238e74ac7c89c523e8e54601712def61852..0000000000000000000000000000000000000000
--- a/cmdline/cta.1cta
+++ /dev/null
@@ -1,28 +0,0 @@
-.\" The CERN Tape Archive (CTA) project
-.\" Copyright (C) 2015  CERN
-.\"
-.\" This program is free software: you can redistribute it and/or modify
-.\" it under the terms of the GNU General Public License as published by
-.\" the Free Software Foundation, either version 3 of the License, or
-.\" (at your option) any later version.
-.\"
-.\" This program is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public License
-.\" along with this program.  If not, see <http://www.gnu.org/licenses/>.
-.TH CTA 1CTA "August 2016" CTA CTA
-.SH NAME
-cta \- main command line interface to the CERN Tape Archive
-.SH SYNOPSIS
-.BI "cta"
-
-.SH DESCRIPTION
-Please refer to the help provided within the \fBcta\fP command. Just type \fBcta\fP for generic help or
-\fBcta <command>\fP for help on a specific command.
-
-.SH AUTHOR
-\fBCTA\fP Team
-
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 73f7306c0342996a58fb068fb23baa8d74beaa46..3aa0c85c7c16e0ea7eb2925c0d80f8287ebe8a72 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -83,6 +83,7 @@ set (COMMON_LIB_SRC_FILES
   exception/Exception.cpp
   exception/InvalidArgument.cpp
   exception/InvalidConfigEntry.cpp
+  exception/LostDatabaseConnection.cpp
   exception/Mismatch.cpp
   exception/MissingOperand.cpp
   exception/MountFailed.cpp
diff --git a/common/exception/LostDatabaseConnection.cpp b/common/exception/LostDatabaseConnection.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f464441cb708617605dffbf4d9057eaf8c6004cd
--- /dev/null
+++ b/common/exception/LostDatabaseConnection.cpp
@@ -0,0 +1,33 @@
+/*
+ * The CERN Tape Archive (CTA) project
+ * Copyright (C) 2015  CERN
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "common/exception/LostDatabaseConnection.hpp"
+
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+cta::exception::LostDatabaseConnection::LostDatabaseConnection(const std::string &context, const bool embedBacktrace):
+  Exception(context, embedBacktrace) {
+}
+
+//------------------------------------------------------------------------------
+// destructor
+//------------------------------------------------------------------------------
+cta::exception::LostDatabaseConnection::~LostDatabaseConnection() noexcept {
+}
diff --git a/common/exception/LostDatabaseConnection.hpp b/common/exception/LostDatabaseConnection.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..9acc170dd4b02609928eb21936b94378731d0e75
--- /dev/null
+++ b/common/exception/LostDatabaseConnection.hpp
@@ -0,0 +1,55 @@
+/*
+ * The CERN Tape Archive (CTA) project
+ * Copyright (C) 2015  CERN
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "common/exception/Exception.hpp"
+
+#include <string>
+
+
+namespace cta    {
+namespace exception {
+
+/**
+ * The database connection has been lost.
+ */
+class LostDatabaseConnection : public cta::exception::Exception {
+public:
+
+  /**
+   * Constructor.
+   *
+   * @param context optional context string added to the message
+   * at initialisation time.
+   * @param embedBacktrace whether to embed a backtrace of where the
+   * exception was throw in the message
+   */
+  LostDatabaseConnection(const std::string &context = "", const bool embedBacktrace = true);
+
+  /**
+   * Empty Destructor, explicitely non-throwing (needed for std::exception
+   * inheritance)
+   */
+  ~LostDatabaseConnection() noexcept override;
+  
+}; // class LostDatabaseConnection
+
+} // namespace exception
+} // namespace cta
+
diff --git a/continuousintegration/README.md b/continuousintegration/README.md
index 58066919d28fd39accdda710da9f05374f997bc8..01b4a6398d23356a11f67391ae3bf155ecacddcf 100644
--- a/continuousintegration/README.md
+++ b/continuousintegration/README.md
@@ -1,6 +1,20 @@
-Folder content:
+# Folder content
+
 * `ci_helpers`: helper scripts used by gilab_ci
 * `docker`: Docker files and content needed to build the needed docker images
 * `orchestration`: orchestration specific files: this contains all the pods definitions and *startup scripts* launched in the pod containers during instanciation.
 * `buildtree_runner`: setup scripts for running the ci tests from the build tree instead of RPMs
 * `buildtree_runner/vmBootstrap`: As set of scripts describing the preparation of a machine for fresh install to running CI scripts **MUST NOT BE RUN BLINDLY**
+
+# How to update the EOS version used in CI
+
+1. ssh to **aiadm**, then:
+```
+$ cd /eos/user/c/ctareg/www/cta-ci-repo/
+$ cp <path_to_rpms>/eos-*.rpm eos/x86_64/
+$ ./update_repos.sh
+```
+2. In the CTA repository, update the yum version lock list with the new EOS version:
+```
+/CTA/continuousintegration/docker/ctafrontend/cc7/etc/yum/pluginconf.d/versionlock.list
+```
diff --git a/continuousintegration/docker/ctafrontend/cc7/etc/yum/pluginconf.d/versionlock.list b/continuousintegration/docker/ctafrontend/cc7/etc/yum/pluginconf.d/versionlock.list
index 7e45d5f801c76205d49193baf1b3fbceed82b3f1..854df8e319a7a9ce610e13cf0515fee032b38884 100644
--- a/continuousintegration/docker/ctafrontend/cc7/etc/yum/pluginconf.d/versionlock.list
+++ b/continuousintegration/docker/ctafrontend/cc7/etc/yum/pluginconf.d/versionlock.list
@@ -1,34 +1,34 @@
-0:eos-archive-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64
-0:eos-cleanup-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64
-0:eos-client-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64
-0:eos-debuginfo-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64
-0:eos-fuse-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64
-0:eos-fuse-core-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64
-0:eos-fuse-sysv-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64
-0:eos-fusex-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64
-0:eos-fusex-core-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64
-0:eos-fusex-selinux-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64
-0:eos-server-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64
-0:eos-srm-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64
-0:eos-test-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64
-0:eos-testkeytab-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64
-1:python2-xrootd-4.8.0-0.rc1.el7.x86_64
-1:python3-xrootd-4.8.0-0.rc1.el7.x86_64
-1:xrootd-4.8.0-0.rc1.el7.x86_64
-1:xrootd-client-4.8.0-0.rc1.el7.x86_64
-1:xrootd-client-devel-4.8.0-0.rc1.el7.x86_64
-1:xrootd-client-libs-4.8.0-0.rc1.el7.x86_64
-1:xrootd-debuginfo-4.8.0-0.rc1.el7.x86_64
-1:xrootd-devel-4.8.0-0.rc1.el7.x86_64
-1:xrootd-doc-4.8.0-0.rc1.el7.noarch
-1:xrootd-fuse-4.8.0-0.rc1.el7.x86_64
-1:xrootd-libs-4.8.0-0.rc1.el7.x86_64
-1:xrootd-private-devel-4.8.0-0.rc1.el7.x86_64
-1:xrootd-selinux-4.8.0-0.rc1.el7.noarch
-1:xrootd-server-4.8.0-0.rc1.el7.x86_64
-1:xrootd-server-devel-4.8.0-0.rc1.el7.x86_64
-1:xrootd-server-libs-4.8.0-0.rc1.el7.x86_64
-1:xrootd-tests-4.8.0-0.rc1.el7.x86_64
+0:eos-archive-4.2.12-20180202120141git3855655.el7.cern.x86_64
+0:eos-cleanup-4.2.12-20180202120141git3855655.el7.cern.x86_64
+0:eos-client-4.2.12-20180202120141git3855655.el7.cern.x86_64
+0:eos-debuginfo-4.2.12-20180202120141git3855655.el7.cern.x86_64
+0:eos-fuse-4.2.12-20180202120141git3855655.el7.cern.x86_64
+0:eos-fuse-core-4.2.12-20180202120141git3855655.el7.cern.x86_64
+0:eos-fuse-sysv-4.2.12-20180202120141git3855655.el7.cern.x86_64
+0:eos-fusex-4.2.12-20180202120141git3855655.el7.cern.x86_64
+0:eos-fusex-core-4.2.12-20180202120141git3855655.el7.cern.x86_64
+0:eos-fusex-selinux-4.2.12-20180202120141git3855655.el7.cern.x86_64
+0:eos-server-4.2.12-20180202120141git3855655.el7.cern.x86_64
+0:eos-srm-4.2.12-20180202120141git3855655.el7.cern.x86_64
+0:eos-test-4.2.12-20180202120141git3855655.el7.cern.x86_64
+0:eos-testkeytab-4.2.12-20180202120141git3855655.el7.cern.x86_64
+1:python2-xrootd-4.8.1-1.el7.cern.x86_64
+1:python3-xrootd-4.8.1-1.el7.cern.x86_64
+1:xrootd-4.8.1-1.el7.cern.x86_64
+1:xrootd-client-4.8.1-1.el7.cern.x86_64
+1:xrootd-client-devel-4.8.1-1.el7.cern.x86_64
+1:xrootd-client-libs-4.8.1-1.el7.cern.x86_64
+1:xrootd-debuginfo-4.8.1-1.el7.cern.x86_64
+1:xrootd-devel-4.8.1-1.el7.cern.x86_64
+1:xrootd-doc-4.8.1-1.el7.cern.noarch
+1:xrootd-fuse-4.8.1-1.el7.cern.x86_64
+1:xrootd-libs-4.8.1-1.el7.cern.x86_64
+1:xrootd-private-devel-4.8.1-1.el7.cern.x86_64
+1:xrootd-selinux-4.8.1-1.el7.cern.noarch
+1:xrootd-server-4.8.1-1.el7.cern.x86_64
+1:xrootd-server-devel-4.8.1-1.el7.cern.x86_64
+1:xrootd-server-libs-4.8.1-1.el7.cern.x86_64
+1:xrootd-tests-4.8.1-1.el7.cern.x86_64
 2:ceph-12.2.2-0.el7.x86_64
 2:ceph-base-12.2.2-0.el7.x86_64
 2:ceph-common-12.2.2-0.el7.x86_64
diff --git a/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/ctaeos-mgm.sh b/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/ctaeos-mgm.sh
index 350f39ff4afd15f4fd9ec9865591d078ad502bfa..db305fa7aa33a031026a90389be89dba5c3a5b86 100755
--- a/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/ctaeos-mgm.sh
+++ b/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/ctaeos-mgm.sh
@@ -34,7 +34,6 @@ eoshost=`hostname -f`
 EOS_INSTANCE=`hostname -s`
 TAPE_FS_ID=65535
 CTA_BIN=/usr/bin/eoscta_stub
-CTA_KT=/etc/cta/cta-cli.sss.keytab
 CTA_XrdSecPROTOCOL=sss
 CTA_PROC_DIR=/eos/${EOS_INSTANCE}/proc/cta
 CTA_WF_DIR=${CTA_PROC_DIR}/workflow
@@ -43,14 +42,6 @@ CTA_TEST_DIR=/eos/${EOS_INSTANCE}/cta
 # dir for eos instance basic tests writable and readable by anyone
 EOS_TMP_DIR=/eos/${EOS_INSTANCE}/tmp
 
-# prepare CTA cli commands environment
-cat <<EOF > /etc/cta/cta-cli.conf
-# The CTA frontend address in the form <FQDN>:<TCPPort>
-# solved by kubernetes DNS server so KIS...
-ctafrontend:10955
-EOF
-
-
 # setup eos host and instance name
   sed -i -e "s/DUMMY_HOST_TO_REPLACE/${eoshost}/" /etc/sysconfig/eos
   sed -i -e "s/DUMMY_INSTANCE_TO_REPLACE/${EOS_INSTANCE}/" /etc/sysconfig/eos
@@ -188,30 +179,10 @@ test -e /usr/lib64/libjemalloc.so.1 && export LD_PRELOAD=/usr/lib64/libjemalloc.
   # set interval in which the WFE engine is running
   #eos space config default space.wfe.interval=1
 
-# ATTENTION
-# for sss authorisation  unix has to be replaced by sss
-
-# Set the worfklow rule for archiving files to tape
-eos attr set sys.workflow.closew.default="bash:shell:cta XRD_LOGLEVEL=Error XrdSecDEBUG=1 XrdSecPROTOCOL=${CTA_XrdSecPROTOCOL} XrdSecSSSKT=${CTA_KT} ${CTA_BIN} archive --user <eos::wfe::rusername> --group <eos::wfe::rgroupname> --diskid <eos::wfe::fid> --instance ignored_instance_name --srcurl <eos::wfe::turl> --size <eos::wfe::size> --checksumtype <eos::wfe::checksumtype> --checksumvalue <eos::wfe::checksum> --storageclass <eos::wfe::cxattr:CTA_StorageClass> --diskfilepath <eos::wfe::path> --diskfileowner <eos::wfe::username> --diskfilegroup <eos::wfe::groupname> --recoveryblob:base64 <eos::wfe::base64:metadata> --reportURL 'eosQuery://${EOS_INSTANCE}//eos/wfe/passwd?mgm.pcmd=event\&mgm.fid=<eos::wfe::fxid>\&mgm.logid=cta\&mgm.event=archived\&mgm.workflow=default\&mgm.path=/eos/wfe/passwd\&mgm.ruid=0\&mgm.rgid=0' --stderr" ${CTA_WF_DIR}
-
-# Set the worflow rule for creating tape file replicas in the EOS namespace.
-eos attr set sys.workflow.archived.default="bash:shell:cta eos file tag <eos::wfe::path> +<eos::wfe::cxattr:CTA_TapeFsId>" ${CTA_WF_DIR}
-
-# Set the worfklow rule for retrieving file from tape.
-eos attr set sys.workflow.sync::prepare.default="bash:shell:cta XrdSecPROTOCOL=${CTA_XrdSecPROTOCOL} XrdSecSSSKT=${CTA_KT} ${CTA_BIN} retrieve --user <eos::wfe::rusername> --group <eos::wfe::rgroupname> --id <eos::wfe::fxattr:sys.archiveFileId> --dsturl '<eos::wfe::turl>\&eos.ruid=0\&eos.rgid=0\&eos.injection=1\&eos.workflow=CTA_retrieve' --diskfilepath <eos::wfe::path> --diskfileowner <eos::wfe::username> --diskfilegroup <eos::wfe::groupname> --recoveryblob:base64 <eos::wfe::base64:metadata> --stderr" ${CTA_WF_DIR}
-
-# Set the workflow rule for the closew event of the CTA_retrieve workflow.
-# Using the CTA_retrieve workflow will prevent the default workflow from
-# receiving the closew event.  Triggering the default workflow in this way would
-# haved causes the unwanted action of copying the disk file to tape again.
-# The action of the CTA_retrieve workflow when triggered by the closew event is
-# to set the CTA_retrieved_timestamp attribute.
-eos attr set sys.workflow.closew.CTA_retrieve="bash:shell:cta eos attr set 'CTA_retrieved_timestamp=\"\`date\`\"' <eos::wfe::path>" ${CTA_WF_DIR}
-
-
 # configure preprod directory separately
 /opt/run/bin/eos_configure_preprod.sh
 
 echo "### ctaeos mgm ready ###"
 
 /bin/bash
+
diff --git a/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/ctafrontend.sh b/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/ctafrontend.sh
index a8e7e59f059792e243f98d61cbeffcffca51b982..90ece0a057eca04fb05ee60430ac18013d9f077a 100755
--- a/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/ctafrontend.sh
+++ b/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/ctafrontend.sh
@@ -11,8 +11,7 @@ yum-config-manager --enable ceph
 yum -y install cta-frontend cta-debuginfo cta-catalogueutils ceph-common
 fi
 
-# /etc/cta/cta-frontend-xrootd.conf is now provided by ctafrontend rpm and comes with
-# CI ready content
+# /etc/cta/cta-frontend-xrootd.conf is now provided by ctafrontend rpm and comes with CI-ready content
 
 /opt/run/bin/init_objectstore.sh
 . /tmp/objectstore-rc.sh
@@ -21,7 +20,6 @@ echo "ObjectStore BackendPath $OBJECTSTOREURL" > /etc/cta/cta-frontend.conf
 echo "Catalogue NumberOfConnections 10" >>/etc/cta/cta-frontend.conf
 echo "Log URL file:/var/log/cta/cta-frontend.log" >>/etc/cta/cta-frontend.conf
 
-
 /opt/run/bin/init_database.sh
 . /tmp/database-rc.sh
 
@@ -30,15 +28,11 @@ echo ${DATABASEURL} >/etc/cta/cta-catalogue.conf
 # EOS INSTANCE NAME used as username for SSS key
 EOSINSTANCE=ctaeos
 
-# Create SSS key for cta-cli, must be forwardable in kubernetes realm (this is what the + is for)
-# USER IN THE SSS FILE IS THE EOS INSTANCE NAME THE REST IS BS
-echo y | xrdsssadmin -k cta-cli+ -u ${EOSINSTANCE} -g cta add /etc/cta/cta-cli.sss.keytab
-chmod 600 /etc/cta/cta-cli.sss.keytab
-chown cta /etc/cta/cta-cli.sss.keytab
-# DO NOT FORGET THAT YOU CAN DEFINE SEPARATE CLIENT AND SERVER KEYTABS
-
-# Wait for the keytab file to be pushed in by the creation script.
-echo -n "Waiting for /etc/cta/cta-frontend.krb5.keytab"
+# Wait for the keytab files to be pushed in by the creation script
+echo -n "Waiting for /etc/cta/eos.sss.keytab."
+for ((;;)); do test -e /etc/cta/eos.sss.keytab && break; sleep 1; echo -n .; done
+echo OK
+echo -n "Waiting for /etc/cta/cta-frontend.krb5.keytab."
 for ((;;)); do test -e /etc/cta/cta-frontend.krb5.keytab && break; sleep 1; echo -n .; done
 echo OK
 
diff --git a/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/eos_configure_preprod.sh b/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/eos_configure_preprod.sh
index 95e9147558350d5765ae5a1cb6527c0060b170b4..a91be345ba28732eee9ed3ccbed1d84b0c49b3b1 100755
--- a/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/eos_configure_preprod.sh
+++ b/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/eos_configure_preprod.sh
@@ -1,26 +1,15 @@
 #!/bin/bash
 PREPROD_DIR=/eos/ctaeos/preprod
-CTA_BIN=/usr/bin/eoscta_stub
-
-mkdir -p /var/eos/wfe/bash
-cp /opt/ci/ctaeos/var/eos/wfe/bash/* /var/eos/wfe/bash/
-chmod 755 /var/eos/wfe/bash/*
 
 eos mkdir ${PREPROD_DIR}
 eos chmod 555 ${PREPROD_DIR}
 eos attr set sys.acl=g:eosusers:rwx!d,u:poweruser1:rwx+dp,u:poweruser2:rwx+dp ${PREPROD_DIR}
 
 eos attr set CTA_StorageClass=ctaStorageClass ${PREPROD_DIR}
-
 eos attr set CTA_TapeFsId=65535 ${PREPROD_DIR}
 
-eos attr set sys.workflow.closew.default="bash:shell:cta XRD_LOGLEVEL=Error XrdSecDEBUG=1 XrdSecPROTOCOL=sss XrdSecSSSKT=/etc/cta/cta-cli.sss.keytab ${CTA_BIN} archive --user <eos::wfe::rusername> --group <eos::wfe::rgroupname> --diskid <eos::wfe::fid> --instance ignored_instance_name --srcurl <eos::wfe::turl> --size <eos::wfe::size> --checksumtype <eos::wfe::checksumtype> --checksumvalue <eos::wfe::checksum> --storageclass <eos::wfe::cxattr:CTA_StorageClass> --diskfilepath <eos::wfe::path> --diskfileowner <eos::wfe::username> --diskfilegroup <eos::wfe::groupname> --recoveryblob:base64 cmVjb3ZlcnkK --reportURL 'eosQuery://ctaeos//eos/wfe/passwd?mgm.pcmd=event\&mgm.fid=<eos::wfe::fxid>\&mgm.logid=cta\&mgm.event=archived\&mgm.workflow=default\&mgm.path=/eos/wfe/passwd\&mgm.ruid=0\&mgm.rgid=0' --stderr" ${PREPROD_DIR}
-
-#eos attr set sys.workflow.archived.default="bash:shell:cta eos file tag <eos::wfe::path> +<eos::wfe::cxattr:CTA_TapeFsId>" ${PREPROD_DIR}
-eos attr set sys.workflow.archived.default="bash:create_tape_drop_disk_replicas:cta <eos::wfe::path> <eos::wfe::cxattr:CTA_TapeFsId>" ${PREPROD_DIR}
-
-eos attr set sys.workflow.sync::prepare.default="bash:retrieve_archive_file:cta <eos::wfe::rusername> <eos::wfe::rgroupname> <eos::wfe::fxattr:sys.archiveFileId> <eos::wfe::turl> <eos::wfe::username> <eos::wfe::groupname> cmVjb3ZlcnkK <eos::wfe::path>" ${PREPROD_DIR}
-
-eos attr set sys.workflow.closew.CTA_retrieve="bash:shell:cta eos attr set 'CTA_retrieved_timestamp=\"\`date\`\"' <eos::wfe::path>" ${PREPROD_DIR}
-
-eos attr set sys.workflow.sync::delete.default="bash:delete_archive_file:cta <eos::wfe::rusername> <eos::wfe::rgroupname> <eos::wfe::fxattr:sys.archiveFileId> <eos::wfe::path>" ${PREPROD_DIR}
+eos attr set sys.workflow.closew.default="proto/cta:ctafrontend:10955 <parent/file>" ${PREPROD_DIR}
+eos attr set sys.workflow.closew.CTA_retrieve="proto/cta:ctafrontend:10955 <parent/file>" ${PREPROD_DIR}
+eos attr set sys.workflow.archived.default="proto/cta:ctafrontend:10955 <parent/file>" ${PREPROD_DIR}
+eos attr set sys.workflow.sync::prepare.default="proto/cta:ctafrontend:10955 <parent/file>" ${PREPROD_DIR}
+eos attr set sys.workflow.sync::delete.default="proto/cta:ctafrontend:10955 <parent/file>" ${PREPROD_DIR}
diff --git a/continuousintegration/orchestration/create_instance.sh b/continuousintegration/orchestration/create_instance.sh
index 87c76607d8fa0807e7b9a3b5b985b9d8ca82674b..709a53d134e9a7f552582c25367bbf994798b662 100755
--- a/continuousintegration/orchestration/create_instance.sh
+++ b/continuousintegration/orchestration/create_instance.sh
@@ -10,6 +10,9 @@ config_database="./database-sqlite.yaml"
 # default library model
 model="mhvtl"
 
+# EOS short instance name
+EOSINSTANCE=ctaeos
+
 # By default keep Database and keep Objectstore
 # default should not make user loose data if he forgot the option
 keepdatabase=1
@@ -275,16 +278,15 @@ kubectl --namespace=${instance} exec ctacli klist
 echo -n "Configuring cta SSS for ctafrontend access from ctaeos"
 for ((i=0; i<300; i++)); do
   echo -n "."
-  [ "`kubectl --namespace=${instance} exec ctafrontend -- bash -c "[ -f /etc/cta/cta-cli.sss.keytab ] && echo -n Ready || echo -n Not ready"`" = "Ready" ] && break
+  [ "`kubectl --namespace=${instance} exec ctaeos -- bash -c "[ -f /etc/eos.keytab ] && echo -n Ready || echo -n Not ready"`" = "Ready" ] && break
   sleep 1
 done
-[ "`kubectl --namespace=${instance} exec ctafrontend -- bash -c "[ -f /etc/cta/cta-cli.sss.keytab ] && echo -n Ready || echo -n Not ready"`" = "Ready" ] || die "TIMED OUT"
-# just in case /etc/cta directory does not exist yet
-kubectl --namespace=${instance} exec -i ctaeos --  bash -c "mkdir -p /etc/cta"
-kubectl --namespace=${instance} exec ctafrontend -- cat /etc/cta/cta-cli.sss.keytab | kubectl --namespace=${instance} exec -i ctaeos --  bash -c "cat > /etc/cta/cta-cli.sss.keytab; chmod 600 /etc/cta/cta-cli.sss.keytab; chown daemon /etc/cta/cta-cli.sss.keytab"
+[ "`kubectl --namespace=${instance} exec ctaeos -- bash -c "[ -f /etc/eos.keytab ] && echo -n Ready || echo -n Not ready"`" = "Ready" ] || die "TIMED OUT"
+kubectl --namespace=${instance} exec ctaeos -- grep ${EOSINSTANCE} /etc/eos.keytab | sed "s/daemon/${EOSINSTANCE}/g" |\
+kubectl --namespace=${instance} exec -i ctafrontend -- \
+bash -c "cat > /etc/cta/eos.sss.keytab.tmp; chmod 400 /etc/cta/eos.sss.keytab.tmp; chown cta:cta /etc/cta/eos.sss.keytab.tmp; mv /etc/cta/eos.sss.keytab.tmp /etc/cta/eos.sss.keytab"
 echo OK
 
-
 echo -n "Waiting for EOS to be configured"
 for ((i=0; i<300; i++)); do
   echo -n "."
@@ -295,6 +297,28 @@ kubectl --namespace=${instance} logs ctaeos | grep -q  "### ctaeos mgm ready ###
 echo OK
 
 
+# Set the workflow rules for archiving, creating tape file replicas in the EOS namespace, retrieving
+# files from tape and deleting files.
+#
+# The closew.CTA_retrieve workflow prevents the default workflow from receiving the closew event, as
+# we don't want to trigger the action of copying the retrived disk file to tape again. The
+# closew.CTA_retrieve workflow sets the CTA_retrieved_timestamp attribute.
+#
+# The FQDN can be set as follows:
+# CTA_ENDPOINT=ctafrontend.${instance}.svc.cluster.local:10955
+#
+# however the simple hostname should be sufficient:
+CTA_ENDPOINT=ctafrontend:10955
+
+echo "Setting workflows in namespace ${instance} pod ctaeos:"
+CTA_WF_DIR=/eos/${EOSINSTANCE}/proc/cta/workflow
+for WORKFLOW in closew.default archived.default sync::prepare.default closew.CTA_retrieve sync::delete.default
+do
+  echo "eos attr set sys.workflow.${WORKFLOW}=\"proto/cta:${CTA_ENDPOINT} <parent/file>\" ${CTA_WF_DIR}"
+  kubectl --namespace=${instance} exec ctaeos -- bash -c "eos attr set sys.workflow.${WORKFLOW}=\"proto/cta:${CTA_ENDPOINT} <parent/file>\" ${CTA_WF_DIR}"
+done
+
+
 echo -n "Copying eos SSS on ctacli and client pods to allow recalls"
 kubectl --namespace=${instance} exec ctaeos cat /etc/eos.keytab | kubectl --namespace=${instance} exec -i ctacli --  bash -c "cat > /etc/eos.keytab; chmod 600 /etc/eos.keytab"
 kubectl --namespace=${instance} exec ctaeos cat /etc/eos.keytab | kubectl --namespace=${instance} exec -i client --  bash -c "cat > /etc/eos.keytab; chmod 600 /etc/eos.keytab"
diff --git a/continuousintegration/orchestration/tests/client_ar.sh b/continuousintegration/orchestration/tests/client_ar.sh
index 87ec5166592d72680c59b0958e8e1be87025a954..96aa0f93c0821288d94d3cea97dd076cf7d9914d 100644
--- a/continuousintegration/orchestration/tests/client_ar.sh
+++ b/continuousintegration/orchestration/tests/client_ar.sh
@@ -202,7 +202,7 @@ if [[ $REMOVE == 1 ]]; then
   else
     # displays what failed and fail
     admin_cta admin ls
-    die "Could not launch cta command."
+    die "Could not launch cta-admin command."
   fi
   # recount the files on tape as the workflows may have gone further...
   INITIALFILESONTAPE=$(admin_cta archivefile ls  --all | grep ${EOS_DIR} | wc -l)
@@ -233,7 +233,7 @@ if [[ $REMOVE == 1 ]]; then
     fi
     FILESONTAPE=$(admin_cta archivefile ls --all > >(grep ${EOS_DIR} | wc -l) 2> >(cat > /tmp/ctaerr))
     if [[ $(cat /tmp/ctaerr | wc -l) -gt 0 ]]; then
-      echo "cta COMMAND FAILED!!"
+      echo "cta-admin COMMAND FAILED!!"
       echo "ERROR CTA ERROR MESSAGE:"
       cat /tmp/ctaerr
       break
diff --git a/cta.spec.in b/cta.spec.in
index ad1893c7d993461cd0f085ba641ee911ea33ae57..51539efc06422a4a1cd11f05bbc2d654c41970fc 100644
--- a/cta.spec.in
+++ b/cta.spec.in
@@ -38,10 +38,10 @@ BuildRequires: xrootd-client-devel = 1:4.2.3
 BuildRequires: xrootd-devel        = 1:4.2.3
 BuildRequires: cryptopp-devel >= 5.6.2
 %else
-BuildRequires: xrootd-client-devel  >= 1:4.8.0
-BuildRequires: xrootd-devel         >= 1:4.8.0
-BuildRequires: xrootd-server-devel  >= 1:4.8.0
-BuildRequires: xrootd-private-devel >= 1:4.8.0
+BuildRequires: xrootd-client-devel  >= 1:4.8.1
+BuildRequires: xrootd-devel         >= 1:4.8.1
+BuildRequires: xrootd-server-devel  >= 1:4.8.1
+BuildRequires: xrootd-private-devel >= 1:4.8.1
 BuildRequires: librados-devel = %{radosVersion}, libradosstriper-devel = %{radosVersion}, 
 BuildRequires: protobuf3-compiler >= 3.3.1 protobuf3-devel >= 3.3.1
 BuildRequires: gmock-devel >= 1.5.0 gtest-devel >= 1.5.0
@@ -113,9 +113,8 @@ CERN Tape Archive:
 The xroot plugin
 %files -n cta-cli
 %defattr(-,root,root)
-%attr(0755,root,root) %{_bindir}/cta.deprecated
 %attr(0755,root,root) %{_bindir}/cta-admin
-%attr(0755,root,root) %{_bindir}/eoscta_stub
+%attr(0755,root,root) %{_bindir}/cta-wfe-test
 %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/cta/cta-cli.conf
 
 %else
@@ -158,7 +157,6 @@ The xroot plugin
 /usr/bin/getent passwd cta || /usr/sbin/useradd -s /bin/nologin -c "CTA system account" -g cta cta
 %files -n cta-frontend
 %defattr(0755,root,root)
-%{_libdir}/libXrdCtaOfs.so*
 %{_libdir}/libXrdSsiCta.so*
 %attr(0755,cta,cta) %dir /var/log/cta
 %attr(0644,root,root) %config(noreplace) /etc/logrotate.d/cta-frontend
@@ -178,9 +176,8 @@ CERN Tape Archive:
 The xroot plugin
 %files -n cta-cli
 %defattr(-,root,root)
-%attr(0755,root,root) %{_bindir}/cta.deprecated
 %attr(0755,root,root) %{_bindir}/cta-admin
-%attr(0755,root,root) %{_bindir}/eoscta_stub
+%attr(0755,root,root) %{_bindir}/cta-wfe-test
 %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/cta/cta-cli.conf
 
 %package -n cta-lib
diff --git a/objectstore/GarbageCollectorTest.cpp b/objectstore/GarbageCollectorTest.cpp
index 2a0a6ea6793cdca40a30114bfe5d78a603229573..7ef84ef2997faa16157b00455aaa7cd4d1d746b6 100644
--- a/objectstore/GarbageCollectorTest.cpp
+++ b/objectstore/GarbageCollectorTest.cpp
@@ -44,7 +44,7 @@ namespace unitTests {
 TEST(ObjectStore, GarbageCollectorBasicFuctionnality) {
   // We will need a log object 
   cta::log::DummyLogger dl("unitTest");
-  cta::catalogue::DummyCatalogue catalogue(dl);
+  cta::catalogue::DummyCatalogue catalogue;
   cta::log::LogContext lc(dl);
   // Here we check for the ability to detect dead (but empty agents)
   // and clean them up.
@@ -98,7 +98,7 @@ TEST(ObjectStore, GarbageCollectorRegister) {
   // We will need a log object 
   cta::log::DummyLogger dl("unitTest");
   cta::log::LogContext lc(dl);
-  cta::catalogue::DummyCatalogue catalogue(dl);
+  cta::catalogue::DummyCatalogue catalogue;
   // Here we check that can successfully call agentRegister's garbage collector
   cta::objectstore::BackendVFS be;
   cta::objectstore::AgentReference agentRef("unitTestGarbageCollector", dl);
@@ -158,7 +158,7 @@ TEST(ObjectStore, GarbageCollectorArchiveQueue) {
   cta::log::DummyLogger dl("unitTest");
   cta::log::LogContext lc(dl);
   // We need a dummy catalogue
-  cta::catalogue::DummyCatalogue catalogue(dl);
+  cta::catalogue::DummyCatalogue catalogue;
   // Here we check that can successfully call agentRegister's garbage collector
   cta::objectstore::BackendVFS be;
   cta::objectstore::AgentReference agentRef("unitTestGarbageCollector", dl);
@@ -218,7 +218,7 @@ TEST(ObjectStore, GarbageCollectorDriveRegister) {
   cta::log::DummyLogger dl("unitTest");
   cta::log::LogContext lc(dl);
   // We need a dummy catalogue
-  cta::catalogue::DummyCatalogue catalogue(dl);
+  cta::catalogue::DummyCatalogue catalogue;
   // Here we check that can successfully call agentRegister's garbage collector
   cta::objectstore::BackendVFS be;
   cta::objectstore::AgentReference agentRef("unitTestGarbageCollector", dl);
@@ -282,7 +282,7 @@ TEST(ObjectStore, GarbageCollectorArchiveRequest) {
 #endif
   cta::log::LogContext lc(dl);
   // We need a dummy catalogue
-  cta::catalogue::DummyCatalogue catalogue(dl);
+  cta::catalogue::DummyCatalogue catalogue;
   // Here we check that can successfully call ArchiveRequests's garbage collector
   cta::objectstore::BackendVFS be;
   // Create the root entry
@@ -480,7 +480,7 @@ TEST(ObjectStore, GarbageCollectorRetrieveRequest) {
 #endif
   cta::log::LogContext lc(dl);
   // We need a dummy catalogue
-  cta::catalogue::DummyCatalogue catalogue(dl);
+  cta::catalogue::DummyCatalogue catalogue;
   // Here we check that can successfully call RetrieveRequests's garbage collector
   cta::objectstore::BackendVFS be;
   // Create the root entry
diff --git a/rdbms/wrapper/OcciStmt.cpp b/rdbms/wrapper/OcciStmt.cpp
index 3337affdf298bc5ee02a4acfa01caf4d740bf939..62f839926dd78dd34e923b7b602478a5b19b7c2d 100644
--- a/rdbms/wrapper/OcciStmt.cpp
+++ b/rdbms/wrapper/OcciStmt.cpp
@@ -17,6 +17,7 @@
  */
 
 #include "common/exception/Exception.hpp"
+#include "common/exception/LostDatabaseConnection.hpp"
 #include "common/make_unique.hpp"
 #include "common/threading/MutexLocker.hpp"
 #include "rdbms/wrapper/OcciColumn.hpp"
@@ -183,6 +184,9 @@ std::unique_ptr<Rset> OcciStmt::executeQuery() {
   try {
     return cta::make_unique<OcciRset>(*this, m_stmt->executeQuery());
   } catch(occi::SQLException &ex) {
+    std::ostringstream msg;
+    msg << std::string(__FUNCTION__) << " failed for SQL statement " << getSqlForException() << ": " << ex.what();
+
     if(connShouldBeClosed(ex)) {
       // Close the statement first and then the connection
       try {
@@ -194,9 +198,9 @@ std::unique_ptr<Rset> OcciStmt::executeQuery() {
         m_conn.close();
       } catch(...) {
       }
+      throw exception::LostDatabaseConnection(msg.str());
     }
-    throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " +
-      getSqlForException() + ": " + ex.what());
+    throw exception::Exception(msg.str());
   }
 }
 
diff --git a/scheduler/OStoreDB/OStoreDBFactory.hpp b/scheduler/OStoreDB/OStoreDBFactory.hpp
index 6aeb7f25e3f5ea8370d85637e81a7cb27ab3af52..6080c3be9e93eb2e6a8ec158a147c29e7f447dd9 100644
--- a/scheduler/OStoreDB/OStoreDBFactory.hpp
+++ b/scheduler/OStoreDB/OStoreDBFactory.hpp
@@ -171,7 +171,7 @@ template <>
 OStoreDBWrapper<cta::objectstore::BackendVFS>::OStoreDBWrapper(
         const std::string &context, const std::string &URL) :
 m_logger(new cta::log::DummyLogger("")), m_backend(new cta::objectstore::BackendVFS()), 
-m_catalogue(new cta::catalogue::DummyCatalogue(*m_logger)),
+m_catalogue(new cta::catalogue::DummyCatalogue),
 m_OStoreDB(*m_backend, *m_catalogue, *m_logger), m_agentReference("OStoreDBFactory", *m_logger) {
   // We need to populate the root entry before using.
   objectstore::RootEntry re(*m_backend);
@@ -198,7 +198,7 @@ template <>
 OStoreDBWrapper<cta::objectstore::BackendRados>::OStoreDBWrapper(
         const std::string &context, const std::string &URL) :
 m_logger(new cta::log::DummyLogger("")), m_backend(cta::objectstore::BackendFactory::createBackend(URL, *m_logger).release()), 
-m_catalogue(new cta::catalogue::DummyCatalogue(*m_logger)),
+m_catalogue(new cta::catalogue::DummyCatalogue),
 m_OStoreDB(*m_backend, *m_catalogue, *m_logger),  m_agentReference("OStoreDBFactory", *m_logger) {
   // We need to first clean up possible left overs in the pool
   auto l = m_backend->list();
diff --git a/scheduler/Scheduler.cpp b/scheduler/Scheduler.cpp
index 93df03ffa7fa9a0d9665ae06c2bf553f6208138d..0c3b6a1eb1077a1d7325ca10379336cdf7a439d7 100644
--- a/scheduler/Scheduler.cpp
+++ b/scheduler/Scheduler.cpp
@@ -418,7 +418,7 @@ std::map<std::string, std::list<common::dataStructures::ArchiveJob> > Scheduler:
 std::list<common::dataStructures::ArchiveJob> Scheduler::getPendingArchiveJobs(const std::string &tapePoolName, log::LogContext & lc) const {
   utils::Timer t;
   if(!m_catalogue.tapePoolExists(tapePoolName)) {
-    throw exception::Exception(std::string("Tape pool ") + tapePoolName + " does not exist");
+    throw exception::UserError(std::string("Tape pool ") + tapePoolName + " does not exist");
   }
   auto catalogueTime = t.secs(utils::Timer::resetCounter);
   auto ret = m_db.getArchiveJobs(tapePoolName);
diff --git a/scheduler/SchedulerTest.cpp b/scheduler/SchedulerTest.cpp
index fe45504f62be2440f6242c14cf7811fb813c5ad5..743b51e6f5a547e1ab0a6552c0ffaa9712b3e29c 100644
--- a/scheduler/SchedulerTest.cpp
+++ b/scheduler/SchedulerTest.cpp
@@ -101,8 +101,10 @@ public:
     m_db = param.dbFactory.create();
     const uint64_t nbConns = 1;
     const uint64_t nbArchiveFileListingConns = 1;
+    const uint32_t maxTriesToConnect = 1;
     //m_catalogue = cta::make_unique<catalogue::SchemaCreatingSqliteCatalogue>(m_tempSqliteFile.path(), nbConns);
-    m_catalogue = cta::make_unique<catalogue::InMemoryCatalogue>(m_dummyLog, nbConns, nbArchiveFileListingConns);
+    m_catalogue = cta::make_unique<catalogue::InMemoryCatalogue>(m_dummyLog, nbConns, nbArchiveFileListingConns,
+      maxTriesToConnect);
     m_scheduler = cta::make_unique<Scheduler>(*m_catalogue, *m_db, 5, 2*1000*1000);
   }
 
diff --git a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp
index ecfe79f902d1a9ae163009af58110aecc9183e5a..e02b2431debb129517ca06f331f48d8cbd95dace 100644
--- a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp
+++ b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp
@@ -118,8 +118,10 @@ public:
     m_db = param.dbFactory.create();
     const uint64_t nbConns = 1;
     const uint64_t nbArchiveFileListingConns = 1;
+    const uint32_t maxTriesToConnect = 1;
     //m_catalogue = cta::make_unique<catalogue::SchemaCreatingSqliteCatalogue>(m_tempSqliteFile.path(), nbConns);
-    m_catalogue = cta::make_unique<catalogue::InMemoryCatalogue>(m_dummyLog, nbConns, nbArchiveFileListingConns);
+    m_catalogue = cta::make_unique<catalogue::InMemoryCatalogue>(m_dummyLog, nbConns, nbArchiveFileListingConns,
+      maxTriesToConnect);
     m_scheduler = cta::make_unique<Scheduler>(*m_catalogue, *m_db, 5, 2*1000*1000);
     
     strncpy(m_tmpDir, "/tmp/DataTransferSessionTestXXXXXX", sizeof(m_tmpDir));
diff --git a/xroot_plugins/CMakeLists.txt b/xroot_plugins/CMakeLists.txt
index 00f3d03843ae9b2baa2c6c5ef9fc78b63e0a44a8..671223ef854917c9166bf1e679b41cedd908310f 100644
--- a/xroot_plugins/CMakeLists.txt
+++ b/xroot_plugins/CMakeLists.txt
@@ -48,27 +48,27 @@ endif (OCCI_SUPPORT)
 #
 # XRootD OFS plugin for CTA Frontend (DEPRECATED)
 #
-add_library (XrdCtaOfs MODULE
-  ListArchiveFilesCmd.cpp
-  XrdCtaFilesystem.cpp
-  XrdCtaFile.cpp
-  XrdCtaDir.cpp)
-if(CMAKE_COMPILER_IS_GNUCC)
-  # Add -Wno-implicit-fallthrough compiler flag if using gcc version 7 or greater
-  if (GCC_VERSION VERSION_EQUAL 7 OR GCC_VERSION VERSION_GREATER 7)
-    set_property(SOURCE XrdCtaFile.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-implicit-fallthrough")
-  endif (GCC_VERSION VERSION_EQUAL 7 OR GCC_VERSION VERSION_GREATER 7)
-endif(CMAKE_COMPILER_IS_GNUCC)
-
-set_property(TARGET XrdCtaOfs PROPERTY SOVERSION "${CTA_SOVERSION}")
-set_property(TARGET XrdCtaOfs PROPERTY   VERSION "${CTA_LIBVERSION}")
-target_link_libraries (XrdCtaOfs ctacatalogue ctascheduler ctacommon ctaobjectstore cryptopp)
-set_property (TARGET XrdCtaOfs APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH})
-if (OCCI_SUPPORT)
-  set_property (TARGET XrdCtaOfs APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH})
-endif (OCCI_SUPPORT)
-
-install (TARGETS XrdCtaOfs DESTINATION usr/${CMAKE_INSTALL_LIBDIR})
+#add_library (XrdCtaOfs MODULE
+#  ListArchiveFilesCmd.cpp
+#  XrdCtaFilesystem.cpp
+#  XrdCtaFile.cpp
+#  XrdCtaDir.cpp)
+#if(CMAKE_COMPILER_IS_GNUCC)
+#  # Add -Wno-implicit-fallthrough compiler flag if using gcc version 7 or greater
+#  if (GCC_VERSION VERSION_EQUAL 7 OR GCC_VERSION VERSION_GREATER 7)
+#    set_property(SOURCE XrdCtaFile.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-implicit-fallthrough")
+#  endif (GCC_VERSION VERSION_EQUAL 7 OR GCC_VERSION VERSION_GREATER 7)
+#endif(CMAKE_COMPILER_IS_GNUCC)
+#
+#set_property(TARGET XrdCtaOfs PROPERTY SOVERSION "${CTA_SOVERSION}")
+#set_property(TARGET XrdCtaOfs PROPERTY   VERSION "${CTA_LIBVERSION}")
+#target_link_libraries (XrdCtaOfs ctacatalogue ctascheduler ctacommon ctaobjectstore cryptopp)
+#set_property (TARGET XrdCtaOfs APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH})
+#if (OCCI_SUPPORT)
+#  set_property (TARGET XrdCtaOfs APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH})
+#endif (OCCI_SUPPORT)
+#
+#install (TARGETS XrdCtaOfs DESTINATION usr/${CMAKE_INSTALL_LIBDIR})
 #
 ####################################################################################################
 
diff --git a/xroot_plugins/XrdSsiCtaServiceProvider.cpp b/xroot_plugins/XrdSsiCtaServiceProvider.cpp
index aeed04b59dde0179ca471c345f6944a2ded06ffb..f31cd337dc3218c324522bdff343ea3a72511b15 100644
--- a/xroot_plugins/XrdSsiCtaServiceProvider.cpp
+++ b/xroot_plugins/XrdSsiCtaServiceProvider.cpp
@@ -50,57 +50,6 @@ XrdSsiProvider *XrdSsiProviderServer = new XrdSsiCtaServiceProvider;
 
 
 
-namespace XrdSsiPb {
-
-/*!
- * Override the Service::Prepare method
- *
- * Ensures that resource.client->name is valid. This is obtained from the KRB5 or SSS key, so
- * connections via unix sockets are not possible in this scheme.
- */
-template<>
-bool Service<cta::xrd::Request, cta::xrd::Response, cta::xrd::Alert>::Prepare(XrdSsiErrInfo &eInfo, const XrdSsiResource &resource)
-{
-   if(resource.client == nullptr || resource.client->name == nullptr)
-   {
-      eInfo.Set("Service::Prepare(): XRootD client name is not set. "
-         "Possible misconfiguration of the KRB5 or SSS keyfile.", EACCES);
-      return false;
-   }
-
-#ifdef XRDSSI_DEBUG
-   std::cerr << "[DEBUG] Service::Prepare():" << std::endl;
-   std::cerr << "[DEBUG]    Resource name: " << resource.rName << std::endl
-             << "[DEBUG]    Resource user: " << resource.rUser << std::endl
-             << "[DEBUG]    Resource info: " << resource.rInfo << std::endl
-             << "[DEBUG]    Hosts to avoid: " << resource.hAvoid << std::endl
-             << "[DEBUG]    Affinity: ";
-
-   switch(resource.affinity)
-   {
-      case XrdSsiResource::None:     std::cerr << "None" << std::endl; break;
-      case XrdSsiResource::Default:  std::cerr << "Default" << std::endl; break;
-      case XrdSsiResource::Weak:     std::cerr << "Weak" << std::endl; break;
-      case XrdSsiResource::Strong:   std::cerr << "Strong" << std::endl; break;
-      case XrdSsiResource::Strict:   std::cerr << "Strict" << std::endl; break;
-   }
-
-   std::cerr << "[DEBUG]    Resource options: "
-             << (resource.rOpts & XrdSsiResource::Reusable ? "Resuable " : "")
-             << (resource.rOpts & XrdSsiResource::Discard  ? "Discard"   : "")
-             << std::endl;
-
-   std::cerr << "[DEBUG]    Resource client protocol: " << resource.client->prot << std::endl;
-   std::cerr << "[DEBUG]    Resource client name: " << resource.client->name << std::endl;
-#endif
-
-   return true;
-}
-
-} // namespace XrdSsiPb
-
-
-
 /*!
  * Initialise the Service Provider
  */
diff --git a/xroot_plugins/cta-frontend-xrootd.conf b/xroot_plugins/cta-frontend-xrootd.conf
index 062bbd45e3f42f4bd5be62fa2602557647dd7850..3bcbffe0e058bb16113df4a60f719a012273edb6 100644
--- a/xroot_plugins/cta-frontend-xrootd.conf
+++ b/xroot_plugins/cta-frontend-xrootd.conf
@@ -1,5 +1,6 @@
 # Load the CTA SSI and OFS plugins
-xrootd.fslib libXrdSsi.so libXrdCtaOfs.so
+#xrootd.fslib libXrdSsi.so libXrdCtaOfs.so
+xrootd.fslib libXrdSsi.so
 
 # Specify which paths are handled by the OFS plugin
 #
@@ -8,10 +9,10 @@ xrootd.fslib libXrdSsi.so libXrdCtaOfs.so
 #
 # Y3Rh is the Base64 encoding of cta, so this string appears at the beginning
 # of all cta admin commands
-ssi.fspath /Y3Rh
+#ssi.fspath /Y3Rh
 # L3Vzci9iaW4vY3Rh is Base64 encoding of /usr/bin/cta which appears at
 # the beginning of commands called from the EOS WFE bash script
-ssi.fspath /L3Vzci9iaW4vY3Rh
+#ssi.fspath /L3Vzci9iaW4vY3Rh
 
 # Load the SSI module
 ssi.svclib libXrdSsiCta.so
@@ -22,7 +23,7 @@ xrootd.seclib libXrdSec.so
 # Protocol specification
 # The xroot server process needs to be able to read the keytab file
 sec.protocol krb5 /etc/cta/cta-frontend.krb5.keytab cta/cta-frontend@TEST.CTA
-sec.protocol sss -s /etc/cta/cta-cli.sss.keytab
+sec.protocol sss -s /etc/cta/eos.sss.keytab
 
 # Only Kerberos 5 and sss are allowed
 sec.protbind * only sss krb5
@@ -41,5 +42,5 @@ all.export /ctafrontend nolock r/w
 # There can be more than one of these; anything that starts with the prefix
 # will go to the the underlying file system. Note that this prefix cannot be
 # a substring of '/ctafrontend', so it is not possible to simply export '/'.
-all.export /Y3Rh
-all.export /L3Vzci9iaW4vY3Rh
+#all.export /Y3Rh
+#all.export /L3Vzci9iaW4vY3Rh
diff --git a/xrootd-ssi-protobuf-interface b/xrootd-ssi-protobuf-interface
index d36f5a1848a4164b9a1182f21614e36e854f3785..1e0d5df3725dade40f968ca55de993a6efc93908 160000
--- a/xrootd-ssi-protobuf-interface
+++ b/xrootd-ssi-protobuf-interface
@@ -1 +1 @@
-Subproject commit d36f5a1848a4164b9a1182f21614e36e854f3785
+Subproject commit 1e0d5df3725dade40f968ca55de993a6efc93908