Commit 278a5b15 authored by Steven Murray's avatar Steven Murray
Browse files

Added SqliteCatalogue unit-tests createArchiveFile and createArchiveFile_same_twice

parent 3bbcc931
......@@ -245,6 +245,38 @@ void cta::catalogue::SqliteCatalogue::createDbSchema() {
"PRIMARY KEY(USER_NAME),"
"FOREIGN KEY(MOUNT_GROUP_NAME) REFERENCES "
"MOUNT_GROUP(MOUNT_GROUP_NAME)"
");"
"CREATE TABLE ARCHIVE_FILE("
"ARCHIVE_FILE_ID INTEGER AUTO INCREMENT,"
"DISK_INSTANCE STRING,"
"DISK_FILE_ID STRING,"
"FILE_SIZE INTEGER,"
"CHECKSUM_TYPE STRING,"
"CHECKSUM_VALUE STRING,"
"STORAGE_CLASS_NAME STRING,"
"CREATION_TIME INTEGER,"
"RECOVERY_PATH STRING,"
"RECOVERY_OWNER STRING,"
"RECOVERY_GROUP STRING,"
"RECOVERY_BLOB STRING,"
"PRIMARY KEY(ARCHIVE_FILE_ID),"
"FOREIGN KEY(STORAGE_CLASS_NAME) "
"REFERENCES STORAGE_CLASS(STORAGE_CLASS_NAME),"
"UNIQUE(DISK_INSTANCE, DISK_FILE_ID)"
");"
"CREATE TABLE TAPE_FILE("
"VID STRING,"
"FSEQ INTEGER,"
"BLOCK_ID INTEGER,"
"CREATION_TIME INTEGER,"
"ARCHIVE_FILE_ID INTEGER,"
"PRIMARY KEY(VID, FSEQ),"
"FOREIGN KEY(ARCHIVE_FILE_ID) "
"REFERENCES ARCHIVE_FILE(ARCHIVE_FILE_ID),"
"UNIQUE(FSEQ, BLOCK_ID)"
");";
m_conn.enableForeignKeys();
m_conn.execNonQuery(sql);
......@@ -351,7 +383,7 @@ std::list<cta::common::dataStructures::AdminUser>
"LAST_MOD_TIME AS LAST_MOD_TIME "
"FROM ADMIN_USER;";
std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql));
ColumnNameToIdx nameToIdx;
ColumnNameToIdx nameToIdx;
while(SQLITE_ROW == stmt->step()) {
if(nameToIdx.empty()) {
nameToIdx = stmt->getColumnNameToIdx();
......@@ -477,7 +509,7 @@ std::list<cta::common::dataStructures::AdminHost> cta::catalogue::SqliteCatalogu
"LAST_MOD_TIME AS LAST_MOD_TIME "
"FROM ADMIN_HOST;";
std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql));
ColumnNameToIdx nameToIdx;
ColumnNameToIdx nameToIdx;
while(SQLITE_ROW == stmt->step()) {
if(nameToIdx.empty()) {
nameToIdx = stmt->getColumnNameToIdx();
......@@ -604,7 +636,7 @@ std::list<cta::common::dataStructures::StorageClass>
"LAST_MOD_TIME AS LAST_MOD_TIME "
"FROM STORAGE_CLASS;";
std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql));
ColumnNameToIdx nameToIdx;
ColumnNameToIdx nameToIdx;
while(SQLITE_ROW == stmt->step()) {
if(nameToIdx.empty()) {
nameToIdx = stmt->getColumnNameToIdx();
......@@ -742,7 +774,7 @@ std::list<cta::common::dataStructures::TapePool>
"LAST_MOD_TIME AS LAST_MOD_TIME "
"FROM TAPE_POOL;";
std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql));
ColumnNameToIdx nameToIdx;
ColumnNameToIdx nameToIdx;
while(SQLITE_ROW == stmt->step()) {
if(nameToIdx.empty()) {
nameToIdx = stmt->getColumnNameToIdx();
......@@ -887,7 +919,7 @@ std::list<cta::common::dataStructures::ArchiveRoute>
"LAST_MOD_TIME AS LAST_MOD_TIME "
"FROM ARCHIVE_ROUTE;";
std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql));
ColumnNameToIdx nameToIdx;
ColumnNameToIdx nameToIdx;
while(SQLITE_ROW == stmt->step()) {
if(nameToIdx.empty()) {
nameToIdx = stmt->getColumnNameToIdx();
......@@ -1017,7 +1049,7 @@ std::list<cta::common::dataStructures::LogicalLibrary>
"LAST_MOD_TIME AS LAST_MOD_TIME "
"FROM LOGICAL_LIBRARY;";
std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql));
ColumnNameToIdx nameToIdx;
ColumnNameToIdx nameToIdx;
while(SQLITE_ROW == stmt->step()) {
if(nameToIdx.empty()) {
nameToIdx = stmt->getColumnNameToIdx();
......@@ -1230,7 +1262,7 @@ std::list<cta::common::dataStructures::Tape>
"LAST_MOD_TIME AS LAST_MOD_TIME "
"FROM TAPE;";
std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql));
ColumnNameToIdx nameToIdx;
ColumnNameToIdx nameToIdx;
while(SQLITE_ROW == stmt->step()) {
if(nameToIdx.empty()) {
nameToIdx = stmt->getColumnNameToIdx();
......@@ -1443,7 +1475,7 @@ std::list<cta::common::dataStructures::User>
"LAST_MOD_TIME AS LAST_MOD_TIME "
"FROM USER;";
std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql));
ColumnNameToIdx nameToIdx;
ColumnNameToIdx nameToIdx;
while(SQLITE_ROW == stmt->step()) {
if(nameToIdx.empty()) {
nameToIdx = stmt->getColumnNameToIdx();
......@@ -1631,7 +1663,7 @@ std::list<cta::common::dataStructures::MountGroup>
"LAST_MOD_TIME AS LAST_MOD_TIME "
"FROM MOUNT_GROUP;";
std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql));
ColumnNameToIdx nameToIdx;
ColumnNameToIdx nameToIdx;
while(SQLITE_ROW == stmt->step()) {
if(nameToIdx.empty()) {
nameToIdx = stmt->getColumnNameToIdx();
......@@ -1791,12 +1823,142 @@ void cta::catalogue::SqliteCatalogue::modifyDedicationUntil(const common::dataSt
//------------------------------------------------------------------------------
void cta::catalogue::SqliteCatalogue::modifyDedicationComment(const common::dataStructures::SecurityIdentity &cliIdentity, const std::string &drivename, const std::string &comment) {}
//------------------------------------------------------------------------------
// createArchiveFile
//------------------------------------------------------------------------------
uint64_t cta::catalogue::SqliteCatalogue::createArchiveFile(
const common::dataStructures::ArchiveFile &archiveFile) {
const time_t now = time(NULL);
const char *const sql =
"INSERT INTO ARCHIVE_FILE("
"DISK_INSTANCE,"
"DISK_FILE_ID,"
"FILE_SIZE,"
"CHECKSUM_TYPE,"
"CHECKSUM_VALUE,"
"STORAGE_CLASS_NAME,"
"CREATION_TIME,"
"RECOVERY_PATH,"
"RECOVERY_OWNER,"
"RECOVERY_GROUP,"
"RECOVERY_BLOB)"
"VALUES("
":DISK_INSTANCE,"
":DISK_FILE_ID,"
":FILE_SIZE,"
":CHECKSUM_TYPE,"
":CHECKSUM_VALUE,"
":STORAGE_CLASS_NAME,"
":CREATION_TIME,"
":RECOVERY_PATH,"
":RECOVERY_OWNER,"
":RECOVERY_GROUP,"
":RECOVERY_BLOB);";
std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql));
stmt->bind(":DISK_INSTANCE", archiveFile.drData.drInstance);
stmt->bind(":DISK_FILE_ID", archiveFile.eosFileID);
stmt->bind(":FILE_SIZE", archiveFile.fileSize);
stmt->bind(":CHECKSUM_TYPE", archiveFile.checksumType);
stmt->bind(":CHECKSUM_VALUE", archiveFile.checksumValue);
stmt->bind(":STORAGE_CLASS_NAME", archiveFile.storageClass);
stmt->bind(":CREATION_TIME", now);
stmt->bind(":RECOVERY_PATH", archiveFile.drData.drPath);
stmt->bind(":RECOVERY_OWNER", archiveFile.drData.drOwner);
stmt->bind(":RECOVERY_GROUP", archiveFile.drData.drGroup);
stmt->bind(":RECOVERY_BLOB", archiveFile.drData.drBlob);
stmt->step();
return getArchiveFileId(archiveFile.drData.drInstance, archiveFile.eosFileID);
}
//------------------------------------------------------------------------------
// getArchiveFileId
//------------------------------------------------------------------------------
uint64_t cta::catalogue::SqliteCatalogue::getArchiveFileId(
const std::string &diskInstance, const std::string &diskFileId) const {
const char *const sql =
"SELECT "
"ARCHIVE_FILE_ID AS ARCHIVE_FILE_ID "
"FROM ARCHIVE_FILE WHERE "
"DISK_INSTANCE = :DISK_INSTANCE AND "
"DISK_FILE_ID = :DISK_FILE_ID;";
std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql));
stmt->bind(":DISK_INSTANCE", diskInstance);
stmt->bind(":DISK_FILE_ID", diskFileId);
if(SQLITE_ROW != stmt->step()) {
exception::Exception ex;
ex.getMessage() << __FUNCTION__ << " failed"
": Could not find archive file from disk instance " << diskInstance <<
" with disk file ID " << diskFileId;
throw ex;
} else {
const ColumnNameToIdx nameToIdx = stmt->getColumnNameToIdx();
return stmt->columnUint64(nameToIdx["ARCHIVE_FILE_ID"]);
}
}
//------------------------------------------------------------------------------
// getArchiveFiles
//------------------------------------------------------------------------------
std::list<cta::common::dataStructures::ArchiveFile> cta::catalogue::SqliteCatalogue::getArchiveFiles(const uint64_t id, const std::string &eosid,
const std::string &copynb, const std::string &tapepool, const std::string &vid, const std::string &owner, const std::string &group, const std::string &storageclass, const std::string &path) {
return std::list<cta::common::dataStructures::ArchiveFile>();
std::list<cta::common::dataStructures::ArchiveFile>
cta::catalogue::SqliteCatalogue::getArchiveFiles(
const uint64_t id,
const std::string &eosid,
const std::string &copynb,
const std::string &tapepool,
const std::string &vid,
const std::string &owner,
const std::string &group,
const std::string &storageclass,
const std::string &path) {
std::list<cta::common::dataStructures::ArchiveFile> files;
const char *const sql =
"SELECT "
"DISK_INSTANCE AS DISK_INSTANCE,"
"DISK_FILE_ID AS DISK_FILE_ID,"
"FILE_SIZE AS FILE_SIZE,"
"CHECKSUM_TYPE AS CHECKSUM_TYPE,"
"CHECKSUM_VALUE AS CHECKSUM_VALUE,"
"STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
"CREATION_TIME AS CREATION_TIME,"
"RECOVERY_PATH AS RECOVERY_PATH,"
"RECOVERY_OWNER AS RECOVERY_OWNER,"
"RECOVERY_GROUP AS RECOVERY_GROUP,"
"RECOVERY_BLOB AS RECOVERY_BLOB "
"FROM ARCHIVE_FILE;";
std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql));
ColumnNameToIdx nameToIdx;
while(SQLITE_ROW == stmt->step()) {
if(nameToIdx.empty()) {
nameToIdx = stmt->getColumnNameToIdx();
}
common::dataStructures::ArchiveFile file;
file.archiveFileID = id;
file.eosFileID = stmt->columnText(nameToIdx["DISK_FILE_ID"]);
file.fileSize = stmt->columnUint64(nameToIdx["FILE_SIZE"]);
file.checksumType = stmt->columnText(nameToIdx["CHECKSUM_TYPE"]);
file.checksumValue = stmt->columnText(nameToIdx["CHECKSUM_VALUE"]);
file.storageClass = stmt->columnText(nameToIdx["STORAGE_CLASS_NAME"]);
file.drData.drInstance = stmt->columnText(nameToIdx["DISK_INSTANCE"]);
file.drData.drPath = stmt->columnText(nameToIdx["RECOVERY_PATH"]);
file.drData.drOwner = stmt->columnText(nameToIdx["RECOVERY_OWNER"]);
file.drData.drGroup = stmt->columnText(nameToIdx["RECOVERY_GROUP"]);
file.drData.drBlob = stmt->columnText(nameToIdx["RECOVERY_BLOB"]);
files.push_back(file);
}
return files;
}
//------------------------------------------------------------------------------
......@@ -1810,8 +1972,52 @@ cta::common::dataStructures::ArchiveFileSummary cta::catalogue::SqliteCatalogue:
//------------------------------------------------------------------------------
// getArchiveFileById
//------------------------------------------------------------------------------
cta::common::dataStructures::ArchiveFile cta::catalogue::SqliteCatalogue::getArchiveFileById(const uint64_t id){
return cta::common::dataStructures::ArchiveFile();
cta::common::dataStructures::ArchiveFile cta::catalogue::SqliteCatalogue::
getArchiveFileById(const uint64_t id) {
const char *const sql =
"SELECT "
"DISK_INSTANCE AS DISK_INSTANCE,"
"DISK_FILE_ID AS DISK_FILE_ID,"
"FILE_SIZE AS FILE_SIZE,"
"CHECKSUM_TYPE AS CHECKSUM_TYPE,"
"CHECKSUM_VALUE AS CHECKSUM_VALUE,"
"STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
"CREATION_TIME AS CREATION_TIME,"
"RECOVERY_PATH AS RECOVERY_PATH,"
"RECOVERY_OWNER AS RECOVERY_OWNER,"
"RECOVERY_GROUP AS RECOVERY_GROUP,"
"RECOVERY_BLOB AS RECOVERY_BLOB "
"FROM ARCHIVE_FILE WHERE "
"ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID;";
std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql));
stmt->bind(":ARCHIVE_FILE_ID", id);
if(SQLITE_ROW != stmt->step()) {
exception::Exception ex;
ex.getMessage() << __FUNCTION__ << " failed"
": Could not find archive file with ID " << id;
throw ex;
} else {
const ColumnNameToIdx nameToIdx = stmt->getColumnNameToIdx();
cta::common::dataStructures::ArchiveFile file;
file.archiveFileID = id;
file.eosFileID = stmt->columnText(nameToIdx["DISK_FILE_ID"]);
file.fileSize = stmt->columnUint64(nameToIdx["FILE_SIZE"]);
file.checksumType = stmt->columnText(nameToIdx["CHECKSUM_TYPE"]);
file.checksumValue = stmt->columnText(nameToIdx["CHECKSUM_VALUE"]);
file.storageClass = stmt->columnText(nameToIdx["STORAGE_CLASS_NAME"]);
file.drData.drInstance = stmt->columnText(nameToIdx["DISK_INSTANCE"]);
file.drData.drPath = stmt->columnText(nameToIdx["RECOVERY_PATH"]);
file.drData.drOwner = stmt->columnText(nameToIdx["RECOVERY_OWNER"]);
file.drData.drGroup = stmt->columnText(nameToIdx["RECOVERY_GROUP"]);
file.drData.drBlob = stmt->columnText(nameToIdx["RECOVERY_BLOB"]);
return file;
}
}
//------------------------------------------------------------------------------
......
......@@ -129,6 +129,19 @@ public:
virtual void modifyDedicationUntil(const cta::common::dataStructures::SecurityIdentity &cliIdentity, const std::string &drivename, const uint64_t untilTimestamp);
virtual void modifyDedicationComment(const cta::common::dataStructures::SecurityIdentity &cliIdentity, const std::string &drivename, const std::string &comment);
/**
* Creates the specified archive file without any tape copies and returns its
* unique identifier.
*
* @param archiveFile The archive file to be created. Note that the
* archiveFileID atrribute of the file shall be ignored.
* @return The unique identifier of the newly created archive file. TBD -
* Eric suggests that this method should return the idenitifer of the archive
* file and the destination tape pools, in other words the Catalogue should
* resolve the archive routes of the archive file given the value of its
* storageClass attribute.
*/
virtual uint64_t createArchiveFile(const common::dataStructures::ArchiveFile &archiveFile);
virtual std::list<cta::common::dataStructures::ArchiveFile> getArchiveFiles(const uint64_t id, const std::string &eosid,
const std::string &copynb, const std::string &tapepool, const std::string &vid, const std::string &owner, const std::string &group, const std::string &storageclass, const std::string &path);
virtual cta::common::dataStructures::ArchiveFileSummary getArchiveFileSummary(const uint64_t id, const std::string &eosid,
......@@ -189,6 +202,19 @@ private:
*/
bool hostIsAdmin(const std::string &userName) const;
/**
* Returns the unique identifier of the specified archive file. Note that
* this method is required by SqliteCatalogue because SQLite does not support
* the SQL syntax: "INSERT INTO ... VALUES ... RETURNING ... INTO ...".
*
* @param diskInstance The name of teh disk storage instance within which the
* specified disk file identifier is unique.
* @param diskFileId The disk identifier of the file.
* @return The unique identifier of the specified archive file.
*/
uint64_t getArchiveFileId(const std::string &diskInstance,
const std::string &diskFileId) const;
}; // class SqliteCatalogue
} // namespace catalogue
......
......@@ -842,4 +842,80 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createUser_same_twice) {
exception::Exception);
}
TEST_F(cta_catalogue_SqliteCatalogueTest, createArchiveFile) {
using namespace cta;
catalogue::SqliteCatalogue catalogue;
ASSERT_TRUE(catalogue.getArchiveFiles(0, "", "", "", "", "", "", "", "").empty());
const std::string storageClassName = "storage_class";
const uint64_t nbCopies = 2;
catalogue.createStorageClass(m_cliSI, storageClassName, nbCopies,
"create storage class");
common::dataStructures::ArchiveFile file;
file.archiveFileID = 1234; // Should be ignored
file.eosFileID = "EOS_file_ID";
file.fileSize = 1;
file.checksumType = "checksum_type";
file.checksumValue = "cheskum_value";
file.storageClass = storageClassName;
file.drData.drInstance = "recovery_instance";
file.drData.drPath = "recovery_path";
file.drData.drOwner = "recovery_owner";
file.drData.drGroup = "recovery_group";
file.drData.drBlob = "recovery_blob";
catalogue.createArchiveFile(file);
std::list<common::dataStructures::ArchiveFile> files;
files = catalogue.getArchiveFiles(0, "", "", "", "", "", "", "", "");
ASSERT_EQ(1, files.size());
const common::dataStructures::ArchiveFile frontFile = files.front();
ASSERT_EQ(file.eosFileID, frontFile.eosFileID);
ASSERT_EQ(file.fileSize, frontFile.fileSize);
ASSERT_EQ(file.checksumType, frontFile.checksumType);
ASSERT_EQ(file.checksumValue, frontFile.checksumValue);
ASSERT_EQ(file.storageClass, frontFile.storageClass);
ASSERT_EQ(file.drData.drInstance, frontFile.drData.drInstance);
ASSERT_EQ(file.drData.drPath, frontFile.drData.drPath);
ASSERT_EQ(file.drData.drOwner, frontFile.drData.drOwner);
ASSERT_EQ(file.drData.drGroup, frontFile.drData.drGroup);
ASSERT_EQ(file.drData.drBlob, frontFile.drData.drBlob);
}
TEST_F(cta_catalogue_SqliteCatalogueTest, createArchiveFile_same_twice) {
using namespace cta;
catalogue::SqliteCatalogue catalogue;
ASSERT_TRUE(catalogue.getArchiveFiles(0, "", "", "", "", "", "", "", "").empty());
const std::string storageClassName = "storage_class";
const uint64_t nbCopies = 2;
catalogue.createStorageClass(m_cliSI, storageClassName, nbCopies,
"create storage class");
common::dataStructures::ArchiveFile file;
file.archiveFileID = 1234; // Should be ignored
file.eosFileID = "EOS_file_ID";
file.fileSize = 1;
file.checksumType = "checksum_type";
file.checksumValue = "cheskum_value";
file.storageClass = storageClassName;
file.drData.drInstance = "recovery_instance";
file.drData.drPath = "recovery_path";
file.drData.drOwner = "recovery_owner";
file.drData.drGroup = "recovery_group";
file.drData.drBlob = "recovery_blob";
catalogue.createArchiveFile(file);
ASSERT_THROW(catalogue.createArchiveFile(file), exception::Exception);
}
} // namespace unitTests
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