Skip to content

Commit

Permalink
re-insert hosts entries to cache if it is evicted
Browse files Browse the repository at this point in the history
  • Loading branch information
chobits committed Apr 2, 2024
1 parent bb8b0de commit 2dddd54
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 25 deletions.
48 changes: 31 additions & 17 deletions kong/dns/client.lua
Original file line number Diff line number Diff line change
Expand Up @@ -128,44 +128,51 @@ end


local init_hosts do
local function insert_answer_into_cache(cache, address, name, qtype)
-- insert via the `:get` callback to prevent inter-process communication
cache:get(name .. ":" .. qtype, nil, function()
return {
local function insert_answer_into_cache(cache, hosts_cache, address, name, qtype)
local key = name .. ":" .. qtype
local answers = {
ttl = LONG_LASTING_TTL,
expire = now() + LONG_LASTING_TTL,
{
name = name,
type = qtype,
address = address,
class = 1,
ttl = LONG_LASTING_TTL,
expire = now() + LONG_LASTING_TTL,
{
name = name,
type = qtype,
address = address,
class = 1,
ttl = LONG_LASTING_TTL,
},
}, nil, LONG_LASTING_TTL
},
}

-- insert via the `:get` callback to prevent inter-process communication
cache:get(key, nil, function()
return answers, nil, LONG_LASTING_TTL
end)

-- used for the host entry eviction
hosts_cache[key] = answers
end

-- insert hosts into cache
function init_hosts(cache, path, preferred_ip_type)
local hosts = parse_hosts(path)
local hosts_cache = {}

for name, address in pairs(hosts) do
name = string_lower(name)

if address.ipv4 then
insert_answer_into_cache(cache, address.ipv4, name, TYPE_A)
insert_answer_into_cache(cache, hosts_cache, address.ipv4, name, TYPE_A)
insert_last_type(cache, name, TYPE_A)
end

if address.ipv6 then
insert_answer_into_cache(cache, address.ipv6, name, TYPE_AAAA)
insert_answer_into_cache(cache, hosts_cache, address.ipv6, name, TYPE_AAAA)
if not address.ipv4 or preferred_ip_type == TYPE_AAAA then
insert_last_type(cache, name, TYPE_AAAA)
end
end
end

return hosts
return hosts, hosts_cache
end
end

Expand Down Expand Up @@ -286,7 +293,7 @@ function _M.new(opts)
preferred_ip_type = preferred_ip_type or TYPE_A

-- parse hosts
local hosts = init_hosts(cache, opts.hosts, preferred_ip_type)
local hosts, hosts_cache = init_hosts(cache, opts.hosts, preferred_ip_type)

return setmetatable({
cache = cache,
Expand All @@ -298,6 +305,7 @@ function _M.new(opts)
error_ttl = opts.error_ttl or DEFAULT_ERROR_TTL,
stale_ttl = opts.stale_ttl or DEFAULT_STALE_TTL,
empty_ttl = opts.empty_ttl or DEFAULT_EMPTY_TTL,
hosts_cache = hosts_cache,
search_types = search_types,

-- TODO: Make the table readonly. But if `string.buffer.encode/decode` and
Expand Down Expand Up @@ -443,6 +451,12 @@ end
local function resolve_name_type_callback(self, name, qtype, cache_only, short_key, tries)
local key = name .. ":" .. qtype

-- check if this key exists in the hosts file (it maybe evicted from cache)
local answers = self.hosts_cache[key]
if answers then
return answers, nil, answers.ttl
end

-- `:peek(stale=true)` verifies if the expired key remains in L2 shm, then
-- initiates an asynchronous background updating task to refresh it.
local ttl, _, answers = self.cache:peek(key, true)
Expand Down
10 changes: 2 additions & 8 deletions kong/dns/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ end

-- construct names from resolv options: search, ndots and domain
function _M.search_names(name, resolv, hosts)
if not resolv.search or _M.is_fqdn(name, resolv.ndots) then
if not resolv.search or _M.is_fqdn(name, resolv.ndots) or (hosts and hosts[name]) then
return { name }
end

Expand All @@ -179,13 +179,7 @@ function _M.search_names(name, resolv, hosts)
table_insert(names, name .. "." .. suffix)
end

-- Always search for the original name.
-- If found in the hosts file, prioritize its search.
if hosts and hosts[name] then
table_insert(names, 1, name)
else
table_insert(names, name)
end
table_insert(names, name) -- append the original name at last

return names
end
Expand Down
20 changes: 20 additions & 0 deletions spec/01-unit/30-new-dns-client/02-old_client_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,26 @@ describe("[DNS client]", function()
answers = cli.cache:get("localhost:1")
assert.is_nil(answers)
end)

it("cache evication", function()
writefile(hosts_path, "::1:2:3:4 localhost")
local cli = assert(client_new())

local answers = cli.cache:get("localhost:28")
assert.equal("[::1:2:3:4]", answers[1].address)

-- evict it
cli.cache:delete("localhost:28")
answers = cli.cache:get("localhost:28")
assert.equal(nil, answers)

-- resolve and re-insert it into cache
answers = cli:resolve("localhost")
assert.equal("[::1:2:3:4]", answers[1].address)

answers = cli.cache:get("localhost:28")
assert.equal("[::1:2:3:4]", answers[1].address)
end)
end)
end)

Expand Down

0 comments on commit 2dddd54

Please sign in to comment.