Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use LMDB as DB-less storage #7885

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions kong-2.5.1-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ build = {
["kong.resty.ctx"] = "kong/resty/ctx.lua",
["kong.vendor.classic"] = "kong/vendor/classic.lua",

["kong.cache.lmdb"] = "kong/cache/lmdb/init.lua",
["kong.cache.lmdb.marshaller"] = "kong/cache/lmdb/marshaller.lua",

["kong.cmd"] = "kong/cmd/init.lua",
["kong.cmd.roar"] = "kong/cmd/roar.lua",
["kong.cmd.stop"] = "kong/cmd/stop.lua",
Expand Down
103 changes: 103 additions & 0 deletions kong/cache/lmdb/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
local marshaller = require("kong.cache.lmdb.marshaller")


local marshall = marshaller.marshall
local unmarshall = marshaller.unmarshall
local type = type
local pairs = pairs
local error = error
local max = math.max
local ngx = ngx
local ngx_log = ngx.log
local ERR = ngx.ERR
local NOTICE = ngx.NOTICE
local DEBUG = ngx.DEBUG


--[[
Hypothesis
----------

Item size: 1024 bytes
Max memory limit: 500 MiBs

LRU size must be: (500 * 2^20) / 1024 = 512000
Floored: 500.000 items should be a good default
--]]
local LRU_SIZE = 5e5


local _init = {}


local function log(lvl, ...)
return ngx_log(lvl, "[DB cache] ", ...)
end


local _M = {}
local mt = { __index = _M }


function _M.new(lmdb)
local self = {
lmdb = lmdb,
}

return setmetatable(self, mt)
end


--function _M:get_page(shadow)
-- if #self.mlcaches == 2 and shadow then
-- return self.page == 2 and 1 or 2
-- end
--
-- return self.page or 1
--end


function _M:get(key)
if type(key) ~= "string" then
error("key must be a string", 2)
end

local v, err = self.lmdb:get(key)
if err then
return nil, "failed to get from node cache: " .. err
end

return v and unmarshall(v) or nil
end


--function _M:get_bulk(bulk, opts)
-- if type(bulk) ~= "table" then
-- error("bulk must be a table", 2)
-- end
--
-- if opts ~= nil and type(opts) ~= "table" then
-- error("opts must be a table", 2)
-- end
--
-- local page = self:get_page((opts or {}).shadow)
-- local res, err = self.mlcaches[page]:get_bulk(bulk, opts)
-- if err then
-- return nil, "failed to get_bulk from node cache: " .. err
-- end
--
-- return res
--end


function _M:safe_set(key, value)
local str_marshalled, err = marshall(value)
if err then
return nil, err
end

return self.lmdb:set(key, str_marshalled)
end


return _M
122 changes: 122 additions & 0 deletions kong/cache/lmdb/marshaller.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
local _M = {}


local cjson = require("cjson.safe")
local tostring = tostring
local tonumber = tonumber
local type = type
local fmt = string.format
local sub = string.sub
local cjson_encode = cjson.encode
local cjson_decode = cjson.decode


local TYPES_LOOKUP = {
number = 1,
boolean = 2,
string = 3,
table = 4,
}


local marshallers = {
shm_value = function(str_value, value_type)
return fmt("%d:%s", value_type, str_value)
end,

shm_nil = function(at, ttl)
return "0:"
end,

[1] = function(number) -- number
return tostring(number)
end,

[2] = function(bool) -- boolean
return bool and "true" or "false"
end,

[3] = function(str) -- string
return str
end,

[4] = function(t) -- table
local json, err = cjson_encode(t)
if not json then
return nil, "could not encode table value: " .. err
end

return json
end,
}


function _M.marshall(value)
if value == nil then
return marshallers.shm_nil()
end

local value_type = TYPES_LOOKUP[type(value)]

if not marshallers[value_type] then
error("cannot cache value of type " .. type(value))
end

local str_marshalled, err = marshallers[value_type](value)
if not str_marshalled then
return nil, "could not serialize value for LMDB insertion: "
.. err
end

return marshallers.shm_value(str_marshalled, value_type)
end


local unmarshallers = {
shm_value = function(marshalled)
local value_type = sub(marshalled, 1, 1)
local str_value = sub(marshalled, 3)

return str_value, tonumber(value_type)
end,

[0] = function() -- nil
return nil
end,

[1] = function(str) -- number
return tonumber(str)
end,

[2] = function(str) -- boolean
return str == "true"
end,

[3] = function(str) -- string
return str
end,

[4] = function(str) -- table
local t, err = cjson_decode(str)
if not t then
return nil, "could not decode table value: " .. err
end

return t
end,
}


function _M.unmarshall(v)
local str_serialized, value_type = unmarshallers.shm_value(v)

local value, err = unmarshallers[value_type](str_serialized)
if err then
return nil, err
end

return value
end


return _M
Loading