Is a client library based on ngx_lua to interface with bloomd servers. A lua bloom filter library
Lua
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
lib/resty
t
README.md

README.md

Name

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

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.

  • IN: the host is the bloomd's host, default is '127.0.0.1'.
  • IN: the port is the bloomd's port, default is 8673.
  • IN: the timeout is the timeout time in ms, default is 5000ms.

create

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

Create a new filter

  • IN: the filter_name is the name of the filter, and can contain the characters a-z, A-Z, 0-9, ., _.
  • IN: the capacity is provided the filter will be created to store at least that many items in the initial filter. default is 0.001.
  • IN: the prob is maximum false positive probability provided.
  • IN: the 'in_memory' is to force the filter not to be persisted to disk.

list

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

List all filters or those matching a prefix.

  • OUT: the ok is list status.
  • OUT: the filters is a Lua table holding all the matched filter.
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.

  • IN: the status is 'Yes'(key exists in filter) or 'No'(if key does not exists in filter).

checks

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

Check if a list of keys are in a filter

  • IN: the keys is a table that contains some keys.
  • OUT: the status is a table that contains each key's status('Yes' or 'No').

set

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

Set an item in a filter

  • OUT: the status is 'Yes'(key is successfully set to the filter) or 'No'(key exists in the filter).

sets

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

Set many items in a filter at once

  • IN: the keys is a table that contains some keys.
  • OUT: the status is a table that contains each key's set status('Yes' or 'No').

info

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

Get info about a filter

  • OUT: the info is a table like {in_memory:1,set_misses:3,checks:8,capacity:100001, probability:0.001,page_outs:1,size:5,check_hits:5, storage:240141,page_ins:1,set_hits:5,check_misses:3,sets:8}.

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:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

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