From a62744b0dee3a2c4158cae8d1ce7c537c3f66c46 Mon Sep 17 00:00:00 2001 From: Michael Davis <michael.davis@cern.ch> Date: Fri, 21 Aug 2020 13:41:49 +0000 Subject: [PATCH] [cta-admin] Adds "failedrequest rm --objectid" Also deletes all unused options which were defined for commands that no longer exist --- ReleaseNotes.md | 3 +- cmdline/CtaAdminCmdParse.hpp | 37 +------ scheduler/OStoreDB/OStoreDB.cpp | 114 ++++++++++++++++++++++ scheduler/OStoreDB/OStoreDB.hpp | 2 + scheduler/OStoreDB/OStoreDBFactory.hpp | 4 + scheduler/Scheduler.cpp | 6 +- scheduler/Scheduler.hpp | 5 + scheduler/SchedulerDatabase.hpp | 7 ++ xroot_plugins/XrdSsiCtaRequestMessage.cpp | 16 +++ xroot_plugins/XrdSsiCtaRequestMessage.hpp | 1 + xrootd-ssi-protobuf-interface | 2 +- 11 files changed, 162 insertions(+), 35 deletions(-) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 1a4753e69c..cfbf0c082b 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -7,6 +7,7 @@ This release is a bug fix release. ### Features - cta/CTA#863 Prevent SQLite database files from being used as the CTA catalogue database backend +- cta/CTA#870 Adds "cta-admin failedrequest rm" command ### Modifications @@ -16,7 +17,7 @@ This release is a bug fix release. - cta/CTA#862 Unable to delete tabtest tape pool because it is in an archive route - cta/CTA#860 Correct contents of cta-lib-catalogue RPM and correct dependencies on it -- Reinstates "cta-admin failedrequest --summary" option +- Reinstates missing "cta-admin failedrequest ls --summary" option - cta/CTA#865 Empty the RetrieveQueue in the case of cancellation of a retrieve request when the drive is down diff --git a/cmdline/CtaAdminCmdParse.hpp b/cmdline/CtaAdminCmdParse.hpp index 367b3054e8..36381d9af5 100644 --- a/cmdline/CtaAdminCmdParse.hpp +++ b/cmdline/CtaAdminCmdParse.hpp @@ -233,7 +233,6 @@ const subcmdLookup_t subcmdLookup = { { "reclaim", AdminCmd::SUBCMD_RECLAIM }, { "retry", AdminCmd::SUBCMD_RETRY }, { "rm", AdminCmd::SUBCMD_RM }, - { "show", AdminCmd::SUBCMD_SHOW }, { "up", AdminCmd::SUBCMD_UP }, { "down", AdminCmd::SUBCMD_DOWN }, }; @@ -253,7 +252,6 @@ const std::map<std::string, OptionBoolean::Key> boolOptions = { { "--readonly", OptionBoolean::READ_ONLY }, // hasOption options - { "--checkchecksum", OptionBoolean::CHECK_CHECKSUM }, { "--disabledtape", OptionBoolean::DISABLED }, { "--justarchive", OptionBoolean::JUSTARCHIVE }, { "--justmove", OptionBoolean::JUSTMOVE }, @@ -275,27 +273,19 @@ const std::map<std::string, OptionUInt64::Key> uint64Options = { { "--archivepriority", OptionUInt64::ARCHIVE_PRIORITY }, { "--capacity", OptionUInt64::CAPACITY }, { "--copynb", OptionUInt64::COPY_NUMBER }, - { "--firstfseq", OptionUInt64::FIRST_FSEQ }, - { "--gid", OptionUInt64::GID }, - { "--id", OptionUInt64::ARCHIVE_FILE_ID }, - { "--lastfseq", OptionUInt64::LAST_FSEQ }, { "--maxdrivesallowed", OptionUInt64::MAX_DRIVES_ALLOWED }, { "--maxlpos", OptionUInt64::MAX_LPOS }, { "--minarchiverequestage", OptionUInt64::MIN_ARCHIVE_REQUEST_AGE }, { "--minlpos", OptionUInt64::MIN_LPOS }, { "--minretrieverequestage", OptionUInt64::MIN_RETRIEVE_REQUEST_AGE }, - { "--nbfiles", OptionUInt64::NUMBER_OF_FILES }, { "--nbwraps", OptionUInt64::NUMBER_OF_WRAPS }, - { "--partial", OptionUInt64::PARTIAL }, { "--partialtapesnumber", OptionUInt64::PARTIAL_TAPES_NUMBER }, { "--primarydensitycode", OptionUInt64::PRIMARY_DENSITY_CODE }, { "--retrievepriority", OptionUInt64::RETRIEVE_PRIORITY }, { "--secondarydensitycode", OptionUInt64::SECONDARY_DENSITY_CODE }, - { "--size", OptionUInt64::FILE_SIZE }, { "--refreshinterval", OptionUInt64::REFRESH_INTERVAL }, { "--targetedfreespace", OptionUInt64::TARGETED_FREE_SPACE }, { "--sleeptime", OptionUInt64::SLEEP_TIME }, - { "--uid", OptionUInt64::OWNER_UID } }; @@ -307,19 +297,14 @@ const std::map<std::string, OptionString::Key> strOptions = { { "--bufferurl", OptionString::BUFFERURL }, { "--cartridge", OptionString::CARTRIDGE }, { "--comment", OptionString::COMMENT }, - { "--diskid", OptionString::DISKID }, { "--drive", OptionString::DRIVE }, { "--encryptionkeyname", OptionString::ENCRYPTION_KEY_NAME }, { "--fxid", OptionString::FXID }, - { "--file", OptionString::FILENAME }, - { "--hostname", OptionString::HOSTNAME }, - { "--input", OptionString::INPUT }, { "--instance", OptionString::INSTANCE }, { "--logicallibrary", OptionString::LOGICAL_LIBRARY }, { "--mediatype", OptionString::MEDIA_TYPE }, { "--mountpolicy", OptionString::MOUNT_POLICY }, - { "--output", OptionString::OUTPUT }, - { "--path", OptionString::PATH }, + { "--objectid", OptionString::OBJECTID }, { "--storageclass", OptionString::STORAGE_CLASS }, { "--supply", OptionString::SUPPLY }, { "--tapepool", OptionString::TAPE_POOL }, @@ -357,7 +342,7 @@ const std::map<AdminCmd::Cmd, CmdHelp> cmdHelp = { " --force option is not set, the drives will complete any running mount and\n" " drives must be in the down state before deleting.\n\n" }}, - { AdminCmd::CMD_FAILEDREQUEST, { "failedrequest", "fr", { "ls" } }}, + { AdminCmd::CMD_FAILEDREQUEST, { "failedrequest", "fr", { "ls", "rm" } }}, { AdminCmd::CMD_GROUPMOUNTRULE, { "groupmountrule", "gmr", { "add", "ch", "rm", "ls" } }}, { AdminCmd::CMD_LOGICALLIBRARY, { "logicallibrary", "ll", { "add", "ch", "rm", "ls" } }}, { AdminCmd::CMD_MEDIATYPE, { "mediatype", "mt", { "add", "ch", "rm", "ls" } }}, @@ -417,16 +402,13 @@ const std::map<AdminCmd::Cmd, CmdHelp> cmdHelp = { * Enumerate options */ const Option opt_all { Option::OPT_FLAG, "--all", "-a", "" }; -const Option opt_archivefileid { Option::OPT_UINT, "--id", "-I", " <archive_file_id>" }; const Option opt_archivepriority { Option::OPT_UINT, "--archivepriority", "--ap", " <priority_value>" }; const Option opt_bufferurl { Option::OPT_STR, "--bufferurl", "-b", " <buffer URL>" }; const Option opt_capacity { Option::OPT_UINT, "--capacity", "-c", " <capacity_in_bytes>" }; const Option opt_cartridge { Option::OPT_STR, "--cartridge", "-t", " <cartridge>" }; -const Option opt_checkchecksum { Option::OPT_FLAG, "--checkchecksum", "-c", "" }; const Option opt_comment { Option::OPT_STR, "--comment", "-m", " <\"comment\">" }; const Option opt_copynb { Option::OPT_UINT, "--copynb", "-c", " <copy_number>" }; const Option opt_disabled { Option::OPT_BOOL, "--disabled", "-d", " <\"true\" or \"false\">" }; -const Option opt_diskid { Option::OPT_STR, "--diskid", "-d", " <disk_id>" }; const Option opt_drivename { Option::OPT_STR, "--drive", "-d", " <drive_name>" }; const Option opt_drivename_cmd { Option::OPT_CMD, "--drive", "", "<drive_name>" }; const Option opt_encrypted { Option::OPT_BOOL, "--encrypted", "-e", " <\"true\" or \"false\">" }; @@ -434,18 +416,13 @@ const Option opt_encryptionkeyname { Option::OPT_STR, "--encryptionkeyname", const Option opt_fid { Option::OPT_STR, "--fxid", "-f", " <eos_fxid>" }; const Option opt_fidfile { Option::OPT_STR_LIST, "--fxidfile", "-F", " <filename>" }; const Option opt_filename { Option::OPT_STR, "--file", "-f", " <filename>" }; -const Option opt_firstfseq { Option::OPT_UINT, "--firstfseq", "-f", " <first_fseq>" }; const Option opt_force { Option::OPT_BOOL, "--force", "-f", " <\"true\" or \"false\">" }; const Option opt_force_flag { Option::OPT_FLAG, "--force", "-f", "" }; -const Option opt_gid { Option::OPT_UINT, "--gid", "-g", " <group_id>" }; -const Option opt_hostname_alias { Option::OPT_STR, "--name", "-n", " <host_name>", "--hostname" }; -const Option opt_input { Option::OPT_STR, "--input", "-i", " <\"zero\" or \"urandom\">" }; const Option opt_instance { Option::OPT_STR, "--instance", "-i", " <disk_instance>" }; const Option opt_justarchive { Option::OPT_FLAG, "--justarchive", "-a", "" }; const Option opt_justmove { Option::OPT_FLAG, "--justmove", "-m", "" }; const Option opt_justaddcopies { Option::OPT_FLAG, "--justaddcopies", "-a", "" }; const Option opt_justretrieve { Option::OPT_FLAG, "--justretrieve", "-r", "" }; -const Option opt_lastfseq { Option::OPT_UINT, "--lastfseq", "-l", " <last_fseq>" }; const Option opt_log { Option::OPT_FLAG, "--log", "-l", "" }; const Option opt_logicallibrary { Option::OPT_STR, "--logicallibrary", "-l", " <logical_library_name>" }; const Option opt_logicallibrary_alias { Option::OPT_STR, "--name", "-n", " <logical_library_name>", "--logicallibrary" }; @@ -459,18 +436,12 @@ const Option opt_minlpos { Option::OPT_UINT, "--minlpos", const Option opt_minretrieverequestage{ Option::OPT_UINT, "--minretrieverequestage", "--ra", " <min_request_age>" }; const Option opt_mountpolicy { Option::OPT_STR, "--mountpolicy", "-u", " <mount_policy_name>" }; const Option opt_mountpolicy_alias { Option::OPT_STR, "--name", "-n", " <mount_policy_name>", "--mountpolicy" }; -const Option opt_number_of_files { Option::OPT_UINT, "--nbfiles", "-n", " <number_of_files_per_tape>" }; -const Option opt_number_of_files_alias{ Option::OPT_UINT, "--number", "-n", " <number_of_files>", "--nbfiles" }; const Option opt_number_of_wraps { Option::OPT_UINT, "--nbwraps", "-w", " <number_of_wraps>" }; -const Option opt_output { Option::OPT_STR, "--output", "-o", " <\"null\" or output_dir>" }; -const Option opt_owner_uid { Option::OPT_UINT, "--uid", "-u", " <owner_uid>" }; const Option opt_partialfiles { Option::OPT_UINT, "--partial", "-p", " <number_of_files_per_tape>" }; const Option opt_partialtapes { Option::OPT_UINT, "--partialtapesnumber", "-p", " <number_of_partial_tapes>" }; -const Option opt_path { Option::OPT_STR, "--path", "-p", " <full_path>" }; -const Option opt_primarydensitycode { Option::OPT_UINT, "--primarydensitycode", "-p", " <primary_density_code>" }; +const Option opt_primarydensitycode { Option::OPT_UINT, "--primarydensitycode", "-p", " <primary_density_code>" }; const Option opt_retrievepriority { Option::OPT_UINT, "--retrievepriority", "--rp", " <priority_value>" }; const Option opt_secondarydensitycode { Option::OPT_UINT, "--secondarydensitycode", "-s", " <secondary_density_code>" }; -const Option opt_size { Option::OPT_UINT, "--size", "-s", " <file_size>" }; const Option opt_storageclass { Option::OPT_STR, "--storageclass", "-s", " <storage_class_name>" }; const Option opt_storageclass_alias { Option::OPT_STR, "--name", "-n", " <storage_class_name>", "--storageclass" }; const Option opt_summary { Option::OPT_FLAG, "--summary", "-S", "" }; @@ -495,6 +466,7 @@ const Option opt_sleep_time { Option::OPT_UINT, "--sleeptime", const Option opt_reason { Option::OPT_STR, "--reason", "-r", " <reason_status_change>" }; const Option opt_show_superseded { Option::OPT_FLAG, "--showsuperseded", "-s", "" }; const Option opt_no_recall { Option::OPT_FLAG, "--no-recall", "-nr", "" }; +const Option opt_object_id { Option::OPT_STR, "--objectid", "-o", " <objectId>" }; /*! * Map valid options to commands @@ -521,6 +493,7 @@ const std::map<cmd_key_t, cmd_val_t> cmdOptions = { {{ AdminCmd::CMD_FAILEDREQUEST, AdminCmd::SUBCMD_LS }, { opt_justarchive.optional(), opt_justretrieve.optional(), opt_tapepool.optional(), opt_vid.optional(), opt_log.optional(), opt_summary.optional() }}, + {{ AdminCmd::CMD_FAILEDREQUEST, AdminCmd::SUBCMD_RM }, { opt_object_id }}, /*----------------------------------------------------------------------------------------------------*/ {{ AdminCmd::CMD_GROUPMOUNTRULE, AdminCmd::SUBCMD_ADD }, { opt_instance, opt_username_alias, opt_mountpolicy, opt_comment }}, diff --git a/scheduler/OStoreDB/OStoreDB.cpp b/scheduler/OStoreDB/OStoreDB.cpp index d8dcde3c26..f1ea81ca98 100644 --- a/scheduler/OStoreDB/OStoreDB.cpp +++ b/scheduler/OStoreDB/OStoreDB.cpp @@ -1537,6 +1537,120 @@ void OStoreDB::cancelArchive(const common::dataStructures::DeleteArchiveRequest ar.remove(); } +//------------------------------------------------------------------------------ +// OStoreDB::deleteFailed() +//------------------------------------------------------------------------------ +void OStoreDB::deleteFailed(const std::string &objectId, log::LogContext &lc) +{ + // Fetch the object + objectstore::GenericObject fr(objectId, m_objectStore); + objectstore::ScopedExclusiveLock sel; + try { + sel.lock(fr); + fr.fetch(); + } catch (objectstore::Backend::NoSuchObject &) { + throw exception::Exception("Object " + objectId + " not found."); + } + + // Validate that the object is an Archive or Retrieve request + if(fr.type() != objectstore::serializers::ArchiveRequest_t && + fr.type() != objectstore::serializers::RetrieveRequest_t) { + throw exception::Exception("Object " + objectId + " is not an archive or retrieve request."); + } + + // Make a list of all owners of the object + std::list<std::string> queueIds; + if(!fr.getOwner().empty()) queueIds.push_back(fr.getOwner()); + if(!fr.getBackupOwner().empty()) queueIds.push_back(fr.getBackupOwner()); + if(fr.type() == objectstore::serializers::ArchiveRequest_t) { + // Archive requests can be in two queues, so ownership is per job not per request + objectstore::ArchiveRequest ar(fr); + // We already hold a lock on the generic object + ar.fetchNoLock(); + for(auto &job : ar.dumpJobs()) { + if(!job.owner.empty()) queueIds.push_back(job.owner); + } + } + if(queueIds.empty()) { + throw exception::Exception("Object " + objectId + " is not owned by any queue."); + } + + // Make a set of failed archive or retrieve queues + std::set<std::string> failedQueueIds; + { + RootEntry re(m_objectStore); + ScopedExclusiveLock rel(re); + re.fetch(); + + switch(fr.type()) { + case objectstore::serializers::ArchiveRequest_t: { + auto archiveQueueList = re.dumpArchiveQueues(JobQueueType::FailedJobs); + for(auto &r : archiveQueueList) { + failedQueueIds.insert(r.address); + } + break; + } + case objectstore::serializers::RetrieveRequest_t: { + auto retrieveQueueList = re.dumpRetrieveQueues(JobQueueType::FailedJobs); + for(auto &r : retrieveQueueList) { + failedQueueIds.insert(r.address); + } + break; + } + default: ; + } + } + + // Validate that all owners of the object are failed queues and therefore it is safe to delete the job + for(auto &qid : queueIds) { + if(failedQueueIds.find(qid) == failedQueueIds.end()) { + throw exception::Exception("Will not delete object " + objectId + "\nwhich is owned by " + qid); + } + } + + // Checks passed, delete the request + log::ScopedParamContainer params(lc); + params.add("objectId", objectId); + int owner_no = 0; + for(auto &qid : queueIds) { + params.add("owner" + std::to_string(owner_no++), qid); + } + + // Delete the references + lc.log(log::INFO, "OStoreDB::deleteFailed(): deleting references"); + bool isQueueEmpty = false; + switch(fr.type()) { + case objectstore::serializers::ArchiveRequest_t: { + for(auto &arq_id : queueIds) { + ArchiveQueue arq(arq_id, m_objectStore); + ScopedExclusiveLock arq_el(arq); + arq.fetch(); + arq.removeJobsAndCommit(std::list<std::string>(1, objectId)); + if(arq.isEmpty()) isQueueEmpty = true; + } + break; + } + case objectstore::serializers::RetrieveRequest_t: { + for(auto &rrq_id : queueIds) { + RetrieveQueue rrq(rrq_id, m_objectStore); + ScopedExclusiveLock rrq_el(rrq); + rrq.fetch(); + rrq.removeJobsAndCommit(std::list<std::string>(1, objectId)); + if(rrq.isEmpty()) isQueueEmpty = true; + } + break; + } + default: ; + } + + // Delete the request + lc.log(log::INFO, "OStoreDB::deleteFailed(): deleting failed request"); + fr.remove(); + + // Trim empty queues + if(isQueueEmpty) trimEmptyQueues(lc); +} + //------------------------------------------------------------------------------ // OStoreDB::getRetrieveJobs() //------------------------------------------------------------------------------ diff --git a/scheduler/OStoreDB/OStoreDB.hpp b/scheduler/OStoreDB/OStoreDB.hpp index 30a52dd59a..82c4086bda 100644 --- a/scheduler/OStoreDB/OStoreDB.hpp +++ b/scheduler/OStoreDB/OStoreDB.hpp @@ -362,6 +362,8 @@ public: */ virtual void cancelArchive(const common::dataStructures::DeleteArchiveRequest& request, log::LogContext & lc) override; + virtual void deleteFailed(const std::string &objectId, log::LogContext &lc) override; + std::list<cta::common::dataStructures::RetrieveJob> getRetrieveJobs(const std::string &vid) const override; std::map<std::string, std::list<common::dataStructures::RetrieveJob>> getRetrieveJobs() const override; diff --git a/scheduler/OStoreDB/OStoreDBFactory.hpp b/scheduler/OStoreDB/OStoreDBFactory.hpp index 8bf7fbd473..79d7bdd9c3 100644 --- a/scheduler/OStoreDB/OStoreDBFactory.hpp +++ b/scheduler/OStoreDB/OStoreDBFactory.hpp @@ -229,6 +229,10 @@ public: m_OStoreDB.cancelRetrieve(instanceName, rqst, lc); } + void deleteFailed(const std::string &objectId, log::LogContext & lc) override { + m_OStoreDB.deleteFailed(objectId, lc); + } + void queueRepack(const SchedulerDatabase::QueueRepackRequest & repackRequest, log::LogContext& lc) override { m_OStoreDB.queueRepack(repackRequest, lc); } diff --git a/scheduler/Scheduler.cpp b/scheduler/Scheduler.cpp index 5f7e90a565..9300f51407 100644 --- a/scheduler/Scheduler.cpp +++ b/scheduler/Scheduler.cpp @@ -268,12 +268,16 @@ void Scheduler::deleteArchive(const std::string &instanceName, const common::dat } //------------------------------------------------------------------------------ -// cancelRetrieve +// abortRetrieve //------------------------------------------------------------------------------ void Scheduler::abortRetrieve(const std::string &instanceName, const common::dataStructures::CancelRetrieveRequest &request, log::LogContext & lc) { m_db.cancelRetrieve(instanceName, request, lc); } +void Scheduler::deleteFailed(const std::string &objectId, log::LogContext & lc) { + m_db.deleteFailed(objectId, lc); +} + //------------------------------------------------------------------------------ // updateFileInfo //------------------------------------------------------------------------------ diff --git a/scheduler/Scheduler.hpp b/scheduler/Scheduler.hpp index 5f6d3577ba..ecac5fdf64 100644 --- a/scheduler/Scheduler.hpp +++ b/scheduler/Scheduler.hpp @@ -167,6 +167,11 @@ public: void abortRetrieve(const std::string &instanceName, const cta::common::dataStructures::CancelRetrieveRequest &request, log::LogContext & lc); + /** + * Delete a job from the failed queue. + */ + void deleteFailed(const std::string &objectId, log::LogContext & lc); + /** * Update the file information of an archived file. * Throws a UserError exception in case of wrong request parameters (ex. unknown file id) diff --git a/scheduler/SchedulerDatabase.hpp b/scheduler/SchedulerDatabase.hpp index 539249db41..86af40f274 100644 --- a/scheduler/SchedulerDatabase.hpp +++ b/scheduler/SchedulerDatabase.hpp @@ -357,6 +357,13 @@ public: */ virtual void cancelArchive(const common::dataStructures::DeleteArchiveRequest& request, log::LogContext & lc) = 0; + /** + * Idempotently deletes the specified ArchiveRequest from the objectstore + * @param request, the ArchiveRequest to delete + * @param lc the LogContext + */ + virtual void deleteFailed(const std::string &objectId, log::LogContext & lc) = 0; + /** * Returns all of the queued archive jobs. The returned jobs are * grouped by tape pool and then sorted by creation time, oldest first. diff --git a/xroot_plugins/XrdSsiCtaRequestMessage.cpp b/xroot_plugins/XrdSsiCtaRequestMessage.cpp index 6fde3828d9..bf5b7b1095 100644 --- a/xroot_plugins/XrdSsiCtaRequestMessage.cpp +++ b/xroot_plugins/XrdSsiCtaRequestMessage.cpp @@ -137,6 +137,9 @@ void RequestMessage::process(const cta::xrd::Request &request, cta::xrd::Respons case cmd_pair(AdminCmd::CMD_FAILEDREQUEST, AdminCmd::SUBCMD_LS): processFailedRequest_Ls(response, stream); break; + case cmd_pair(AdminCmd::CMD_FAILEDREQUEST, AdminCmd::SUBCMD_RM): + processFailedRequest_Rm(response); + break; case cmd_pair(AdminCmd::CMD_GROUPMOUNTRULE, AdminCmd::SUBCMD_ADD): processGroupMountRule_Add(response); break; @@ -1060,6 +1063,19 @@ void RequestMessage::processFailedRequest_Ls(cta::xrd::Response &response, XrdSs +void RequestMessage::processFailedRequest_Rm(cta::xrd::Response &response) +{ + using namespace cta::admin; + + auto &objectId = getRequired(OptionString::OBJECTID); + + m_scheduler.deleteFailed(objectId, m_lc); + + response.set_type(cta::xrd::Response::RSP_SUCCESS); +} + + + void RequestMessage::processGroupMountRule_Add(cta::xrd::Response &response) { using namespace cta::admin; diff --git a/xroot_plugins/XrdSsiCtaRequestMessage.hpp b/xroot_plugins/XrdSsiCtaRequestMessage.hpp index 55fa5d9635..a9adaee034 100644 --- a/xroot_plugins/XrdSsiCtaRequestMessage.hpp +++ b/xroot_plugins/XrdSsiCtaRequestMessage.hpp @@ -172,6 +172,7 @@ private: void processDrive_Down (cta::xrd::Response &response); void processDrive_Ch (cta::xrd::Response &response); void processDrive_Rm (cta::xrd::Response &response); + void processFailedRequest_Rm (cta::xrd::Response &response); void processGroupMountRule_Add (cta::xrd::Response &response); void processGroupMountRule_Ch (cta::xrd::Response &response); void processGroupMountRule_Rm (cta::xrd::Response &response); diff --git a/xrootd-ssi-protobuf-interface b/xrootd-ssi-protobuf-interface index 8f52c91184..fe00c7bc15 160000 --- a/xrootd-ssi-protobuf-interface +++ b/xrootd-ssi-protobuf-interface @@ -1 +1 @@ -Subproject commit 8f52c91184ee20987455ca82323937e9bda037c1 +Subproject commit fe00c7bc15bd5a95326bdeb2fe5f5fe2a9316ddc -- GitLab