Commit b2726d0f authored by Steven Murray's avatar Steven Murray
Browse files

cta/CTA#186 CTA should cope with idle database connections being dropped by the database server

Added CatalogueRetryWrapper.hpp
parent e5c83023
......@@ -17,6 +17,7 @@
*/
#include "catalogue/CatalogueFactory.hpp"
#include "catalogue/CatalogueRetryWrapper.hpp"
#include "catalogue/InMemoryCatalogue.hpp"
#include "catalogue/OracleCatalogue.hpp"
#include "catalogue/SqliteCatalogue.hpp"
......@@ -38,13 +39,22 @@ std::unique_ptr<Catalogue> CatalogueFactory::create(
try {
switch(login.dbType) {
case rdbms::Login::DBTYPE_IN_MEMORY:
return cta::make_unique<InMemoryCatalogue>(log, nbConns, nbArchiveFileListingConns, maxTriesToConnect);
{
auto c = cta::make_unique<InMemoryCatalogue>(log, nbConns, nbArchiveFileListingConns, maxTriesToConnect);
return cta::make_unique<CatalogueRetryWrapper>(log, std::move(c), maxTriesToConnect);
}
case rdbms::Login::DBTYPE_ORACLE:
return cta::make_unique<OracleCatalogue>(log, login.username, login.password, login.database, nbConns,
nbArchiveFileListingConns, maxTriesToConnect);
{
auto c = cta::make_unique<OracleCatalogue>(log, login.username, login.password, login.database, nbConns,
nbArchiveFileListingConns, maxTriesToConnect);
return cta::make_unique<CatalogueRetryWrapper>(log, std::move(c), maxTriesToConnect);
}
case rdbms::Login::DBTYPE_SQLITE:
return cta::make_unique<SqliteCatalogue>(log, login.database, nbConns, nbArchiveFileListingConns,
maxTriesToConnect);
{
auto c = cta::make_unique<SqliteCatalogue>(log, login.database, nbConns, nbArchiveFileListingConns,
maxTriesToConnect);
return cta::make_unique<CatalogueRetryWrapper>(log, std::move(c), maxTriesToConnect);
}
case rdbms::Login::DBTYPE_NONE:
throw exception::Exception("Cannot create a catalogue without a database type");
default:
......
This diff is collapsed.
......@@ -140,15 +140,6 @@ 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 =
......@@ -342,15 +333,6 @@ void OracleCatalogue::deleteArchiveFileInternal(const std::string &diskInstanceN
//------------------------------------------------------------------------------
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 *const selectSql =
"SELECT "
......@@ -617,13 +599,6 @@ 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;
......
......@@ -126,64 +126,6 @@ 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.
*
......
......@@ -2194,13 +2194,6 @@ 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 =
......@@ -2232,13 +2225,6 @@ void RdbmsCatalogue::tapeMountedForArchiveInternal(const std::string &vid, const
// 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 =
......@@ -2304,13 +2290,6 @@ 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 "
......@@ -3778,13 +3757,6 @@ 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 =
......@@ -3819,16 +3791,6 @@ void RdbmsCatalogue::tapeLabelledInternal(const std::string &vid, const std::str
//------------------------------------------------------------------------------
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,
......@@ -3974,18 +3936,6 @@ 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,
......@@ -4052,18 +4002,6 @@ 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,
......@@ -4226,13 +4164,6 @@ RequesterAndGroupMountPolicies RdbmsCatalogue::getMountPolicies(
// isAdmin
//------------------------------------------------------------------------------
bool RdbmsCatalogue::isAdmin(const common::dataStructures::SecurityIdentity &admin) const {
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);
......@@ -4283,13 +4214,6 @@ 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 =
......
......@@ -985,155 +985,6 @@ 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
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment