Commit 6fa577bb authored by Steven Murray's avatar Steven Murray
Browse files

cta/CTA#267 Added STORAGE_CLASS_ID column to STORAGE_CLASS table.

parent 9af0c83a
......@@ -139,6 +139,7 @@ void DropSchemaCmd::dropSqliteCatalogueSchema(rdbms::Conn &conn) {
"ADMIN_USER",
"ADMIN_HOST",
"STORAGE_CLASS",
"STORAGE_CLASS_ID",
"TAPE_POOL",
"LOGICAL_LIBRARY",
"MOUNT_POLICY"};
......@@ -191,7 +192,7 @@ void DropSchemaCmd::dropOracleCatalogueSchema(rdbms::Conn &conn) {
dropDatabaseTables(conn, tablesToDrop);
std::list<std::string> sequencesToDrop = {"ARCHIVE_FILE_ID_SEQ"};
std::list<std::string> sequencesToDrop = {"ARCHIVE_FILE_ID_SEQ", "STORAGE_CLASS_ID_SEQ"};
dropDatabaseSequences(conn, sequencesToDrop);
} catch(exception::Exception &ex) {
throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str());
......
......@@ -175,7 +175,7 @@ void OracleCatalogue::deleteArchiveFile(const std::string &diskInstanceName, con
"ARCHIVE_FILE.SIZE_IN_BYTES AS SIZE_IN_BYTES,"
"ARCHIVE_FILE.CHECKSUM_TYPE AS CHECKSUM_TYPE,"
"ARCHIVE_FILE.CHECKSUM_VALUE AS CHECKSUM_VALUE,"
"ARCHIVE_FILE.STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
"STORAGE_CLASS.STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
"ARCHIVE_FILE.CREATION_TIME AS ARCHIVE_FILE_CREATION_TIME,"
"ARCHIVE_FILE.RECONCILIATION_TIME AS RECONCILIATION_TIME,"
"TAPE_FILE.VID AS VID,"
......@@ -186,6 +186,8 @@ void OracleCatalogue::deleteArchiveFile(const std::string &diskInstanceName, con
"TAPE_FILE.CREATION_TIME AS TAPE_FILE_CREATION_TIME "
"FROM "
"ARCHIVE_FILE "
"INNER JOIN STORAGE_CLASS ON "
"ARCHIVE_FILE.STORAGE_CLASS_ID = STORAGE_CLASS.STORAGE_CLASS_ID "
"LEFT OUTER JOIN TAPE_FILE ON "
"ARCHIVE_FILE.ARCHIVE_FILE_ID = TAPE_FILE.ARCHIVE_FILE_ID "
"WHERE "
......@@ -366,7 +368,7 @@ void OracleCatalogue::deleteArchiveFileByDiskFileId(const std::string &diskInsta
"ARCHIVE_FILE.SIZE_IN_BYTES AS SIZE_IN_BYTES,"
"ARCHIVE_FILE.CHECKSUM_TYPE AS CHECKSUM_TYPE,"
"ARCHIVE_FILE.CHECKSUM_VALUE AS CHECKSUM_VALUE,"
"ARCHIVE_FILE.STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
"STORAGE_CLASS.STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
"ARCHIVE_FILE.CREATION_TIME AS ARCHIVE_FILE_CREATION_TIME,"
"ARCHIVE_FILE.RECONCILIATION_TIME AS RECONCILIATION_TIME,"
"TAPE_FILE.VID AS VID,"
......@@ -377,6 +379,8 @@ void OracleCatalogue::deleteArchiveFileByDiskFileId(const std::string &diskInsta
"TAPE_FILE.CREATION_TIME AS TAPE_FILE_CREATION_TIME "
"FROM "
"ARCHIVE_FILE "
"INNER JOIN STORAGE_CLASS ON "
"ARCHIVE_FILE.STORAGE_CLASS_ID = STORAGE_CLASS.STORAGE_CLASS_ID "
"LEFT OUTER JOIN TAPE_FILE ON "
"ARCHIVE_FILE.ARCHIVE_FILE_ID = TAPE_FILE.ARCHIVE_FILE_ID "
"WHERE "
......@@ -524,6 +528,31 @@ uint64_t OracleCatalogue::getNextArchiveFileId(rdbms::Conn &conn) {
}
}
//------------------------------------------------------------------------------
// getNextStorageClassId
//------------------------------------------------------------------------------
uint64_t OracleCatalogue::getNextStorageClassId(rdbms::Conn &conn) {
try {
const char *const sql =
"SELECT "
"STORAGE_CLASS_ID_SEQ.NEXTVAL AS STORAGE_CLASS_ID "
"FROM "
"DUAL";
auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
auto rset = stmt.executeQuery();
if (!rset.next()) {
throw exception::Exception(std::string("Result set is unexpectedly empty"));
}
return rset.columnUint64("STORAGE_CLASS_ID");
} catch(exception::UserError &) {
throw;
} catch(exception::Exception &ex) {
ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
throw;
}
}
//------------------------------------------------------------------------------
// selectTapeForUpdate
//------------------------------------------------------------------------------
......@@ -864,12 +893,12 @@ void OracleCatalogue::idempotentBatchInsertArchiveFiles(rdbms::Conn &conn,
"SIZE_IN_BYTES,"
"CHECKSUM_TYPE,"
"CHECKSUM_VALUE,"
"STORAGE_CLASS_NAME,"
"STORAGE_CLASS_ID,"
"CREATION_TIME,"
"RECONCILIATION_TIME)"
"VALUES("
"SELECT "
":ARCHIVE_FILE_ID,"
":DISK_INSTANCE_NAME,"
"DISK_INSTANCE_NAME,"
":DISK_FILE_ID,"
":DISK_FILE_PATH,"
":DISK_FILE_USER,"
......@@ -878,9 +907,14 @@ void OracleCatalogue::idempotentBatchInsertArchiveFiles(rdbms::Conn &conn,
":SIZE_IN_BYTES,"
":CHECKSUM_TYPE,"
":CHECKSUM_VALUE,"
":STORAGE_CLASS_NAME,"
"STORAGE_CLASS_ID,"
":CREATION_TIME,"
":RECONCILIATION_TIME)";
":RECONCILIATION_TIME "
"FROM "
"STORAGE_CLASS "
"WHERE "
"DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND "
"STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME";
auto stmt = conn.createStmt(sql, autocommitMode);
rdbms::wrapper::OcciStmt &occiStmt = dynamic_cast<rdbms::wrapper::OcciStmt &>(stmt.getStmt());
occiStmt->setBatchErrorMode(true);
......
......@@ -117,6 +117,20 @@ public:
*/
uint64_t getNextArchiveFileId(rdbms::Conn &conn) override;
/**
* Returns a unique storage class ID that can be used by a new storage class
* within the catalogue.
*
* This method must be implemented by the sub-classes of RdbmsCatalogue
* because different database technologies propose different solution to the
* problem of generating ever increasing numeric identifiers.
*
* @param conn The database connection.
* @return a unique archive ID that can be used by a new archive file within
* within the catalogue.
*/
uint64_t getNextStorageClassId(rdbms::Conn &conn) override;
/**
* Notifies the catalogue that the specified files have been written to tape.
*
......
......@@ -20,6 +20,7 @@
#include "catalogue/RdbmsArchiveFileItorImpl.hpp"
#include "common/exception/Exception.hpp"
#include "common/exception/LostDatabaseConnection.hpp"
#include "common/exception/UserError.hpp"
namespace cta {
namespace catalogue {
......@@ -98,7 +99,7 @@ RdbmsArchiveFileItorImpl::RdbmsArchiveFileItorImpl(
"ARCHIVE_FILE.SIZE_IN_BYTES AS SIZE_IN_BYTES,"
"ARCHIVE_FILE.CHECKSUM_TYPE AS CHECKSUM_TYPE,"
"ARCHIVE_FILE.CHECKSUM_VALUE AS CHECKSUM_VALUE,"
"ARCHIVE_FILE.STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
"STORAGE_CLASS.STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
"ARCHIVE_FILE.CREATION_TIME AS ARCHIVE_FILE_CREATION_TIME,"
"ARCHIVE_FILE.RECONCILIATION_TIME AS RECONCILIATION_TIME,"
"TAPE_FILE.VID AS VID,"
......@@ -108,11 +109,13 @@ RdbmsArchiveFileItorImpl::RdbmsArchiveFileItorImpl(
"TAPE_FILE.COPY_NB AS COPY_NB,"
"TAPE_FILE.CREATION_TIME AS TAPE_FILE_CREATION_TIME, "
"TAPE.TAPE_POOL_NAME AS TAPE_POOL_NAME "
"FROM "
"FROM "
"ARCHIVE_FILE "
"LEFT OUTER JOIN TAPE_FILE ON "
"INNER JOIN STORAGE_CLASS ON "
"ARCHIVE_FILE.STORAGE_CLASS_ID = STORAGE_CLASS.STORAGE_CLASS_ID "
"LEFT OUTER JOIN TAPE_FILE ON "
"ARCHIVE_FILE.ARCHIVE_FILE_ID = TAPE_FILE.ARCHIVE_FILE_ID "
"LEFT OUTER JOIN TAPE ON "
"LEFT OUTER JOIN TAPE ON "
"TAPE_FILE.VID = TAPE.VID";
const bool thereIsAtLeastOneSearchCriteria =
......@@ -164,7 +167,7 @@ RdbmsArchiveFileItorImpl::RdbmsArchiveFileItorImpl(
}
if(searchCriteria.storageClass) {
if(addedAWhereConstraint) sql += " AND ";
sql += "ARCHIVE_FILE.STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME";
sql += "STORAGE_CLASS.STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME";
addedAWhereConstraint = true;
}
if(searchCriteria.vid) {
......@@ -233,10 +236,11 @@ RdbmsArchiveFileItorImpl::RdbmsArchiveFileItorImpl(
m_rset = m_stmt.executeQuery();
m_rsetIsEmpty = !m_rset.next();
} 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());
ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
throw;
}
}
......@@ -268,54 +272,61 @@ bool RdbmsArchiveFileItorImpl::hasMore() {
// next
//------------------------------------------------------------------------------
common::dataStructures::ArchiveFile RdbmsArchiveFileItorImpl::next() {
if(!m_hasMoreHasBeenCalled) {
throw exception::Exception(std::string(__FUNCTION__) + " failed: hasMore() must be called before next()");
}
m_hasMoreHasBeenCalled = false;
try {
if(!m_hasMoreHasBeenCalled) {
throw exception::Exception("hasMore() must be called before next()");
}
m_hasMoreHasBeenCalled = false;
// If there are no more rows in the result set
if(m_rsetIsEmpty) {
// There must be an ArchiveFile object currently under construction
if(nullptr == m_archiveFileBuilder.getArchiveFile()) {
throw exception::Exception(std::string(__FUNCTION__) +
" failed: next() was called with no more rows in the result set and no ArchiveFile object under construction");
// If there are no more rows in the result set
if(m_rsetIsEmpty) {
// There must be an ArchiveFile object currently under construction
if(nullptr == m_archiveFileBuilder.getArchiveFile()) {
throw exception::Exception("next() was called with no more rows in the result set and no ArchiveFile object"
" under construction");
}
// Return the ArchiveFile object that must now be complete and clear the
// ArchiveFile builder
auto tmp = *m_archiveFileBuilder.getArchiveFile();
m_archiveFileBuilder.clear();
return tmp;
}
// Return the ArchiveFile object that must now be complete and clear the
// ArchiveFile builder
auto tmp = *m_archiveFileBuilder.getArchiveFile();
m_archiveFileBuilder.clear();
return tmp;
}
while(true) {
auto archiveFile = populateArchiveFile(m_rset);
while(true) {
auto archiveFile = populateArchiveFile(m_rset);
auto completeArchiveFile = m_archiveFileBuilder.append(archiveFile);
auto completeArchiveFile = m_archiveFileBuilder.append(archiveFile);
m_rsetIsEmpty = !m_rset.next();
m_rsetIsEmpty = !m_rset.next();
// If the ArchiveFile object under construction is complete
if (nullptr != completeArchiveFile.get()) {
// If the ArchiveFile object under construction is complete
if (nullptr != completeArchiveFile.get()) {
return *completeArchiveFile;
return *completeArchiveFile;
// The ArchiveFile object under construction is not complete
} else {
if(m_rsetIsEmpty) {
// There must be an ArchiveFile object currently under construction
if (nullptr == m_archiveFileBuilder.getArchiveFile()) {
throw exception::Exception("next() was called with no more rows in the result set and no ArchiveFile object"
" under construction");
}
// The ArchiveFile object under construction is not complete
} else {
if(m_rsetIsEmpty) {
// There must be an ArchiveFile object currently under construction
if (nullptr == m_archiveFileBuilder.getArchiveFile()) {
throw exception::Exception(std::string(__FUNCTION__) + " failed:"
" next() was called with no more rows in the result set and no ArchiveFile object under construction");
// Return the ArchiveFile object that must now be complete and clear the
// ArchiveFile builder
auto tmp = *m_archiveFileBuilder.getArchiveFile();
m_archiveFileBuilder.clear();
return tmp;
}
// Return the ArchiveFile object that must now be complete and clear the
// ArchiveFile builder
auto tmp = *m_archiveFileBuilder.getArchiveFile();
m_archiveFileBuilder.clear();
return tmp;
}
}
} catch(exception::UserError &) {
throw;
} catch(exception::Exception &ex) {
ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
throw;
}
}
......
......@@ -461,9 +461,11 @@ void RdbmsCatalogue::createStorageClass(
throw exception::UserError(std::string("Cannot create storage class ") + storageClass.diskInstance + ":" +
storageClass.name + " because it already exists");
}
const uint64_t storageClassId = getNextStorageClassId(conn);
const time_t now = time(nullptr);
const char *const sql =
"INSERT INTO STORAGE_CLASS("
"STORAGE_CLASS_ID,"
"DISK_INSTANCE_NAME,"
"STORAGE_CLASS_NAME,"
"NB_COPIES,"
......@@ -478,6 +480,7 @@ void RdbmsCatalogue::createStorageClass(
"LAST_UPDATE_HOST_NAME,"
"LAST_UPDATE_TIME)"
"VALUES("
":STORAGE_CLASS_ID,"
":DISK_INSTANCE_NAME,"
":STORAGE_CLASS_NAME,"
":NB_COPIES,"
......@@ -493,6 +496,7 @@ void RdbmsCatalogue::createStorageClass(
":LAST_UPDATE_TIME)";
auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON);
stmt.bindUint64(":STORAGE_CLASS_ID", storageClassId);
stmt.bindString(":DISK_INSTANCE_NAME", storageClass.diskInstance);
stmt.bindString(":STORAGE_CLASS_NAME", storageClass.name);
stmt.bindUint64(":NB_COPIES", storageClass.nbCopies);
......@@ -1218,6 +1222,7 @@ void RdbmsCatalogue::createArchiveRoute(
const char *const sql =
"INSERT INTO ARCHIVE_ROUTE("
"STORAGE_CLASS_ID,"
"DISK_INSTANCE_NAME,"
"STORAGE_CLASS_NAME,"
"COPY_NB,"
......@@ -1232,9 +1237,10 @@ void RdbmsCatalogue::createArchiveRoute(
"LAST_UPDATE_USER_NAME,"
"LAST_UPDATE_HOST_NAME,"
"LAST_UPDATE_TIME)"
"VALUES("
":DISK_INSTANCE_NAME,"
":STORAGE_CLASS_NAME,"
"SELECT "
"STORAGE_CLASS_ID AS STORAGE_CLASS_ID,"
"DISK_INSTANCE_NAME AS DISK_INSTANCE_NAME,"
"STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
":COPY_NB,"
":TAPE_POOL_NAME,"
......@@ -1246,7 +1252,12 @@ void RdbmsCatalogue::createArchiveRoute(
":LAST_UPDATE_USER_NAME,"
":LAST_UPDATE_HOST_NAME,"
":LAST_UPDATE_TIME)";
":LAST_UPDATE_TIME "
"FROM "
"STORAGE_CLASS "
"WHERE "
"DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND "
"STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME";
auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON);
stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName);
......@@ -3726,12 +3737,12 @@ void RdbmsCatalogue::insertArchiveFile(rdbms::Conn &conn, const rdbms::Autocommi
"SIZE_IN_BYTES,"
"CHECKSUM_TYPE,"
"CHECKSUM_VALUE,"
"STORAGE_CLASS_NAME,"
"STORAGE_CLASS_ID,"
"CREATION_TIME,"
"RECONCILIATION_TIME)"
"VALUES("
"SELECT "
":ARCHIVE_FILE_ID,"
":DISK_INSTANCE_NAME,"
"DISK_INSTANCE_NAME,"
":DISK_FILE_ID,"
":DISK_FILE_PATH,"
":DISK_FILE_USER,"
......@@ -3740,9 +3751,14 @@ void RdbmsCatalogue::insertArchiveFile(rdbms::Conn &conn, const rdbms::Autocommi
":SIZE_IN_BYTES,"
":CHECKSUM_TYPE,"
":CHECKSUM_VALUE,"
":STORAGE_CLASS_NAME,"
"STORAGE_CLASS_ID,"
":CREATION_TIME,"
":RECONCILIATION_TIME)";
":RECONCILIATION_TIME "
"FROM "
"STORAGE_CLASS "
"WHERE "
"DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND "
"STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME";
auto stmt = conn.createStmt(sql, autocommitMode);
stmt.bindUint64(":ARCHIVE_FILE_ID", row.archiveFileId);
......@@ -3886,6 +3902,8 @@ common::dataStructures::ArchiveFileSummary RdbmsCatalogue::getTapeFileSummary(
"COUNT(ARCHIVE_FILE.ARCHIVE_FILE_ID) AS TOTAL_FILES "
"FROM "
"ARCHIVE_FILE "
"INNER JOIN STORAGE_CLASS ON "
"ARCHIVE_FILE.STORAGE_CLASS_ID = STORAGE_CLASS.STORAGE_CLASS_ID "
"INNER JOIN TAPE_FILE ON "
"ARCHIVE_FILE.ARCHIVE_FILE_ID = TAPE_FILE.ARCHIVE_FILE_ID "
"INNER JOIN TAPE ON "
......@@ -3938,7 +3956,7 @@ common::dataStructures::ArchiveFileSummary RdbmsCatalogue::getTapeFileSummary(
}
if(searchCriteria.storageClass) {
if(addedAWhereConstraint) sql += " AND ";
sql += "ARCHIVE_FILE.STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME";
sql += "STORAGE_CLASS.STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME";
addedAWhereConstraint = true;
}
if(searchCriteria.vid) {
......@@ -4761,7 +4779,7 @@ std::unique_ptr<common::dataStructures::ArchiveFile> RdbmsCatalogue::getArchiveF
"ARCHIVE_FILE.SIZE_IN_BYTES AS SIZE_IN_BYTES,"
"ARCHIVE_FILE.CHECKSUM_TYPE AS CHECKSUM_TYPE,"
"ARCHIVE_FILE.CHECKSUM_VALUE AS CHECKSUM_VALUE,"
"ARCHIVE_FILE.STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
"STORAGE_CLASS.STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
"ARCHIVE_FILE.CREATION_TIME AS ARCHIVE_FILE_CREATION_TIME,"
"ARCHIVE_FILE.RECONCILIATION_TIME AS RECONCILIATION_TIME,"
"TAPE_FILE.VID AS VID,"
......@@ -4772,6 +4790,8 @@ std::unique_ptr<common::dataStructures::ArchiveFile> RdbmsCatalogue::getArchiveF
"TAPE_FILE.CREATION_TIME AS TAPE_FILE_CREATION_TIME "
"FROM "
"ARCHIVE_FILE "
"INNER JOIN STORAGE_CLASS ON "
"ARCHIVE_FILE.STORAGE_CLASS_ID = STORAGE_CLASS.STORAGE_CLASS_ID "
"LEFT OUTER JOIN TAPE_FILE ON "
"ARCHIVE_FILE.ARCHIVE_FILE_ID = TAPE_FILE.ARCHIVE_FILE_ID "
"WHERE "
......@@ -4845,7 +4865,7 @@ std::unique_ptr<common::dataStructures::ArchiveFile> RdbmsCatalogue::getArchiveF
"ARCHIVE_FILE.SIZE_IN_BYTES AS SIZE_IN_BYTES,"
"ARCHIVE_FILE.CHECKSUM_TYPE AS CHECKSUM_TYPE,"
"ARCHIVE_FILE.CHECKSUM_VALUE AS CHECKSUM_VALUE,"
"ARCHIVE_FILE.STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
"STORAGE_CLASS.STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
"ARCHIVE_FILE.CREATION_TIME AS ARCHIVE_FILE_CREATION_TIME,"
"ARCHIVE_FILE.RECONCILIATION_TIME AS RECONCILIATION_TIME,"
"TAPE_FILE.VID AS VID,"
......@@ -4856,6 +4876,8 @@ std::unique_ptr<common::dataStructures::ArchiveFile> RdbmsCatalogue::getArchiveF
"TAPE_FILE.CREATION_TIME AS TAPE_FILE_CREATION_TIME "
"FROM "
"ARCHIVE_FILE "
"INNER JOIN STORAGE_CLASS ON "
"ARCHIVE_FILE.STORAGE_CLASS_ID = STORAGE_CLASS.STORAGE_CLASS_ID "
"LEFT OUTER JOIN TAPE_FILE ON "
"ARCHIVE_FILE.ARCHIVE_FILE_ID = TAPE_FILE.ARCHIVE_FILE_ID "
"WHERE "
......
......@@ -1130,6 +1130,20 @@ protected:
*/
virtual uint64_t getNextArchiveFileId(rdbms::Conn &conn) = 0;
/**
* Returns a unique storage class ID that can be used by a new storage class
* within the catalogue.
*
* This method must be implemented by the sub-classes of RdbmsCatalogue
* because different database technologies propose different solution to the
* problem of generating ever increasing numeric identifiers.
*
* @param conn The database connection.
* @return a unique archive ID that can be used by a new archive file within
* within the catalogue.
*/
virtual uint64_t getNextStorageClassId(rdbms::Conn &conn) = 0;
/**
* Returns a cached version of the mapping from tape copy to tape pool for the
* specified storage class.
......
......@@ -302,6 +302,39 @@ uint64_t SqliteCatalogue::getNextArchiveFileId(rdbms::Conn &conn) {
}
}
//------------------------------------------------------------------------------
// getNextStorageClassId
//------------------------------------------------------------------------------
uint64_t SqliteCatalogue::getNextStorageClassId(rdbms::Conn &conn) {
// The SQLite implemenation of getNextStorageClassId() serializes access to
// the SQLite database in order to avoid busy errors
threading::MutexLocker locker(m_mutex);
rdbms::AutoRollback autoRollback(conn);
conn.executeNonQuery("UPDATE STORAGE_CLASS_ID SET ID = ID + 1", rdbms::AutocommitMode::OFF);
uint64_t storageClassId = 0;
{
const char *const sql =
"SELECT "
"ID AS ID "
"FROM "
"STORAGE_CLASS_ID";
auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
auto rset = stmt.executeQuery();
if(!rset.next()) {
throw exception::Exception("STORAGE_CLASS_ID table is empty");
}
storageClassId = rset.columnUint64("ID");
if(rset.next()) {
throw exception::Exception("Found more than one ID counter in the STORAGE_CLASS_ID table");
}
}
conn.commit();
return storageClassId;
}
//------------------------------------------------------------------------------
// selectTapeForUpdate
//------------------------------------------------------------------------------
......
......@@ -122,6 +122,20 @@ protected:
*/
uint64_t getNextArchiveFileId(rdbms::Conn &conn) override;
/**
* Returns a unique storage class ID that can be used by a new storage class
* within the catalogue.
*
* This method must be implemented by the sub-classes of RdbmsCatalogue
* because different database technologies propose different solution to the
* problem of generating ever increasing numeric identifiers.
*
* @param conn The database connection.
* @return a unique archive ID that can be used by a new archive file within
* within the catalogue.
*/
uint64_t getNextStorageClassId(rdbms::Conn &conn) override;
/**
* Notifies the catalogue that the specified files have been written to tape.
*
......
......@@ -25,6 +25,7 @@ CREATE TABLE ADMIN_HOST(
CONSTRAINT ADMIN_HOST_PK PRIMARY KEY(ADMIN_HOST_NAME)
);
CREATE TABLE STORAGE_CLASS(
STORAGE_CLASS_ID INTEGER CONSTRAINT STORAGE_CLASS_SCI_NN NOT NULL,
DISK_INSTANCE_NAME VARCHAR2(100) CONSTRAINT STORAGE_CLASS_DIN_NN NOT NULL,
STORAGE_CLASS_NAME VARCHAR2(100) CONSTRAINT STORAGE_CLASS_SCN_NN NOT NULL,
NB_COPIES INTEGER CONSTRAINT STORAGE_CLASS_NC_NN NOT NULL,
......@@ -35,7 +36,8 @@ CREATE TABLE STORAGE_CLASS(
LAST_UPDATE_USER_NAME VARCHAR2(100) CONSTRAINT STORAGE_CLASS_LUUN_NN NOT NULL,
LAST_UPDATE_HOST_NAME VARCHAR2(100) CONSTRAINT STORAGE_CLASS_LUHN_NN NOT NULL,
LAST_UPDATE_TIME INTEGER CONSTRAINT STORAGE_CLASS_LUT_NN NOT NULL,
CONSTRAINT STORAGE_CLASS_PK PRIMARY KEY(DISK_INSTANCE_NAME, STORAGE_CLASS_NAME)
CONSTRAINT STORAGE_CLASS_PK PRIMARY KEY(STORAGE_CLASS_ID),
CONSTRAINT STORAGE_CLASS_DIN_SCN_UN UNIQUE(DISK_INSTANCE_NAME, STORAGE_CLASS_NAME)
);
CREATE TABLE TAPE_POOL(
TAPE_POOL_NAME VARCHAR2(100) CONSTRAINT TAPE_POOL_TPN_NN NOT NULL,
......@@ -52,6 +54,7 @@ CREATE TABLE TAPE_POOL(
CONSTRAINT TAPE_POOL_IS_ENCRYPTED_BOOL_CK CHECK(IS_ENCRYPTED IN (0, 1))
);
CREATE TABLE ARCHIVE_ROUTE(
STORAGE_CLASS_ID INTEGER CONSTRAINT ARCHIVE_ROUTE_SCI_NN NOT NULL,
DISK_INSTANCE_NAME VARCHAR2(100) CONSTRAINT ARCHIVE_ROUTE_DIN_NN NOT NULL,
STORAGE_CLASS_NAME VARCHAR2(100) CONSTRAINT ARCHIVE_ROUTE_SCN_NN NOT NULL,
COPY_NB INTEGER CONSTRAINT ARCHIVE_ROUTE_CN_NN NOT NULL,
......@@ -64,7 +67,8 @@ CREATE TABLE ARCHIVE_ROUTE(
LAST_UPDATE_HOST_NAME VARCHAR2(100) CONSTRAINT ARCHIVE_ROUTE_LUHN_NN NOT NULL,
LAST_UPDATE_TIME INTEGER CONSTRAINT ARCHIVE_ROUTE_LUT_NN NOT NULL,
CONSTRAINT ARCHIVE_ROUTE_PK PRIMARY KEY(DISK_INSTANCE_NAME, STORAGE_CLASS_NAME, COPY_NB),
CONSTRAINT ARCHIVE_ROUTE_STORAGE_CLASS_FK FOREIGN KEY(DISK_INSTANCE_NAME, STORAGE_CLASS_NAME)
CONSTRAINT ARCHIVE_ROUTE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),
CONSTRAINT ARCHIVE_ROUTE_SC_FK FOREIGN KEY(DISK_INSTANCE_NAME, STORAGE_CLASS_NAME)
REFERENCES STORAGE_CLASS(DISK_INSTANCE_NAME, STORAGE_CLASS_NAME),
CONSTRAINT ARCHIVE_ROUTE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_NAME)
REFERENCES TAPE_POOL(TAPE_POOL_NAME)
......@@ -170,12 +174,11 @@ CREATE TABLE ARCHIVE_FILE(
SIZE_IN_BYTES INTEGER CONSTRAINT ARCHIVE_FILE_SIB_NN NOT NULL,
CHECKSUM_TYPE VARCHAR2(100) CONSTRAINT ARCHIVE_FILE_CT1_NN NOT NULL,
CHECKSUM_VALUE VARCHAR2(100) CONSTRAINT ARCHIVE_FILE_CV_NN NOT NULL,
STORAGE_CLASS_NAME VARCHAR2(100) CONSTRAINT ARCHIVE_FILE_SCN_NN NOT NULL,
STORAGE_CLASS_ID INTEGER CONSTRAINT ARCHIVE_FILE_SCI_NN NOT NULL,
CREATION_TIME INTEGER CONSTRAINT ARCHIVE_FILE_CT2_NN NOT NULL,
RECONCILIATION_TIME INTEGER CONSTRAINT ARCHIVE_FILE_RT_NN NOT NULL,
CONSTRAINT ARCHIVE_FILE_PK PRIMARY KEY(ARCHIVE_FILE_ID),
CONSTRAINT ARCHIVE_FILE_STORAGE_CLASS_FK FOREIGN KEY(DISK_INSTANCE_NAME, STORAGE_CLASS_NAME)
REFERENCES STORAGE_CLASS(DISK_INSTANCE_NAME, STORAGE_CLASS_NAME),
CONSTRAINT ARCHIVE_FILE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),
CONSTRAINT ARCHIVE_FILE_DIN_DFI_UN UNIQUE(DISK_INSTANCE_NAME, DISK_FILE_ID)
);
CREATE INDEX ARCHIVE_FILE_DIN_DFP_IDX ON ARCHIVE_FILE(DISK_INSTANCE_NAME, DISK_FILE_PATH);
......
......@@ -6,6 +6,14 @@ CREATE SEQUENCE ARCHIVE_FILE_ID_SEQ
NOCYCLE
CACHE 20
NOORDER;
CREATE SEQUENCE STORAGE_CLASS_ID_SEQ
INCREMENT BY 1
START WITH 1
NOMAXVALUE
MINVALUE 1
NOCYCLE
CACHE 20
NOORDER;
CREATE GLOBAL TEMPORARY TABLE TEMP_TAPE_FILE_BATCH(
ARCHIVE_FILE_ID INTEGER
)
......
......@@ -3,3 +3,8 @@ CREATE TABLE ARCHIVE_FILE_ID(
CONSTRAINT ARCHIVE_FILE_ID_PK PRIMARY KEY(ID)
);
INSERT INTO ARCHIVE_FILE_ID(ID) VALUES(1);
CREATE TABLE STORAGE_CLASS_ID(
ID INTEGER,
CONSTRAINT STORAGE_CLASS_ID_PK PRIMARY KEY(ID)
);
INSERT INTO STORAGE_CLASS_ID(ID) VALUES(1);
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