Home

Awesome

Name

lua-resty-bloomd - Is a client library based on ngx_lua to interface with bloomd servers(https://github.com/armon/bloomd)<br/>

Bloomd is a high-performance C server which is used to expose bloom filters and operations over them to networked clients.

Table of Contents

Status

This library is production ready.

Synopsis

    lua_package_path "/path/to/lua-resty-bloomd/lib/?.lua;;";

    server {
        location /test {
            content_by_lua '
            local bloomd = require("resty.bloomd")
            
            local function debug(name, ok, err)
            	if type(err) == 'table' then
            		local t = {}
            		for k, v in pairs(err) do 
            			table.insert(t, k .. ":" .. tostring(v))
            		end
            		err = table.concat(t, ",")
            	end
            	ngx.say(string.format("%15s -- ok: %5s, err: %s", name, tostring(ok), tostring(err)))
            end
            -- create a new instance and connect to the bloomd(127.0.0.1:8673)
            local filter_obj = bloomd:new("127.0.0.1", 8673, 2000)
            local function test_main()
            	local filter_name = "my_filter"
            	local capacity = 100001
            	local probability = 0.001
            	-- create a filter named filter_name
            	local ok, err = filter_obj:create(filter_name, capacity, probability)
            	debug("create-new", ok, err)
            	assert(ok == true)
            	-- assert(err == "Done", "err ~= 'Done'")
            
            	-- create a filter, the name is exist
            	local ok, err = filter_obj:create(filter_name, capacity, probability)
            	debug("create-exist", ok, err)
            	assert(ok == true)
            	assert(err == "Exists")
            
            	-- set a key, New
            	local ok, err = filter_obj:set(filter_name, 'my_key')
            	debug("set-new", ok, err)
            	assert(ok==true)
            	assert(err == "Yes")
            
            	-- set a key, Exist
            	local ok, err = filter_obj:set(filter_name, 'my_key')
            	debug("set-exist", ok, err)
            	assert(ok==true)
            	assert(err == "No")
            
            	-- check a key, Exist
            	local ok, err = filter_obj:check(filter_name, 'my_key')
            	debug("check-exist", ok, err)
            	assert(ok==true)
            	assert(err == "Yes")
            
            	-- check a key, Not Exist
            	local ok, err = filter_obj:check(filter_name, 'this_key_not_exist')
            	debug("check-not-exist", ok, err)
            	assert(ok==true)
            	assert(err == "No")
            
            	-- flush a filter
            	local ok, err = filter_obj:flush(filter_name)
            	debug("flush", ok, err)
            	assert(ok==true)
            	assert(err == "Done")
            
            	-- close a bloom filter
            	local ok, err = filter_obj:close(filter_name)
            	debug("close", ok, err)
            	assert(ok==true)
            	assert(err == "Done")
            
            	-- check a key, Exist
            	local ok, err = filter_obj:check(filter_name, 'my_key')
            	debug("check-exist", ok, err)
            	assert(ok==true)
            	assert(err == "Yes")
            
            
            	filter_obj:create("my_filter3", capacity, 0.001)
            	-- list all filter
            	local ok, filters = filter_obj:list(filter_name)
            	debug("list", ok, filters)
            	assert(ok==true)
            	assert(type(filters)=='table' and #filters==2)
            	for _,filter in ipairs(filters) do 
            		if filter.name == filter_name then 
            			assert(filter.size == 1)
            		end		
            	end
            	filter_obj:drop('my_filter3')
            
            	-- Set many items in a filter at once(bulk command)
            	local ok, status = filter_obj:sets(filter_name, {"a", "b", "c"})
            	assert(ok)
            	assert(type(status)=='table')
            	err = table.concat(status, ' ')
            	debug("sets", ok, err)
            	assert(err == "Yes Yes Yes")
            
            	local ok, status = filter_obj:sets(filter_name, {"a", "b", "d"})
            	assert(ok)
            	assert(type(status)=='table')
            	err = table.concat(status, ' ')
            	debug("sets", ok, err)
            	assert(err == "No No Yes")
            
            	-- Checks if a list of keys are in a filter
            	local ok, status = filter_obj:checks(filter_name, {"a", "x", "c", "d", "e"})
            	assert(ok)
            	assert(type(status)=='table')
            	err = table.concat(status, ' ')
            	debug("checks", ok, err)
            	assert(err == "Yes No Yes Yes No")
            
            
            	-- Gets info about a filter
            	local ok, info = filter_obj:info(filter_name)
            	debug("info", ok, info)
            	assert(ok)
            	assert(type(info)=='table')
            	assert(info.capacity == capacity)
            	assert(info.probability == probability)
            	assert(info.size == 5)
            
            	-- drop a filter
            	local ok, err = filter_obj:drop(filter_name)
            	debug("drop", ok, err)
            	assert(ok==true)
            	assert(err == "Done")
            
            
            	-- Test filter not exist
            	local ok, err = filter_obj:drop(filter_name)
            	debug("drop-not-exist", ok, err)
            	assert(ok==false)
            	assert(err == "Filter does not exist")
            
            
            	-- create, close and clear a bloom filter, my_filter2 is still in disk.
            	local ok, err = filter_obj:create("my_filter2", 10000*20, 0.001)
            	debug("create-new", ok, err)
            	assert(ok == true)
            	assert(err == "Done", "err ~= 'Done'")
            	local ok, err = filter_obj:close("my_filter2")
            	debug("close", ok, err)
            	assert(ok==true)
            	assert(err == "Done")
            	local ok, err = filter_obj:clear("my_filter2")
            	debug("clear", ok, err)
            	assert(ok==true)
            	assert(err == "Done")
            
            	ngx.say("--------- all test ok --------------")
            end
            local ok, err = pcall(test_main)
            if not ok then
            	filter_obj:close("my_filter")
            	filter_obj:close("my_filter2")
            	filter_obj:close("my_filter3")
            	assert(ok, err)
            end
            ';
        }
    }

Methods

Back to TOC new

syntax: filter_obj = bloomd:new(host, port, timeout)

Create a new bloom filter object.

create

syntax: ok, err = filter_obj:create(filter_name, capacity, prob, in_memory)

Create a new filter

list

syntax: ok, filters = filter_obj:list(filter_prefix)

List all filters or those matching a prefix.<br/>

for _,filter in ipairs(filters) do 
	ngx.say(filter.name, ",", filter.probability, ",", 
	        filter.storage, ",", filter.capacity, ",",filter.size)
end

drop

syntax: ok, err = filter_obj:drop(filter_name)

Drop a filter (Deletes from disk). On Success Returns ok:true, err:'Done'

close

syntax: ok, err = filter_obj:close(filter_name)

Close a filter (Unmaps from memory, but still accessible). On Success Returns ok:true, err:'Done'

clear

syntax: ok, err = filter_obj:clear(filter_name)

Clear a filter from the lists (Removes memory, left on disk)

check

syntax: ok, status = filter_obj:check(filter_name, key)

Check if a key is in a filter.

checks

syntax: ok, status = filter_obj:checks(filter_name, keys)

Check if a list of keys are in a filter

set

syntax: ok, status = filter_obj:set(filter_name, key)

Set an item in a filter

sets

syntax: ok, status = filter_obj:sets(filter_name, keys)

Set many items in a filter at once

info

syntax: ok, info = filter_obj:info(filter_name)

Get info about a filter

flush

syntax: ok, err = filter_obj:flush(filter_name)

Flush a specified filter.

Back to TOC

Installation

You need to compile ngx_lua with your Nginx.

You need to configure the lua_package_path directive to add the path of your lua-resty-bloomd source tree to ngx_lua's Lua module search path, as in

# nginx.conf
http {
    lua_package_path "/path/to/lua-resty-bloomd/lib/?.lua;;";
    ...
}

and then load the library in Lua:

bloomd = require "resty.bloomd"

Back to TOC

Authors

Xiaojie Liu jie123108@163.com

Back to TOC

Copyright and License

This module is licensed under the BSD license.

Copyright (C) 2015, by Xiaojie Liu jie123108@163.com

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Back to TOC