You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

84 lines
2.2 KiB
Lua

local mod_name = (...):match ( "^(.*)%..-$" )
local setmetatable = setmetatable
local strbyte = string.byte
local strformat = string.format
local t_insert = table.insert
local t_concat = table.concat
local hasposix , posix = pcall ( require , "posix" )
local ll = require ( mod_name .. ".ll" )
local num_to_le_uint = ll.num_to_le_uint
local num_to_be_uint = ll.num_to_be_uint
local function _tostring(ob)
local t = {}
for i = 1 , 12 do
t_insert(t, strformat("%02x", strbyte(ob.id, i, i)))
end
return t_concat(t)
end
local function _get_ts(ob)
return ll.be_uint_to_num(ob.id, 1, 4)
end
local function _get_hostname(ob)
local t = {}
for i = 5, 7 do
t_insert(t, strformat("%02x", strbyte(ob.id, i, i)))
end
return t_concat(t)
end
local function _get_pid(ob)
return ll.be_uint_to_num(ob.id, 8, 9)
end
local function _get_inc(ob)
return ll.be_uint_to_num(ob.id, 10, 12)
end
local object_id_mt = {
__tostring = _tostring;
__eq = function ( a , b ) return a.id == b.id end ;
}
local machineid
if hasposix then
machineid = posix.uname("%n")
else
machineid = assert(io.popen("uname -n")):read("*l")
end
machineid = ngx.md5_bin(machineid):sub(1, 3)
local pid = num_to_le_uint(bit.band(ngx.worker.pid(), 0xFFFF), 2)
local inc = 0
local function generate_id ( )
inc = inc + 1
-- "A BSON ObjectID is a 12-byte value consisting of a 4-byte timestamp (seconds since epoch), a 3-byte machine id, a 2-byte process id, and a 3-byte counter. Note that the timestamp and counter fields must be stored big endian unlike the rest of BSON"
return num_to_be_uint ( os.time ( ) , 4 ) .. machineid .. pid .. num_to_be_uint ( inc , 3 )
end
local function new_object_id(str)
if str then
assert(#str == 12)
else
str = generate_id()
end
return setmetatable({id = str,
tostring = _tostring,
get_ts = _get_ts,
get_pid = _get_pid,
get_hostname = _get_hostname,
get_inc = _get_inc,
} , object_id_mt)
end
return {
new = new_object_id ;
metatable = object_id_mt ;
}