From 140526fbd3bb7cb02f066ebae8846b70ae81c994 Mon Sep 17 00:00:00 2001 From: Kory Draughn Date: Mon, 22 Apr 2024 09:07:44 -0400 Subject: [PATCH] [111] Allow removal of data objects with only stale replicas. --- .../test_rule_engine_plugin_logical_quotas.py | 23 +++++++++++++++++++ src/handler.cpp | 19 ++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/packaging/test_rule_engine_plugin_logical_quotas.py b/packaging/test_rule_engine_plugin_logical_quotas.py index 38ace1a..2d62449 100644 --- a/packaging/test_rule_engine_plugin_logical_quotas.py +++ b/packaging/test_rule_engine_plugin_logical_quotas.py @@ -831,6 +831,29 @@ def test_quotas_do_not_block_non_administrators_from_creating_or_writing_data_ob self.assert_quotas(sandbox, expected_number_of_objects = 1, expected_size_in_bytes = file_size) + @unittest.skipIf(test.settings.RUN_IN_TOPOLOGY, "Skip for Topology Testing") + def test_data_objects_having_only_stale_replicas_can_be_removed__issue_111(self): + config = IrodsConfig() + + with lib.file_backed_up(config.server_config_path): + self.enable_rule_engine_plugin(config) + + col = self.user.session_collection + self.logical_quotas_start_monitoring_collection(col) + + # Create a non-empty data object. + data_object = f'{col}/test_data_objects_having_only_stale_replicas_can_be_removed__issue_111.txt' + contents = 'test_data_objects_having_only_stale_replicas_can_be_removed__issue_111' + self.user.assert_icommand(['istream', 'write', data_object], input=contents) + self.assert_quotas(col, expected_number_of_objects=1, expected_size_in_bytes=len(contents)) + + # Mark the replica stale. + lib.set_replica_status(self.admin1, data_object, 0, 0) + + # Show the data object was removed and the total data size was left as is. + self.user.assert_icommand(['irm', '-f', data_object]) + self.assert_quotas(col, expected_number_of_objects=0, expected_size_in_bytes=len(contents)) + # # Utility Functions # diff --git a/src/handler.cpp b/src/handler.cpp index ec7dd6e..fc0cd43 100644 --- a/src/handler.cpp +++ b/src/handler.cpp @@ -1229,7 +1229,24 @@ namespace irods::handler const auto& attrs = get_instance_config(_instance_configs, _instance_name).attributes(); if (auto collection = get_monitored_parent_collection(conn, attrs, input->objPath); collection) { - size_in_bytes_ = fs::server::data_object_size(conn, input->objPath); + try { + size_in_bytes_ = fs::server::data_object_size(conn, input->objPath); + } + catch (const fs::filesystem_error& e) { + // The filesystem library's data_object_size() function will throw an exception + // if the data object does not have any good replicas. Because the REP is designed + // to track the data size of good replicas, the only reasonable step is to leave + // the data size as is. + // + // Attempting to define rules for handling data objects without good replicas + // contains too many challenges. Relying on the admin to recalculate the totals is + // the best/safest approach. + if (e.code().value() != SYS_NO_GOOD_REPLICA) { + rodsLog(LOG_ERROR, e.what()); + addRErrorMsg(&get_rei(_effect_handler).rsComm->rError, e.code().value(), e.what()); + return ERROR(e.code().value(), e.what()); + } + } } } catch (const irods::exception& e) {