Commit 8fe1b551 authored by Steven Murray's avatar Steven Murray
Browse files

Catalogue::createArchiveRoute() explains more user errors

parent a2553244
......@@ -1241,6 +1241,50 @@ TEST_P(cta_catalogue_CatalogueTest, createArchiveRoute) {
const common::dataStructures::EntryLog lastModificationLog = route.lastModificationLog;
ASSERT_EQ(creationLog, lastModificationLog);
}
TEST_P(cta_catalogue_CatalogueTest, createArchiveRoute_non_existent_storage_class) {
using namespace cta;
ASSERT_TRUE(m_catalogue->getStorageClasses().empty());
ASSERT_TRUE(m_catalogue->getTapePools().empty());
ASSERT_TRUE(m_catalogue->getArchiveRoutes().empty());
const std::string diskInstanceName = "disk_instance";
const std::string storageClassName = "storage_class";
const std::string tapePoolName = "tape_pool";
const uint64_t nbPartialTapes = 2;
const bool isEncrypted = true;
m_catalogue->createTapePool(m_admin, tapePoolName, nbPartialTapes, isEncrypted, "Create tape pool");
const uint64_t copyNb = 1;
const std::string comment = "Create archive route";
ASSERT_THROW(m_catalogue->createArchiveRoute(m_admin, diskInstanceName, storageClassName, copyNb, tapePoolName,
comment), exception::UserError);
}
TEST_P(cta_catalogue_CatalogueTest, createArchiveRoute_non_existent_tape_pool) {
using namespace cta;
ASSERT_TRUE(m_catalogue->getStorageClasses().empty());
ASSERT_TRUE(m_catalogue->getTapePools().empty());
ASSERT_TRUE(m_catalogue->getArchiveRoutes().empty());
common::dataStructures::StorageClass storageClass;
storageClass.diskInstance = "disk_instance";
storageClass.name = "storage_class";
storageClass.nbCopies = 2;
storageClass.comment = "Create storage class";
m_catalogue->createStorageClass(m_admin, storageClass);
const std::string tapePoolName = "tape_pool";
const uint64_t copyNb = 1;
const std::string comment = "Create archive route";
ASSERT_THROW(m_catalogue->createArchiveRoute(m_admin, storageClass.diskInstance, storageClass.name, copyNb,
tapePoolName, comment), exception::UserError);
}
TEST_P(cta_catalogue_CatalogueTest, createArchiveRoute_same_name_different_disk_instance) {
using namespace cta;
......@@ -1301,7 +1345,7 @@ TEST_P(cta_catalogue_CatalogueTest, createArchiveRoute_same_name_different_disk_
}
}
TEST_P(cta_catalogue_CatalogueTest, createArchiveRouteTapePool_same_twice) {
TEST_P(cta_catalogue_CatalogueTest, createArchiveRoute_same_twice) {
using namespace cta;
ASSERT_TRUE(m_catalogue->getStorageClasses().empty());
......
......@@ -765,6 +765,34 @@ bool RdbmsCatalogue::tapePoolExists(rdbms::Conn &conn, const std::string &tapePo
}
}
//------------------------------------------------------------------------------
// archiveRouteExists
//------------------------------------------------------------------------------
bool RdbmsCatalogue::archiveRouteExists(rdbms::Conn &conn, const std::string &diskInstanceName,
const std::string &storageClassName, const uint64_t copyNb) const {
try {
const char *const sql =
"SELECT "
"DISK_INSTANCE_NAME AS DISK_INSTANCE_NAME,"
"STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
"COPY_NB AS COPY_NB "
"FROM "
"ARCHIVE_ROUTE "
"WHERE "
"DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND "
"STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME AND "
"COPY_NB = :COPY_NB";
auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF);
stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName);
stmt->bindString(":STORAGE_CLASS_NAME", storageClassName);
stmt->bindUint64(":COPY_NB", copyNb);
auto rset = stmt->executeQuery();
return rset->next();
} catch (exception::Exception &ex) {
throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str());
}
}
//------------------------------------------------------------------------------
// deleteTapePool
//------------------------------------------------------------------------------
......@@ -948,6 +976,27 @@ void RdbmsCatalogue::createArchiveRoute(
const std::string &comment) {
try {
const time_t now = time(nullptr);
auto conn = m_connPool.getConn();
if(archiveRouteExists(*conn, diskInstanceName, storageClassName, copyNb)) {
exception::UserError ue;
ue.getMessage() << "Cannot create archive route " << diskInstanceName << ":" << storageClassName << "," << copyNb
<< "->" << tapePoolName << " because it already exists";
throw ue;
}
if(!storageClassExists(*conn, diskInstanceName, storageClassName)) {
exception::UserError ue;
ue.getMessage() << "Cannot create archive route " << diskInstanceName << ":" << storageClassName << "," << copyNb
<< "->" << tapePoolName << " because storage class " << diskInstanceName << ":" << storageClassName <<
" does not exist";
throw ue;
}
if(!tapePoolExists(*conn, tapePoolName)) {
exception::UserError ue;
ue.getMessage() << "Cannot create archive route " << diskInstanceName << ":" << storageClassName << "," << copyNb
<< "->" << tapePoolName << " because tape pool " << tapePoolName + " does not exist";
throw ue;
}
const char *const sql =
"INSERT INTO ARCHIVE_ROUTE("
"DISK_INSTANCE_NAME,"
......@@ -979,7 +1028,6 @@ void RdbmsCatalogue::createArchiveRoute(
":LAST_UPDATE_USER_NAME,"
":LAST_UPDATE_HOST_NAME,"
":LAST_UPDATE_TIME)";
auto conn = m_connPool.getConn();
auto stmt = conn->createStmt(sql, rdbms::Stmt::AutocommitMode::ON);
stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName);
......@@ -998,6 +1046,8 @@ void RdbmsCatalogue::createArchiveRoute(
stmt->bindUint64(":LAST_UPDATE_TIME", now);
stmt->executeNonQuery();
} catch(exception::UserError &) {
throw;
} catch(exception::Exception &ex) {
throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str());
}
......
......@@ -545,7 +545,8 @@ protected:
* @param storageClassName The name of the storage class.
* @return True if the storage class exists.
*/
bool storageClassExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &storageClassName) const;
bool storageClassExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &storageClassName)
const;
/**
* Returns true if the specified tape pool exists.
......@@ -556,6 +557,20 @@ protected:
*/
bool tapePoolExists(rdbms::Conn &conn, const std::string &tapePoolName) const;
/**
* Returns true if the specified archive route exists.
*
* @param conn The database connection.
* @param diskInstanceName The name of the disk instance to which the storage
* class belongs.
* @param storageClassName The name of the storage class which is only
* guaranteed to be unique within its disk instance.
* @param copyNb The copy number of the tape file.
* @return True if the archive route exists.
*/
bool archiveRouteExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &storageClassName,
const uint64_t copyNb) const;
/**
* Returns true if the specified tape exists.
*
......
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