Software /
code /
prosody
File
util/hashring.lua @ 11571:a8f0f87e115a
prosody: Close the state on exit (ie garbage-collect everything)
This ensures __gc is called on everything that may need it, such as
database connections.
It was reported in the chat by Happy that SQLite3 does not close its
state cleanly in WAL mode, leaving the WAL file behind. This is probably
rather a bug in mod_storage_sql, but forcing a final GC sweep should
also help with such things everywhere.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Tue, 18 May 2021 20:08:37 +0200 |
parent | 11208:96429946a742 |
child | 12795:87424cbedc55 |
line wrap: on
line source
local function generate_ring(nodes, num_replicas, hash) local new_ring = {}; for _, node_name in ipairs(nodes) do for replica = 1, num_replicas do local replica_hash = hash(node_name..":"..replica); new_ring[replica_hash] = node_name; table.insert(new_ring, replica_hash); end end table.sort(new_ring); return new_ring; end local hashring_methods = {}; local hashring_mt = { __index = function (self, k) -- Automatically build self.ring if it's missing if k == "ring" then local ring = generate_ring(self.nodes, self.num_replicas, self.hash); rawset(self, "ring", ring); return ring; end return rawget(hashring_methods, k); end }; local function new(num_replicas, hash_function) return setmetatable({ nodes = {}, num_replicas = num_replicas, hash = hash_function }, hashring_mt); end; function hashring_methods:add_node(name) self.ring = nil; self.nodes[name] = true; table.insert(self.nodes, name); return true; end function hashring_methods:add_nodes(nodes) self.ring = nil; for _, node_name in ipairs(nodes) do if not self.nodes[node_name] then self.nodes[node_name] = true; table.insert(self.nodes, node_name); end end return true; end function hashring_methods:remove_node(node_name) self.ring = nil; if self.nodes[node_name] then for i, stored_node_name in ipairs(self.nodes) do if node_name == stored_node_name then self.nodes[node_name] = nil; table.remove(self.nodes, i); return true; end end end return false; end function hashring_methods:remove_nodes(nodes) self.ring = nil; for _, node_name in ipairs(nodes) do self:remove_node(node_name); end end function hashring_methods:clone() local clone_hashring = new(self.num_replicas, self.hash); clone_hashring:add_nodes(self.nodes); return clone_hashring; end function hashring_methods:get_node(key) local key_hash = self.hash(key); for _, replica_hash in ipairs(self.ring) do if key_hash < replica_hash then return self.ring[replica_hash]; end end return self.ring[self.ring[1]]; end return { new = new; }