Commit 66cd1602 authored by Steven Murray's avatar Steven Murray
Browse files

Moved OracleCatalogue::deleteArchiveFile to RdbmsCatalogue because Oracle,...

Moved OracleCatalogue::deleteArchiveFile to RdbmsCatalogue because Oracle, MySQL and PostgreSQL support 'SELECT FOR UPDATE'.  SQLite is the odd one out in that it does not provide support.
parent fb6c69ba
......@@ -158,199 +158,6 @@ OracleCatalogue::OracleCatalogue(
OracleCatalogue::~OracleCatalogue() {
}
//------------------------------------------------------------------------------
// deleteArchiveFile
//------------------------------------------------------------------------------
void OracleCatalogue::deleteArchiveFile(const std::string &diskInstanceName, const uint64_t archiveFileId,
log::LogContext &lc) {
try {
const char *selectSql =
"SELECT "
"ARCHIVE_FILE.ARCHIVE_FILE_ID AS ARCHIVE_FILE_ID,"
"ARCHIVE_FILE.DISK_INSTANCE_NAME AS DISK_INSTANCE_NAME,"
"ARCHIVE_FILE.DISK_FILE_ID AS DISK_FILE_ID,"
"ARCHIVE_FILE.DISK_FILE_PATH AS DISK_FILE_PATH,"
"ARCHIVE_FILE.DISK_FILE_USER AS DISK_FILE_USER,"
"ARCHIVE_FILE.DISK_FILE_GROUP AS DISK_FILE_GROUP,"
"ARCHIVE_FILE.DISK_FILE_RECOVERY_BLOB AS DISK_FILE_RECOVERY_BLOB,"
"ARCHIVE_FILE.SIZE_IN_BYTES AS SIZE_IN_BYTES,"
"ARCHIVE_FILE.CHECKSUM_TYPE AS CHECKSUM_TYPE,"
"ARCHIVE_FILE.CHECKSUM_VALUE AS CHECKSUM_VALUE,"
"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,"
"TAPE_FILE.FSEQ AS FSEQ,"
"TAPE_FILE.BLOCK_ID AS BLOCK_ID,"
"TAPE_FILE.COMPRESSED_SIZE_IN_BYTES AS COMPRESSED_SIZE_IN_BYTES,"
"TAPE_FILE.COPY_NB AS COPY_NB,"
"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 "
"ARCHIVE_FILE.ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID "
"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();
selectStmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId);
t.reset();
rdbms::Rset selectRset = selectStmt.executeQuery();
const auto selectFromArchiveFileTime = t.secs();
std::unique_ptr<common::dataStructures::ArchiveFile> archiveFile;
while(selectRset.next()) {
if(nullptr == archiveFile.get()) {
archiveFile = cta::make_unique<common::dataStructures::ArchiveFile>();
archiveFile->archiveFileID = selectRset.columnUint64("ARCHIVE_FILE_ID");
archiveFile->diskInstance = selectRset.columnString("DISK_INSTANCE_NAME");
archiveFile->diskFileId = selectRset.columnString("DISK_FILE_ID");
archiveFile->diskFileInfo.path = selectRset.columnString("DISK_FILE_PATH");
archiveFile->diskFileInfo.owner = selectRset.columnString("DISK_FILE_USER");
archiveFile->diskFileInfo.group = selectRset.columnString("DISK_FILE_GROUP");
archiveFile->diskFileInfo.recoveryBlob = selectRset.columnString("DISK_FILE_RECOVERY_BLOB");
archiveFile->fileSize = selectRset.columnUint64("SIZE_IN_BYTES");
archiveFile->checksumType = selectRset.columnString("CHECKSUM_TYPE");
archiveFile->checksumValue = selectRset.columnString("CHECKSUM_VALUE");
archiveFile->storageClass = selectRset.columnString("STORAGE_CLASS_NAME");
archiveFile->creationTime = selectRset.columnUint64("ARCHIVE_FILE_CREATION_TIME");
archiveFile->reconciliationTime = selectRset.columnUint64("RECONCILIATION_TIME");
}
// If there is a tape file
if(!selectRset.columnIsNull("VID")) {
// Add the tape file to the archive file's in-memory structure
common::dataStructures::TapeFile tapeFile;
tapeFile.vid = selectRset.columnString("VID");
tapeFile.fSeq = selectRset.columnUint64("FSEQ");
tapeFile.blockId = selectRset.columnUint64("BLOCK_ID");
tapeFile.compressedSize = selectRset.columnUint64("COMPRESSED_SIZE_IN_BYTES");
tapeFile.copyNb = selectRset.columnUint64("COPY_NB");
tapeFile.creationTime = selectRset.columnUint64("TAPE_FILE_CREATION_TIME");
tapeFile.checksumType = archiveFile->checksumType; // Duplicated for convenience
tapeFile.checksumValue = archiveFile->checksumValue; // Duplicated for convenience
archiveFile->tapeFiles[selectRset.columnUint64("COPY_NB")] = tapeFile;
}
}
if(nullptr == archiveFile.get()) {
log::ScopedParamContainer spc(lc);
spc.add("fileId", archiveFileId);
lc.log(log::WARNING, "Ignoring request to delete archive file because it does not exist in the catalogue");
return;
}
if(diskInstanceName != archiveFile->diskInstance) {
log::ScopedParamContainer spc(lc);
spc.add("fileId", std::to_string(archiveFile->archiveFileID))
.add("diskInstance", archiveFile->diskInstance)
.add("requestDiskInstance", diskInstanceName)
.add("diskFileId", archiveFile->diskFileId)
.add("diskFileInfo.path", archiveFile->diskFileInfo.path)
.add("diskFileInfo.owner", archiveFile->diskFileInfo.owner)
.add("diskFileInfo.group", archiveFile->diskFileInfo.group)
.add("fileSize", std::to_string(archiveFile->fileSize))
.add("checksumType", archiveFile->checksumType)
.add("checksumValue", archiveFile->checksumValue)
.add("creationTime", std::to_string(archiveFile->creationTime))
.add("reconciliationTime", std::to_string(archiveFile->reconciliationTime))
.add("storageClass", archiveFile->storageClass)
.add("getConnTime", getConnTime)
.add("createStmtTime", createStmtTime)
.add("selectFromArchiveFileTime", selectFromArchiveFileTime);
for(auto it=archiveFile->tapeFiles.begin(); it!=archiveFile->tapeFiles.end(); it++) {
std::stringstream tapeCopyLogStream;
tapeCopyLogStream << "copy number: " << it->first
<< " vid: " << it->second.vid
<< " fSeq: " << it->second.fSeq
<< " blockId: " << it->second.blockId
<< " creationTime: " << it->second.creationTime
<< " compressedSize: " << it->second.compressedSize
<< " checksumType: " << it->second.checksumType //this shouldn't be here: repeated field
<< " checksumValue: " << it->second.checksumValue //this shouldn't be here: repeated field
<< " copyNb: " << it->second.copyNb; //this shouldn't be here: repeated field
spc.add("TAPE FILE", tapeCopyLogStream.str());
}
lc.log(log::WARNING, "Failed to delete archive file because the disk instance of the request does not match that "
"of the archived file");
exception::UserError ue;
ue.getMessage() << "Failed to delete archive file with ID " << archiveFileId << " because the disk instance of "
"the request does not match that of the archived file: archiveFileId=" << archiveFileId << " path=" <<
archiveFile->diskFileInfo.path << " requestDiskInstance=" << diskInstanceName << " archiveFileDiskInstance=" <<
archiveFile->diskInstance;
throw ue;
}
t.reset();
{
const char *const sql = "DELETE FROM TAPE_FILE WHERE ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID";
auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId);
stmt.executeNonQuery();
}
const auto deleteFromTapeFileTime = t.secs(utils::Timer::resetCounter);
{
const char *const sql = "DELETE FROM ARCHIVE_FILE WHERE ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID";
auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId);
stmt.executeNonQuery();
}
const auto deleteFromArchiveFileTime = t.secs(utils::Timer::resetCounter);
conn.commit();
const auto commitTime = t.secs();
log::ScopedParamContainer spc(lc);
spc.add("fileId", std::to_string(archiveFile->archiveFileID))
.add("diskInstance", archiveFile->diskInstance)
.add("diskFileId", archiveFile->diskFileId)
.add("diskFileInfo.path", archiveFile->diskFileInfo.path)
.add("diskFileInfo.owner", archiveFile->diskFileInfo.owner)
.add("diskFileInfo.group", archiveFile->diskFileInfo.group)
.add("fileSize", std::to_string(archiveFile->fileSize))
.add("checksumType", archiveFile->checksumType)
.add("checksumValue", archiveFile->checksumValue)
.add("creationTime", std::to_string(archiveFile->creationTime))
.add("reconciliationTime", std::to_string(archiveFile->reconciliationTime))
.add("storageClass", archiveFile->storageClass)
.add("getConnTime", getConnTime)
.add("createStmtTime", createStmtTime)
.add("selectFromArchiveFileTime", selectFromArchiveFileTime)
.add("deleteFromTapeFileTime", deleteFromTapeFileTime)
.add("deleteFromArchiveFileTime", deleteFromArchiveFileTime)
.add("commitTime", commitTime);
for(auto it=archiveFile->tapeFiles.begin(); it!=archiveFile->tapeFiles.end(); it++) {
std::stringstream tapeCopyLogStream;
tapeCopyLogStream << "copy number: " << it->first
<< " vid: " << it->second.vid
<< " fSeq: " << it->second.fSeq
<< " blockId: " << it->second.blockId
<< " creationTime: " << it->second.creationTime
<< " compressedSize: " << it->second.compressedSize
<< " checksumType: " << it->second.checksumType //this shouldn't be here: repeated field
<< " checksumValue: " << it->second.checksumValue //this shouldn't be here: repeated field
<< " copyNb: " << it->second.copyNb; //this shouldn't be here: repeated field
spc.add("TAPE FILE", tapeCopyLogStream.str());
}
lc.log(log::INFO, "Archive file deleted from CTA catalogue");
} catch(exception::UserError &) {
throw;
} catch(exception::Exception &ex) {
ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
throw;
}
}
//------------------------------------------------------------------------------
// getNextArchiveFileId
//------------------------------------------------------------------------------
......
......@@ -61,27 +61,6 @@ public:
*/
~OracleCatalogue() override;
/**
* 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.
*
* @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 deleteArchiveFile(const std::string &diskInstanceName, const uint64_t archiveFileId, log::LogContext &lc)
override;
/**
* Returns a unique archive ID that can be used by a new archive file within
* the catalogue.
......
......@@ -4490,6 +4490,199 @@ RequesterAndGroupMountPolicies RdbmsCatalogue::getMountPolicies(
}
}
//------------------------------------------------------------------------------
// deleteArchiveFile
//------------------------------------------------------------------------------
void RdbmsCatalogue::deleteArchiveFile(const std::string &diskInstanceName, const uint64_t archiveFileId,
log::LogContext &lc) {
try {
const char *selectSql =
"SELECT "
"ARCHIVE_FILE.ARCHIVE_FILE_ID AS ARCHIVE_FILE_ID,"
"ARCHIVE_FILE.DISK_INSTANCE_NAME AS DISK_INSTANCE_NAME,"
"ARCHIVE_FILE.DISK_FILE_ID AS DISK_FILE_ID,"
"ARCHIVE_FILE.DISK_FILE_PATH AS DISK_FILE_PATH,"
"ARCHIVE_FILE.DISK_FILE_USER AS DISK_FILE_USER,"
"ARCHIVE_FILE.DISK_FILE_GROUP AS DISK_FILE_GROUP,"
"ARCHIVE_FILE.DISK_FILE_RECOVERY_BLOB AS DISK_FILE_RECOVERY_BLOB,"
"ARCHIVE_FILE.SIZE_IN_BYTES AS SIZE_IN_BYTES,"
"ARCHIVE_FILE.CHECKSUM_TYPE AS CHECKSUM_TYPE,"
"ARCHIVE_FILE.CHECKSUM_VALUE AS CHECKSUM_VALUE,"
"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,"
"TAPE_FILE.FSEQ AS FSEQ,"
"TAPE_FILE.BLOCK_ID AS BLOCK_ID,"
"TAPE_FILE.COMPRESSED_SIZE_IN_BYTES AS COMPRESSED_SIZE_IN_BYTES,"
"TAPE_FILE.COPY_NB AS COPY_NB,"
"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 "
"ARCHIVE_FILE.ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID "
"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();
selectStmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId);
t.reset();
rdbms::Rset selectRset = selectStmt.executeQuery();
const auto selectFromArchiveFileTime = t.secs();
std::unique_ptr<common::dataStructures::ArchiveFile> archiveFile;
while(selectRset.next()) {
if(nullptr == archiveFile.get()) {
archiveFile = cta::make_unique<common::dataStructures::ArchiveFile>();
archiveFile->archiveFileID = selectRset.columnUint64("ARCHIVE_FILE_ID");
archiveFile->diskInstance = selectRset.columnString("DISK_INSTANCE_NAME");
archiveFile->diskFileId = selectRset.columnString("DISK_FILE_ID");
archiveFile->diskFileInfo.path = selectRset.columnString("DISK_FILE_PATH");
archiveFile->diskFileInfo.owner = selectRset.columnString("DISK_FILE_USER");
archiveFile->diskFileInfo.group = selectRset.columnString("DISK_FILE_GROUP");
archiveFile->diskFileInfo.recoveryBlob = selectRset.columnString("DISK_FILE_RECOVERY_BLOB");
archiveFile->fileSize = selectRset.columnUint64("SIZE_IN_BYTES");
archiveFile->checksumType = selectRset.columnString("CHECKSUM_TYPE");
archiveFile->checksumValue = selectRset.columnString("CHECKSUM_VALUE");
archiveFile->storageClass = selectRset.columnString("STORAGE_CLASS_NAME");
archiveFile->creationTime = selectRset.columnUint64("ARCHIVE_FILE_CREATION_TIME");
archiveFile->reconciliationTime = selectRset.columnUint64("RECONCILIATION_TIME");
}
// If there is a tape file
if(!selectRset.columnIsNull("VID")) {
// Add the tape file to the archive file's in-memory structure
common::dataStructures::TapeFile tapeFile;
tapeFile.vid = selectRset.columnString("VID");
tapeFile.fSeq = selectRset.columnUint64("FSEQ");
tapeFile.blockId = selectRset.columnUint64("BLOCK_ID");
tapeFile.compressedSize = selectRset.columnUint64("COMPRESSED_SIZE_IN_BYTES");
tapeFile.copyNb = selectRset.columnUint64("COPY_NB");
tapeFile.creationTime = selectRset.columnUint64("TAPE_FILE_CREATION_TIME");
tapeFile.checksumType = archiveFile->checksumType; // Duplicated for convenience
tapeFile.checksumValue = archiveFile->checksumValue; // Duplicated for convenience
archiveFile->tapeFiles[selectRset.columnUint64("COPY_NB")] = tapeFile;
}
}
if(nullptr == archiveFile.get()) {
log::ScopedParamContainer spc(lc);
spc.add("fileId", archiveFileId);
lc.log(log::WARNING, "Ignoring request to delete archive file because it does not exist in the catalogue");
return;
}
if(diskInstanceName != archiveFile->diskInstance) {
log::ScopedParamContainer spc(lc);
spc.add("fileId", std::to_string(archiveFile->archiveFileID))
.add("diskInstance", archiveFile->diskInstance)
.add("requestDiskInstance", diskInstanceName)
.add("diskFileId", archiveFile->diskFileId)
.add("diskFileInfo.path", archiveFile->diskFileInfo.path)
.add("diskFileInfo.owner", archiveFile->diskFileInfo.owner)
.add("diskFileInfo.group", archiveFile->diskFileInfo.group)
.add("fileSize", std::to_string(archiveFile->fileSize))
.add("checksumType", archiveFile->checksumType)
.add("checksumValue", archiveFile->checksumValue)
.add("creationTime", std::to_string(archiveFile->creationTime))
.add("reconciliationTime", std::to_string(archiveFile->reconciliationTime))
.add("storageClass", archiveFile->storageClass)
.add("getConnTime", getConnTime)
.add("createStmtTime", createStmtTime)
.add("selectFromArchiveFileTime", selectFromArchiveFileTime);
for(auto it=archiveFile->tapeFiles.begin(); it!=archiveFile->tapeFiles.end(); it++) {
std::stringstream tapeCopyLogStream;
tapeCopyLogStream << "copy number: " << it->first
<< " vid: " << it->second.vid
<< " fSeq: " << it->second.fSeq
<< " blockId: " << it->second.blockId
<< " creationTime: " << it->second.creationTime
<< " compressedSize: " << it->second.compressedSize
<< " checksumType: " << it->second.checksumType //this shouldn't be here: repeated field
<< " checksumValue: " << it->second.checksumValue //this shouldn't be here: repeated field
<< " copyNb: " << it->second.copyNb; //this shouldn't be here: repeated field
spc.add("TAPE FILE", tapeCopyLogStream.str());
}
lc.log(log::WARNING, "Failed to delete archive file because the disk instance of the request does not match that "
"of the archived file");
exception::UserError ue;
ue.getMessage() << "Failed to delete archive file with ID " << archiveFileId << " because the disk instance of "
"the request does not match that of the archived file: archiveFileId=" << archiveFileId << " path=" <<
archiveFile->diskFileInfo.path << " requestDiskInstance=" << diskInstanceName << " archiveFileDiskInstance=" <<
archiveFile->diskInstance;
throw ue;
}
t.reset();
{
const char *const sql = "DELETE FROM TAPE_FILE WHERE ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID";
auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId);
stmt.executeNonQuery();
}
const auto deleteFromTapeFileTime = t.secs(utils::Timer::resetCounter);
{
const char *const sql = "DELETE FROM ARCHIVE_FILE WHERE ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID";
auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId);
stmt.executeNonQuery();
}
const auto deleteFromArchiveFileTime = t.secs(utils::Timer::resetCounter);
conn.commit();
const auto commitTime = t.secs();
log::ScopedParamContainer spc(lc);
spc.add("fileId", std::to_string(archiveFile->archiveFileID))
.add("diskInstance", archiveFile->diskInstance)
.add("diskFileId", archiveFile->diskFileId)
.add("diskFileInfo.path", archiveFile->diskFileInfo.path)
.add("diskFileInfo.owner", archiveFile->diskFileInfo.owner)
.add("diskFileInfo.group", archiveFile->diskFileInfo.group)
.add("fileSize", std::to_string(archiveFile->fileSize))
.add("checksumType", archiveFile->checksumType)
.add("checksumValue", archiveFile->checksumValue)
.add("creationTime", std::to_string(archiveFile->creationTime))
.add("reconciliationTime", std::to_string(archiveFile->reconciliationTime))
.add("storageClass", archiveFile->storageClass)
.add("getConnTime", getConnTime)
.add("createStmtTime", createStmtTime)
.add("selectFromArchiveFileTime", selectFromArchiveFileTime)
.add("deleteFromTapeFileTime", deleteFromTapeFileTime)
.add("deleteFromArchiveFileTime", deleteFromArchiveFileTime)
.add("commitTime", commitTime);
for(auto it=archiveFile->tapeFiles.begin(); it!=archiveFile->tapeFiles.end(); it++) {
std::stringstream tapeCopyLogStream;
tapeCopyLogStream << "copy number: " << it->first
<< " vid: " << it->second.vid
<< " fSeq: " << it->second.fSeq
<< " blockId: " << it->second.blockId
<< " creationTime: " << it->second.creationTime
<< " compressedSize: " << it->second.compressedSize
<< " checksumType: " << it->second.checksumType //this shouldn't be here: repeated field
<< " checksumValue: " << it->second.checksumValue //this shouldn't be here: repeated field
<< " copyNb: " << it->second.copyNb; //this shouldn't be here: repeated field
spc.add("TAPE FILE", tapeCopyLogStream.str());
}
lc.log(log::INFO, "Archive file deleted from CTA catalogue");
} catch(exception::UserError &) {
throw;
} catch(exception::Exception &ex) {
ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
throw;
}
}
//------------------------------------------------------------------------------
// isAdmin
//------------------------------------------------------------------------------
......
......@@ -512,6 +512,27 @@ public:
*/
common::dataStructures::ArchiveFile getArchiveFileById(const uint64_t id) override;
/**
* 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.
*
* @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 deleteArchiveFile(const std::string &instanceName, const uint64_t archiveFileId,
log::LogContext &lc) override;
/**
* Returns true if the specified user has administrator privileges.
*
......
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