matanper commented on code in PR #69290:
URL: https://github.com/apache/doris/pull/69290#discussion_r4376318440


##########
cloud/src/recycler/checker.cpp:
##########
@@ -1049,14 +1052,32 @@ int InstanceChecker::do_inverted_check() {
     // so we choose to skip here.
     TEST_SYNC_POINT_RETURN_WITH_VALUE("InstanceChecker::do_inverted_check", 
(int)0);
 
-    for (auto& [_, accessor] : accessor_map_) {
+    // Several resources may be backed by the same storage location, e.g. 
storage vaults on the same
+    // bucket and prefix with different credentials. List each location only 
once, otherwise its
+    // objects would be scanned and their leaks counted repeatedly. Compare 
the location as
+    // configured, not the normalized `uri()`: prefixes "a/b" and "a//b" share 
a uri but hold
+    // different objects, and skipping one would hide its leaks.
+    std::unordered_set<std::string> checked_locations;
+    for (auto& [resource_id, accessor] : accessor_map_) {

Review Comment:
   Fixed in 22b5e5a254a, root made alias-safe in a7ce4faabe7. Each accessor now 
has a `StorageRoot` (the S3 bucket, empty for HDFS, plus the prefix without 
empty path components). When another vault's root is inside the listed `data/` 
of the vault being scanned (e.g. `root/data` inside `root`), the parent skips 
that `data/.../data/` subtree; those objects are checked once, when the child 
vault is listed. Test: `InvertedCheckTest.nested_vault`.



##########
cloud/src/recycler/checker.cpp:
##########
@@ -946,16 +940,19 @@ int InstanceChecker::do_inverted_check() {
             return -1;
         }
 
-        if (tablet_rowsets_cache.tablet_id == tablet_id) {
-            if (tablet_rowsets_cache.rowset_ids.contains(rowset_id)) {
-                return 0;
-            } else {
-                LOG(WARNING) << "rowset not exists, key=" << obj_key;
-                return -1;
-            }
+        if (tablet_rowsets_cache.tablet_id == tablet_id &&

Review Comment:
   Fixed in 22b5e5a254a, root made alias-safe in a7ce4faabe7. The tablet cache 
now keeps `rowset_id -> resource_id`, and a segment is only covered by its 
rowset if the rowset's vault has the root it was listed from; otherwise it is a 
leak (a cache hit that fails the check re-reads the meta first, as for a miss). 
Ownership compares roots, not listing locations, and the root is built to err 
toward "same": it is the bucket (empty for HDFS) plus the prefix without empty 
path components, with no endpoint/fs_name since those have aliases (http/https, 
internal/public endpoints; host/FQDN/IP/nameservice). So a different root 
surely means different paths, and vaults that may be the same storage (other 
credentials, an endpoint alias) accept each other's objects: an ambiguity can 
only hide a copy, never report live data. A resource with no accessor (an HDFS 
vault in a build without HDFS) is trusted. Test: 
`InvertedCheckTest.segment_in_another_vault_is_leak`.



##########
cloud/src/recycler/hdfs_accessor.cpp:
##########
@@ -325,11 +327,44 @@ class HdfsListIterator final : public ListIterator {
     std::vector<DirEntries> level_dirs_;
 };
 
-HdfsAccessor::HdfsAccessor(const HdfsVaultInfo& info)
-        : StorageVaultAccessor(AccessorType::HDFS), info_(info), 
prefix_(info.prefix()) {
-    if (!prefix_.empty() && prefix_[0] != '/') {
-        prefix_.insert(prefix_.begin(), '/');
+namespace {
+
+// Either empty or starts with '/', e.g. "p1" and "/p1" are the same directory
+std::string accessor_prefix(const HdfsVaultInfo& info) {
+    std::string prefix = info.prefix();
+    if (!prefix.empty() && prefix[0] != '/') {
+        prefix.insert(prefix.begin(), '/');
     }
+    return prefix;
+}
+
+// fs_name and prefix name the directory, but a logical nameservice in fs_name 
resolves through the
+// vault's hdfs_confs: two vaults with fs_name hdfs://ns and prefix /warehouse 
are different
+// clusters when their dfs.namenode.rpc-address.ns.* differ. Append the 
effective confs, sorted by
+// key, so equal locations mean equal configurations; differences that do not 
matter only cost a
+// second listing. '\n' separates the parts, so e.g. hdfs://ns/a + /b and 
hdfs://ns + /a/b differ.
+std::string accessor_location(const HdfsVaultInfo& info) {
+    // libhdfs applies builder confs so that the first value set for a key 
wins: keep that one
+    std::map<std::string, std::string> confs;
+    for (const auto& conf : info.build_conf().hdfs_confs()) {
+        confs.emplace(conf.key(), conf.value());

Review Comment:
   Fixed in 22b5e5a254a: the location keeps all `hdfs_confs` in their 
configured order instead of picking a winner, so identical locations mean 
identical configurations under either precedence. A reordering now only costs 
an extra listing (the root, and so ownership, ignores confs). Test: 
`HdfsAccessorLocationTest.location`.



##########
cloud/src/recycler/s3_accessor.cpp:
##########
@@ -310,8 +310,12 @@ std::optional<S3Conf> S3Conf::from_obj_store_info(const 
ObjectStoreInfoPB& obj_i
     return s3_conf;
 }
 
+// The location is endpoint, bucket and prefix as configured; `uri_` 
normalizes them for display.
+// '\n' never occurs in an endpoint or a bucket name, so different confs never 
collide.
 S3Accessor::S3Accessor(S3Conf conf)
-        : StorageVaultAccessor(AccessorType::S3), conf_(std::move(conf)) {}
+        : StorageVaultAccessor(AccessorType::S3,
+                               conf.endpoint + '\n' + conf.bucket + '\n' + 
conf.prefix),

Review Comment:
   Fixed in 22b5e5a254a: the S3 location adds provider, ak, role_arn, 
external_id and the credential provider type (never the sk), so vaults that 
differ only in identity are listed separately. The root stays 
endpoint/bucket/prefix, so the duplicate listing does not turn into false 
leaks. Test: `S3AccessorLocationTest.location_includes_the_credential_identity`.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to