Coverage Report

Created: 2026-05-21 16:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/util/dns_cache.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#pragma once
19
20
#include <chrono>
21
#include <cstdint>
22
#include <functional>
23
#include <iostream>
24
#include <shared_mutex>
25
#include <string>
26
#include <thread>
27
#include <unordered_map>
28
29
#include "common/status.h"
30
31
namespace doris {
32
33
// Same as
34
// fe/fe-core/src/main/java/org/apache/doris/common/DNSCache.java
35
class DNSCache {
36
public:
37
    using Resolver = std::function<Status(const std::string&, std::string&, bool)>;
38
39
    DNSCache();
40
41
    // Test-only constructor: uses a custom resolver and does NOT start the
42
    // background refresh thread.  Call refresh_for_test() to drive one cycle.
43
    explicit DNSCache(Resolver resolver);
44
45
    ~DNSCache();
46
47
    // get ip by hostname
48
    Status get(const std::string& hostname, std::string* ip);
49
50
private:
51
    // Resolve hostname to IP address.
52
    // If resolution fails, falls back to cached IP if available.
53
    // Returns the resolved IP, or cached IP on failure, or empty string if no cache available.
54
    std::string _resolve_hostname(const std::string& hostname);
55
56
    // update the ip of hostname in cache; if out_failures is non-null, it is
57
    // set to the current consecutive failure count for hostname (read under the
58
    // same lock used to update cache, avoiding a second lock acquisition).
59
    Status _update(const std::string& hostname, uint32_t* out_failures = nullptr);
60
61
    // erase a hostname from cache (with unique_lock)
62
    void _erase(const std::string& hostname);
63
64
    // one refresh cycle: update every cached hostname and evict if needed
65
    void _refresh_once();
66
67
    // a function for refresh daemon thread
68
    // update cache at fix internal
69
    void _refresh_cache();
70
71
    // ── test helpers (accessible via friend class DNSCacheTest) ──────────────
72
14
    size_t size_for_test() const {
73
14
        std::shared_lock<std::shared_mutex> lock(mutex);
74
14
        return cache.size();
75
14
    }
76
77
3
    uint32_t failure_count_for_test(const std::string& hostname) const {
78
3
        std::shared_lock<std::shared_mutex> lock(mutex);
79
3
        auto it = failure_count.find(hostname);
80
3
        return it != failure_count.end() ? it->second : 0;
81
3
    }
82
83
    // Run one refresh cycle synchronously (no sleep).  Only meaningful when
84
    // the object was constructed with the test constructor (no background thread).
85
11
    void refresh_for_test() { _refresh_once(); }
86
87
    friend class DNSCacheTest;
88
89
private:
90
    Resolver _resolver; // null → use global hostname_to_ip
91
    // hostname -> ip
92
    std::unordered_map<std::string, std::string> cache;
93
    // hostname -> consecutive resolution failure count
94
    std::unordered_map<std::string, uint32_t> failure_count;
95
    mutable std::shared_mutex mutex;
96
    std::thread refresh_thread;
97
    bool stop_refresh = false;
98
};
99
100
} // end of namespace doris