This is an automated email from the ASF dual-hosted git repository.
wyxxxcat pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 73d9733c78a [fix](cloud) Fix recycler checks for shared storage in
clone and rollback scenarios (#69492)
73d9733c78a is described below
commit 73d9733c78a48c82f04aa5f70fe118bebd11b6f4
Author: Yixuan Wang <[email protected]>
AuthorDate: Wed Oct 28 10:08:55 2026 +0800
[fix](cloud) Fix recycler checks for shared storage in clone and rollback
scenarios (#69492)
### What problem does this PR solve?
Issue Number: close #xxx
Related PR: #xxx
Problem Summary:
### Release note
None
### Check List (For Author)
- Test <!-- At least one of them must be included. -->
- [ ] Regression test
- [ ] Unit Test
- [ ] Manual test (add detailed scripts or steps below)
- [ ] No need to test or manual test. Explain why:
- [ ] This is a refactor/code format and no logic has been changed.
- [ ] Previous test can cover this change.
- [ ] No code files have been changed.
- [ ] Other reason <!-- Add your reason? -->
- Behavior changed:
- [ ] No.
- [ ] Yes. <!-- Explain the behavior change -->
- Does this need documentation?
- [ ] No.
- [ ] Yes. <!-- Add document PR link here. eg:
https://github.com/apache/doris-website/pull/1214 -->
### Check List (For Reviewer who merge this PR)
- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label <!-- Add branch pick label that this PR
should merge into -->
---
cloud/src/recycler/checker.cpp | 207 +++++++++++++++++++--
cloud/src/recycler/checker.h | 92 ++++++++-
cloud/src/recycler/recycler_service.cpp | 2 +-
.../plugins/snapshot_recycler_plugin.groovy | 15 +-
4 files changed, 282 insertions(+), 34 deletions(-)
diff --git a/cloud/src/recycler/checker.cpp b/cloud/src/recycler/checker.cpp
index e122bbfb861..f1caa677b75 100644
--- a/cloud/src/recycler/checker.cpp
+++ b/cloud/src/recycler/checker.cpp
@@ -130,7 +130,8 @@ TxnErrorCode collect_pending_table_stream_drops(
return iter->error_code();
}
-Checker::Checker(std::shared_ptr<TxnKv> txn_kv) : txn_kv_(std::move(txn_kv)) {
+Checker::Checker(std::shared_ptr<TxnKv> txn_kv)
+ : txn_kv_(std::move(txn_kv)),
resource_mgr_(std::make_shared<ResourceManager>(txn_kv_)) {
ip_port_ = std::string(butil::my_ip_cstr()) + ":" +
std::to_string(config::brpc_listen_port);
}
@@ -150,13 +151,18 @@ int Checker::start() {
std::chrono::seconds(config::recycler_sleep_before_scheduling_seconds));
while (!stopped()) {
std::vector<InstanceInfoPB> instances;
- get_all_instances(txn_kv_.get(), instances);
+ if (get_all_instances(txn_kv_.get(), instances) != 0) {
+ // Do not publish a partial owner index after a failed scan.
+ instances.clear();
+ }
LOG(INFO) << "Checker get instances: " << [&instances] {
std::stringstream ss;
for (auto& i : instances) ss << ' ' << i.instance_id();
return ss.str();
}();
if (!instances.empty()) {
+ auto shared_storage_index =
+ std::make_shared<SharedStorageIndex>(txn_kv_,
instances);
// enqueue instances
std::lock_guard lock(mtx_);
for (auto& instance : instances) {
@@ -169,7 +175,8 @@ int Checker::start() {
pending_instance_map_.insert({instance.instance_id(), enqueue_time_s});
// skip instance already in pending queue
if (success) {
- pending_instance_queue_.push_back(std::move(instance));
+ pending_instance_queue_.push_back(
+ {std::move(instance), shared_storage_index});
}
}
pending_instance_cond_.notify_all();
@@ -193,6 +200,7 @@ int Checker::start() {
while (!stopped()) {
// fetch instance to check
InstanceInfoPB instance;
+ std::shared_ptr<SharedStorageIndex> shared_storage_index;
long enqueue_time_s = 0;
{
std::unique_lock lock(mtx_);
@@ -202,7 +210,9 @@ int Checker::start() {
if (stopped()) {
return;
}
- instance = std::move(pending_instance_queue_.front());
+ instance = std::move(pending_instance_queue_.front().instance);
+ shared_storage_index =
+
std::move(pending_instance_queue_.front().shared_storage_index);
pending_instance_queue_.pop_front();
enqueue_time_s = pending_instance_map_[instance.instance_id()];
pending_instance_map_.erase(instance.instance_id());
@@ -217,7 +227,9 @@ int Checker::start() {
continue;
}
}
- auto checker = std::make_shared<InstanceChecker>(txn_kv_,
instance.instance_id());
+ auto checker = std::make_shared<InstanceChecker>(txn_kv_,
instance.instance_id(),
+ resource_mgr_,
+
std::move(shared_storage_index));
if (checker->init(instance) != 0) {
LOG(WARNING) << "failed to init instance checker, instance_id="
<< instance.instance_id();
@@ -424,7 +436,7 @@ void Checker::do_inspect(const InstanceInfoPB& instance) {
<< " key=" << hex(check_job_key);
return;
}
- auto checker = InstanceChecker(txn_kv_, instance.instance_id());
+ auto checker = InstanceChecker(txn_kv_, instance.instance_id(),
resource_mgr_);
if (checker.init(instance) != 0) {
LOG_CHECK_INTERVAL_ALARM << "failed to init instance checker,
instance_id="
<< instance.instance_id();
@@ -519,16 +531,156 @@ int key_exist(TxnKv* txn_kv, std::string_view key) {
}
}
-InstanceChecker::InstanceChecker(std::shared_ptr<TxnKv> txn_kv, const
std::string& instance_id)
- : txn_kv_(txn_kv), instance_id_(instance_id) {
+SharedStorageIndex::SharedStorageIndex(std::shared_ptr<TxnKv> txn_kv,
+
std::optional<std::vector<InstanceInfoPB>> instances)
+ : txn_kv_(std::move(txn_kv)),
preloaded_instances_(std::move(instances)) {}
+
+std::optional<SharedStorageIndex::StorageLocation>
SharedStorageIndex::s3_location(
+ const ObjectStoreInfoPB& obj_info) {
+ // Missing connection info must not make unrelated resources match.
+ if (obj_info.endpoint().empty() || obj_info.bucket().empty()) {
+ return std::nullopt;
+ }
+ return StorageLocation {"s3", obj_info.endpoint(), obj_info.bucket(),
obj_info.prefix()};
+}
+
+std::optional<SharedStorageIndex::StorageLocation>
SharedStorageIndex::hdfs_location(
+ const HdfsVaultInfo& hdfs_info) {
+ if (hdfs_info.build_conf().fs_name().empty()) {
+ return std::nullopt;
+ }
+ return StorageLocation {"hdfs", hdfs_info.build_conf().fs_name(), "",
hdfs_info.prefix()};
+}
+
+void SharedStorageIndex::ensure_loaded() {
+ std::call_once(load_once_, [this] {
+ load_status_ = load_all_instances();
+ if (load_status_ != 0) {
+ // Never expose a partially built index.
+ instance_resource_locations_.clear();
+ location_to_owners_.clear();
+ }
+ });
+}
+
+int SharedStorageIndex::load_all_instances() {
+ std::vector<InstanceInfoPB> instances;
+ if (preloaded_instances_.has_value()) {
+ instances = std::move(*preloaded_instances_);
+ preloaded_instances_.reset();
+ } else if (get_all_instances(txn_kv_.get(), instances) != 0) {
+ return -1;
+ }
+ // Load all instances, even those not scheduled for checking: decoupled
+ // instances can still share storage with the checked one.
+ for (const auto& instance : instances) {
+ if (load_instance(instance) != 0) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int SharedStorageIndex::load_instance(const InstanceInfoPB& instance) {
+ const std::string& instance_id = instance.instance_id();
+ // Register the instance even if it has no resources, so that it can be
told
+ // apart from an unknown instance.
+ instance_resource_locations_[instance_id];
+ // Locations of the resources in `resource_ids` are filled by the vault
scan below.
+ for (const auto& resource_id : instance.resource_ids()) {
+ add_resource(instance_id, resource_id, std::nullopt);
+ }
+ for (const auto& obj_info : instance.obj_info()) {
+ add_resource(instance_id, obj_info.id(), s3_location(obj_info));
+ }
+ if (instance.resource_ids().empty()) {
+ return 0;
+ }
+ return load_storage_vaults(instance_id);
+}
+
+int SharedStorageIndex::load_storage_vaults(const std::string& instance_id) {
+ std::unique_ptr<Transaction> txn;
+ if (txn_kv_->create_txn(&txn) != TxnErrorCode::TXN_OK) {
+ return -1;
+ }
+ auto iter = txn->full_range_get(storage_vault_key({instance_id, ""}),
+ storage_vault_key({instance_id, "\xff"}));
+ for (auto entry = iter->next(); entry.has_value(); entry = iter->next()) {
+ StorageVaultPB vault;
+ if (!vault.ParseFromArray(entry->second.data(), entry->second.size()))
{
+ LOG_WARNING("malformed storage vault").tag("instance_id",
instance_id);
+ return -1;
+ }
+ std::optional<StorageLocation> location;
+ if (vault.has_obj_info()) {
+ location = s3_location(vault.obj_info());
+ } else if (vault.has_hdfs_info()) {
+ location = hdfs_location(vault.hdfs_info());
+ }
+ add_resource(instance_id, vault.id(), std::move(location));
+ }
+ return iter->is_valid() ? 0 : -1;
+}
+
+void SharedStorageIndex::add_resource(const std::string& instance_id,
+ const std::string& resource_id,
+ std::optional<StorageLocation> location)
{
+ auto& resource_location =
instance_resource_locations_[instance_id][resource_id];
+ if (!location.has_value()) {
+ return;
+ }
+ if (!resource_location.has_value()) {
+ resource_location = location;
+ }
+ location_to_owners_[std::move(*location)].push_back({instance_id,
resource_id});
+}
+
+int SharedStorageIndex::get_shared_resource_owners(std::string_view
instance_id,
+ SharedResourceOwners*
owners) {
+ ensure_loaded();
+ owners->clear();
+ if (load_status_ != 0) {
+ return -1;
+ }
+ auto instance =
instance_resource_locations_.find(std::string(instance_id));
+ if (instance == instance_resource_locations_.end()) {
+ LOG_WARNING("instance not found while checking shared resources")
+ .tag("instance_id", instance_id);
+ return -1;
+ }
+ for (const auto& [resource_id, location] : instance->second) {
+ if (location.has_value()) {
+ (*owners)[resource_id] = location_to_owners_.at(*location);
+ } else {
+ // Without a known location, the resource is only owned by its own
instance.
+ (*owners)[resource_id] = {{instance->first, resource_id}};
+ }
+ }
+ return 0;
+}
+
+InstanceChecker::InstanceChecker(std::shared_ptr<TxnKv> txn_kv, const
std::string& instance_id,
+ std::shared_ptr<ResourceManager> resource_mgr,
+ std::shared_ptr<SharedStorageIndex>
shared_storage_index)
+ : txn_kv_(txn_kv),
+ instance_id_(instance_id),
+ resource_mgr_(std::move(resource_mgr)),
+ shared_storage_index_(std::move(shared_storage_index)) {
snapshot_manager_ = create_snapshot_manager(txn_kv);
- resource_mgr_ = std::make_shared<ResourceManager>(std::move(txn_kv));
- resource_mgr_->init();
+ if (!shared_storage_index_) {
+ shared_storage_index_ = std::make_shared<SharedStorageIndex>(txn_kv);
+ }
+ if (!resource_mgr_) {
+ resource_mgr_ = std::make_shared<ResourceManager>(std::move(txn_kv));
+ resource_mgr_->init();
+ }
}
int InstanceChecker::init(const InstanceInfoPB& instance) {
table_stream_versioned_write_ = instance.multi_version_status() ==
MULTI_VERSION_WRITE_ONLY ||
instance.multi_version_status() ==
MULTI_VERSION_READ_WRITE;
+ resource_mgr_->refresh_instance(instance_id_, instance);
int ret = init_obj_store_accessors(instance);
if (ret != 0) {
@@ -655,6 +807,7 @@ int InstanceChecker::do_check() {
struct TabletFiles {
int64_t tablet_id {0};
+ std::string resource_id;
std::unordered_set<std::string> files;
};
TabletFiles tablet_files_cache;
@@ -678,7 +831,8 @@ int InstanceChecker::do_check() {
};
++num_scanned_with_segment;
- if (tablet_files_cache.tablet_id != rs_meta.tablet_id()) {
+ if (tablet_files_cache.tablet_id != rs_meta.tablet_id() ||
+ tablet_files_cache.resource_id != rs_meta.resource_id()) {
long tablet_volume = 0;
// Clear cache
tablet_files_cache.tablet_id = 0;
@@ -706,7 +860,12 @@ int InstanceChecker::do_check() {
tablet_files_cache.files.insert(std::move(file->path));
tablet_volume += file->size;
}
+ if (!list_iter->is_valid()) {
+ check_ret = -1;
+ return;
+ }
tablet_files_cache.tablet_id = rs_meta.tablet_id();
+ tablet_files_cache.resource_id = rs_meta.resource_id();
instance_volume += tablet_volume;
}
@@ -744,7 +903,13 @@ int InstanceChecker::do_check() {
}
TabletIndexPB tablet_index;
- if (get_tablet_idx(txn_kv_.get(), instance_id_, rs_meta.tablet_id(),
tablet_index) == -1) {
+ CloneChainReader reader(instance_id_, resource_mgr_.get());
+ int index_ret =
+ get_tablet_idx(txn_kv_.get(), instance_id_,
rs_meta.tablet_id(), tablet_index);
+ if (index_ret == 1) {
+ err = reader.get_tablet_index(txn.get(), rs_meta.tablet_id(),
&tablet_index);
+ }
+ if (index_ret < 0 || err != TxnErrorCode::TXN_OK) {
LOG(WARNING) << "failed to get tablet index, tablet_id= " <<
rs_meta.tablet_id();
check_ret = -1;
return;
@@ -754,16 +919,20 @@ int InstanceChecker::do_check() {
meta_schema_key({instance_id_, tablet_index.index_id(),
rs_meta.schema_version()});
ValueBuf tablet_schema_val;
err = cloud::blob_get(txn.get(), tablet_schema_key,
&tablet_schema_val);
-
- if (err != TxnErrorCode::TXN_OK) {
+ auto* schema = rs_meta.mutable_tablet_schema();
+ if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ // Clone/rollback rowsets may reference a schema that only exists
in
+ // versioned metadata, possibly in an ancestor of the current
instance.
+ err = reader.get_tablet_schema(txn.get(), tablet_index.index_id(),
+ rs_meta.schema_version(), schema);
+ } else if (err == TxnErrorCode::TXN_OK &&
!parse_schema_value(tablet_schema_val, schema)) {
check_ret = -1;
- LOG(WARNING) << "failed to get schema, err=" << err;
+ LOG(WARNING) << "malformed schema value, key=" <<
hex(tablet_schema_key);
return;
}
-
- auto* schema = rs_meta.mutable_tablet_schema();
- if (!parse_schema_value(tablet_schema_val, schema)) {
- LOG(WARNING) << "malformed schema value, key=" <<
hex(tablet_schema_key);
+ if (err != TxnErrorCode::TXN_OK) {
+ check_ret = -1;
+ LOG(WARNING) << "failed to get schema, err=" << err;
return;
}
diff --git a/cloud/src/recycler/checker.h b/cloud/src/recycler/checker.h
index 9a643f2f382..630d1526d90 100644
--- a/cloud/src/recycler/checker.h
+++ b/cloud/src/recycler/checker.h
@@ -26,9 +26,12 @@
#include <cstdint>
#include <deque>
#include <functional>
-#include <memory>
+#include <map>
+#include <mutex>
+#include <optional>
#include <string_view>
#include <thread>
+#include <tuple>
#include <unordered_map>
#include <unordered_set>
@@ -46,6 +49,8 @@ class StorageVaultAccessor;
class InstanceChecker;
class TxnKv;
class InstanceInfoPB;
+class ObjectStoreInfoPB;
+class HdfsVaultInfo;
struct PendingTableStreamDrop {
int64_t base_db_id;
@@ -63,6 +68,77 @@ TxnErrorCode collect_pending_table_stream_drops(
const std::shared_ptr<TxnKv>& txn_kv, std::string_view instance_id,
std::unordered_map<int64_t, PendingTableStreamDrop>* pending_drops);
+struct SharedResourceOwner {
+ std::string instance_id;
+ std::string resource_id;
+};
+
+// resource id -> all instance/resource pairs that use the same physical
storage.
+using SharedResourceOwners = std::unordered_map<std::string,
std::vector<SharedResourceOwner>>;
+
+// Tells which instance/resource pairs write into the same physical storage.
+// Resource IDs are local to an instance, so the physical storage location is
+// matched instead: descendants can write into inherited resources even after
+// decoupling removes their source_instance_id.
+//
+// One index is shared by all checkers of a scheduling round. It is loaded
+// lazily on the first query, and the result (success or failure) is cached
+// until the round ends. A new round must create a new index to see changes.
+class SharedStorageIndex {
+public:
+ // If `instances` is given, it is used as the full instance list instead of
+ // scanning all instances from the kv store.
+ explicit SharedStorageIndex(
+ std::shared_ptr<TxnKv> txn_kv,
+ std::optional<std::vector<InstanceInfoPB>> instances =
std::nullopt);
+
+ // For every resource of `instance_id`, fill in all owners sharing its
physical storage.
+ // A resource without identifiable storage location is only owned by
itself.
+ // Return 0 on success, -1 if the index failed to load or the instance is
unknown.
+ // Never fills partial owners on failure.
+ int get_shared_resource_owners(std::string_view instance_id,
SharedResourceOwners* owners);
+
+private:
+ // Physical storage location. All fields must match exactly, overlapping
+ // prefixes are not merged. Credentials are deliberately not part of it.
+ struct StorageLocation {
+ std::string type; // "s3" or "hdfs"
+ std::string endpoint; // S3 endpoint, or HDFS fs_name
+ std::string bucket; // empty for HDFS
+ std::string prefix;
+
+ bool operator<(const StorageLocation& other) const {
+ return std::tie(type, endpoint, bucket, prefix) <
+ std::tie(other.type, other.endpoint, other.bucket,
other.prefix);
+ }
+ };
+
+ // Resources without connection info have no location, so that they never
+ // match unrelated resources.
+ using ResourceLocations = std::map<std::string,
std::optional<StorageLocation>>;
+
+ static std::optional<StorageLocation> s3_location(const ObjectStoreInfoPB&
obj_info);
+ static std::optional<StorageLocation> hdfs_location(const HdfsVaultInfo&
hdfs_info);
+
+ void ensure_loaded();
+ int load_all_instances();
+ int load_instance(const InstanceInfoPB& instance);
+ int load_storage_vaults(const std::string& instance_id);
+ void add_resource(const std::string& instance_id, const std::string&
resource_id,
+ std::optional<StorageLocation> location);
+
+ std::shared_ptr<TxnKv> txn_kv_;
+ // Consumed by the first load.
+ std::optional<std::vector<InstanceInfoPB>> preloaded_instances_;
+
+ std::once_flag load_once_;
+ int load_status_ = -1;
+ // instance_id -> (resource_id -> location)
+ std::unordered_map<std::string, ResourceLocations>
instance_resource_locations_;
+ // location -> all instance/resource pairs located there
+ std::map<StorageLocation, std::vector<SharedResourceOwner>>
location_to_owners_;
+};
+
class Checker {
public:
explicit Checker(std::shared_ptr<TxnKv> txn_kv);
@@ -82,6 +158,7 @@ private:
friend class RecyclerServiceImpl;
std::shared_ptr<TxnKv> txn_kv_;
+ std::shared_ptr<ResourceManager> resource_mgr_;
std::atomic_bool stopped_ {false};
std::string ip_port_;
std::vector<std::thread> workers_;
@@ -89,7 +166,11 @@ private:
std::mutex mtx_;
// notify check workers
std::condition_variable pending_instance_cond_;
- std::deque<InstanceInfoPB> pending_instance_queue_;
+ struct PendingInstance {
+ InstanceInfoPB instance;
+ std::shared_ptr<SharedStorageIndex> shared_storage_index;
+ };
+ std::deque<PendingInstance> pending_instance_queue_;
// instance_id -> enqueue_timestamp
std::unordered_map<std::string, long> pending_instance_map_;
std::unordered_map<std::string, std::shared_ptr<InstanceChecker>>
working_instance_map_;
@@ -101,7 +182,9 @@ private:
class InstanceChecker {
public:
- explicit InstanceChecker(std::shared_ptr<TxnKv> txn_kv, const std::string&
instance_id);
+ explicit InstanceChecker(std::shared_ptr<TxnKv> txn_kv, const std::string&
instance_id,
+ std::shared_ptr<ResourceManager> resource_mgr =
nullptr,
+ std::shared_ptr<SharedStorageIndex>
shared_storage_index = nullptr);
// Return 0 if success, otherwise error
int init(const InstanceInfoPB& instance);
// Return 0 if success.
@@ -169,6 +252,8 @@ public:
ResourceManager* resource_mgr() const { return resource_mgr_.get(); }
+ SharedStorageIndex* shared_storage_index() const { return
shared_storage_index_.get(); }
+
void get_all_accessor(std::vector<StorageVaultAccessor*>* accessors);
std::string_view instance_id() const { return instance_id_; }
@@ -280,6 +365,7 @@ private:
std::shared_ptr<SnapshotManager> snapshot_manager_;
std::shared_ptr<ResourceManager> resource_mgr_;
bool table_stream_versioned_write_ {false};
+ std::shared_ptr<SharedStorageIndex> shared_storage_index_;
};
} // namespace doris::cloud
diff --git a/cloud/src/recycler/recycler_service.cpp
b/cloud/src/recycler/recycler_service.cpp
index c9c68004f8a..e6559c4e8bc 100644
--- a/cloud/src/recycler/recycler_service.cpp
+++ b/cloud/src/recycler/recycler_service.cpp
@@ -393,7 +393,7 @@ void RecyclerServiceImpl::check_instance(const std::string&
instance_id, MetaSer
// skip instance already in pending queue
if (success) {
// TODO(plat1ko): Support high priority
- checker_->pending_instance_queue_.push_back(std::move(instance));
+ checker_->pending_instance_queue_.push_back({std::move(instance),
nullptr});
}
checker_->pending_instance_cond_.notify_all();
}
diff --git a/regression-test/plugins/snapshot_recycler_plugin.groovy
b/regression-test/plugins/snapshot_recycler_plugin.groovy
index 702e29043cc..4360291b7a9 100644
--- a/regression-test/plugins/snapshot_recycler_plugin.groovy
+++ b/regression-test/plugins/snapshot_recycler_plugin.groovy
@@ -40,8 +40,7 @@ def recyclerRequest = { Suite suite, String address, String
method, String path,
// The snapshot Docker suites set both scheduling intervals to 10 seconds.
Suite.metaClass.recycleAndCheckSnapshot = { String recyclerAddress, String
instanceId,
- int maxRounds = 10, int maxPolls =
60,
- boolean requireCheck = true ->
+ int maxRounds = 10, int maxPolls =
60 ->
Suite suite = delegate as Suite
assert maxRounds > 0 && maxPolls > 0
String token = "greedisgood9999"
@@ -87,11 +86,9 @@ Suite.metaClass.recycleAndCheckSnapshot = { String
recyclerAddress, String insta
for (int round = 1; round <= maxRounds; round++) {
suite.getLogger().info("Starting snapshot recycle/check:
instance=${instanceId}, round=${round}/${maxRounds}")
boolean recycled = runJob('recycle')
- // Check cloned instances through SQL below: their inherited snapshot
files do not
- // have snapshot keys in the derived instance, so the recycler checker
rejects them.
- boolean checked = !requireCheck || runJob('check')
+ boolean checked = runJob('check')
suite.getLogger().info("Snapshot recycle/check:
instance=${instanceId}, round=${round}/${maxRounds}, "
- + "recycled=${recycled}, checked=${checked},
checkRequired=${requireCheck}, jobs=${lastJobs}")
+ + "recycled=${recycled}, checked=${checked}, jobs=${lastJobs}")
if (recycled && checked) return
}
assert false : "Recycle/check failed after ${maxRounds} rounds:
instance=${instanceId}, jobs=${lastJobs}"
@@ -152,11 +149,7 @@ Suite.metaClass.checkSnapshotRecycle = { SuiteCluster
recyclerCluster, Map insta
}
}
instanceClusters.each { instanceId, dataCluster ->
- if (dataCluster != null && dataCluster != recyclerCluster) {
- suite.recycleAndCheckSnapshot(recyclerAddress,
instanceId.toString(), 10, 60, false)
- } else {
- suite.recycleAndCheckSnapshot(recyclerAddress,
instanceId.toString())
- }
+ suite.recycleAndCheckSnapshot(recyclerAddress, instanceId.toString())
}
instanceClusters.each { instanceId, dataCluster ->
if (dataCluster != null) {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]