Lua binding completed(tested)

This commit is contained in:
lionsoul 2018-10-03 20:05:14 +08:00
parent 92684b1183
commit 3d69968290
5 changed files with 183 additions and 40 deletions

View File

@ -18,7 +18,7 @@ ip2region - 最自由的ip地址查询库ip到地区的映射库提供Bina
### 4. 多查询客户端的支持0.0x毫秒级别的查询
已经集成的客户端有java, C#, php, c, pythonnodejsphp扩展(支持linux, php5, php7版本已支持)golang
已经集成的客户端有java、C#、php、c、python、nodejs、php扩展(php5和php7)、golang、rust、lua
提供了两种查询算法,响应时间如下:
客户端/binary算法/b-tree算法/Memory算法
@ -27,6 +27,7 @@ ip2region - 最自由的ip地址查询库ip到地区的映射库提供Bina
php/0.x毫秒/0.1x毫秒/0.1x毫秒
c/0.0x毫秒/0.0x毫秒/0.00x毫秒(b-tree算法基本稳定在0.02x毫秒级别)
python/0.x毫秒/0.1x毫秒/未知
lua/0.x毫秒/0.x毫秒/0.x毫秒
任何客户端b-tree都比binary算法快当然Memory算法固然是最快的
@ -70,6 +71,12 @@ python:
python binding/python/testSearcher.py ./data/ip2region.db
```
lua:
```shell
cd binding/lua/
lua testSearcher.lua ../../data/ip2region.db
```
均会看到如下界面:
```shell
initializing B-tree ...

View File

@ -1,5 +1,5 @@
--[[
Ip2region lua binding
_M lua binding
@author chenxin<chenxin619315@gmail.com>
@date 2018/10/02
@ -7,23 +7,22 @@ Ip2region lua binding
require("bit32");
local Ip2region = {
local INDEX_BLOCK_LENGTH = 12;
local TOTAL_HEADER_LENGTH = 8192;
local _M = {
dbFile = "",
dbFileHandler = "",
dbFileHandler = nil,
dbBinStr = "",
HeaderSip = "",
HeaderPtr = "",
headerLen = "",
HeaderSip = nil,
HeaderPtr = nil,
headerLen = 0,
firstIndexPtr = 0,
lastIndexPtr = 0,
totalBlocks = 0
};
-- common constants
local INDEX_BLOCK_LENGTH = 12;
local TOTAL_HEADER_LENGTH = 8192;
function Ip2region:new(obj)
_G["Ip2region"] = _M;
function _M:new(obj)
obj = obj or {};
setmetatable(obj, {__index = self});
return obj;
@ -58,27 +57,37 @@ internal function to convert the string ip to a long value
@param ip
@return Integer
]]--
function ip2long(ip)
function _M:ip2long(ip)
local ini = 1;
local iip = 0;
local off = 24;
local int = 0;
while true do
local pos = string.find(ip, '.', ini, true);
if ( not pos or off <= 0 ) then
if ( not pos ) then
break;
end
int = tonumber(string.sub(ip, ini, pos - 1));
iip = bit32.bor(iip, bit32.lshift(int, off));
local sub = string.sub(ip, ini, pos - 1);
if ( string.len(sub) < 1 ) then
return nil;
end
iip = bit32.bor(iip, bit32.lshift(tonumber(sub), off));
ini = pos + 1;
off = off - 8;
end
int = tonumber(string.sub(ip, ini));
iip = bit32.bor(iip, bit32.lshift(int, off));
-- check if it is a valid ip address
if ( off ~= 0 or ini > string.len(ip) ) then
return nil;
end
return iip;
local sub = string.sub(ip, ini);
if ( string.len(sub) < 1 ) then
return nil;
end
return bit32.bor(iip, bit32.lshift(tonumber(sub), off));
end
@ -108,7 +117,15 @@ then search the memory only and this will a lot faster than disk base search
@param ip
@return table or nil for failed
]]--
function Ip2region:memorySearch(ip)
function _M:memorySearch(ip)
-- string ip conversion
if ( type(ip) == "string" ) then
ip = self:ip2long(ip);
if ( ip == nil ) then
return nil;
end
end;
-- check and load the binary string for the first time
if ( self.dbBinStr == "" ) then
self.dbBinStr = get_file_contents(self.dbFile);
@ -121,9 +138,6 @@ function Ip2region:memorySearch(ip)
self.totalBlocks = (self.lastIndexPtr - self.firstIndexPtr)/INDEX_BLOCK_LENGTH + 1;
end
if ( type(ip) == "string" ) then
ip = ip2long(ip);
end;
-- binary search to define the data
local l = 0;
@ -168,15 +182,18 @@ or long ip numeric with binary search algorithm
@param ip
@return table or nil for failed
]]--
function Ip2region:binarySearch(ip)
function _M:binarySearch(ip)
-- check and conver the ip address
if ( type(ip) == "string" ) then
ip = ip2long(ip);
ip = self:ip2long(ip);
if ( ip == nil ) then
return nil;
end
end
if ( self.totalBlocks == 0 ) then
-- check and open the original db file
if ( self.dbFileHandler == "" ) then
if ( self.dbFileHandler == nil ) then
self.dbFileHandler = io.open(self.dbFile, "r");
if ( not self.dbFileHandler ) then
return nil;
@ -239,15 +256,19 @@ get the data block associated with the specified ip with b-tree search algorithm
@param ip
@return table or nil for failed
]]--
function Ip2region:btreeSearch(ip)
if ( type(ip) ) then
ip = ip2long(ip);
function _M:btreeSearch(ip)
-- string ip to integer conversion
if ( type(ip) == "string" ) then
ip = self:ip2long(ip);
if ( ip == nil ) then
return nil;
end
end
-- check and load the header
if ( self.HeaderSip == "" ) then
if ( self.headerLen == 0 ) then
-- check and open the original db file
if ( self.dbFileHandler == "" ) then
if ( self.dbFileHandler == nil ) then
self.dbFileHandler = io.open(self.dbFile, 'r');
if ( not self.dbFileHandler ) then
return nil;
@ -277,6 +298,7 @@ function Ip2region:btreeSearch(ip)
self.headerLen = idx;
end
-- 1. define the index block with the binary search
local l = 0;
local h = self.headerLen;
@ -368,4 +390,4 @@ function Ip2region:btreeSearch(ip)
end
return Ip2region;
return _M;

49
binding/lua/README.md Normal file
View File

@ -0,0 +1,49 @@
# Lua ip2region binding
### 一,如何测试
* 1, cd到ip2region/binding/lua/根目录
* 2, 运行testSearcher测试程序
```shell
lua testSearcher.lua ../../data/ip2region.db
```
* 3, 输入ip地址开始测试即可
```shell
initializing btree
+----------------------------------+
| ip2region test script |
| Author: chenxin619315@gmail.com |
| Type 'quit' to exit program |
+----------------------------------+
ip2region>> 1.2.3.4
0|美国|0|华盛顿|0|0 in 8.001000 millseconds
ip2region>> 101.233.153.103
2163|中国|0|广东省|深圳市|鹏博士 in 0.176000 millseconds
ip2region>>
```
### 二,如何使用
* 1, 将Ip2region.lua拷贝到你的package.path下
* 2, 通过如下流程在你的lua程序中使用
```lua
-- 包含模块
require "Ip2region";
-- 创建查询对象
-- dbFile表示ip2region.db数据库文件的地址
local searcher = Ip2region:new({dbFile: "ip2region.db file path"});
local data;
-- 查询,备注请使用“:”调用方法,不要使用“.”
-- 1binary查询
data = searcher:binarySearch("101.233.153.103");
-- 2btree查询
data = searcher:btreeSearch("101.233.153.103");
-- 3memory查询
data = searcher:memorySearch("101.233.153.103");
-- 返回结果如下
print("city_id=", data.city_id, "region=", data.region);
```

View File

@ -1,9 +1,74 @@
-- ip2region test lua script
local cjson = require "cjson";
local Ip2region = require "Ip2region";
--[[
ip2region lua client test script
@author chenxin<chenxin619315@gmail.com>
]]--
-- check the command line arguments
if ( not arg[1] ) then
print([[
Usage: lua testSearcher.lua [ip2region db file] [algorithm]
+-Optional Algorithm: binary, b-tree, memory]]);
os.exit();
end
local Ip2region = require "Ip2region";
-- local cjson = require "cjson";
-- local socket = require "socket";
-- check and parse the dbFile and the method algorithm
local searcher = Ip2region:new({dbFile = arg[1]});
local algorithm = "btree";
if ( arg[2] ~= nil ) then
local arg_2 = string.lower(arg[2]);
if ( arg_2 ~= "binary" and arg_2 ~= "memory" ) then
algorithm = "binary";
elseif ( arg_2 == "memory" ) then
algorithm = "memory";
end
end
local searcher = Ip2region:new({dbFile = "../../data/ip2region.db"});
-- local data = searcher:memorySearch("120.79.17.142");
-- local data = searcher:binarySearch("120.79.17.142");
local data = searcher:btreeSearch("120.79.17.142");
print(cjson.encode(data));
-- local data = searcher:btreeSearch("120.79.17.142");
print("initializing " .. algorithm ..[[
+----------------------------------+
| ip2region test script |
| Author: chenxin619315@gmail.com |
| Type 'quit' to exit program |
+----------------------------------+]]
);
while ( true ) do
io.write("ip2region>> ");
io.input(io.stdin);
local line = io.read();
if ( line == nil ) then
-- do nothing
break;
elseif ( line == "quit" ) then
break;
elseif ( searcher:ip2long(line) == nil ) then
print("Invalid ip address=", line);
else
local data;
local s_time = os.clock();
if ( algorithm == "btree" ) then
data = searcher:btreeSearch(line);
elseif ( algorithm == "binary" ) then
data = searcher:binarySearch(line);
elseif ( algorithm == "memory" ) then
data = searcher:memorySearch(line);
end
local cost_time = (os.clock() - s_time) * 1000; -- to millseconds
if ( data == nil ) then
io.write("Failed for ip=", line, " is it a valid ip address ?");
else
io.write(string.format("%u|%s in %5f millseconds\n", data.city_id, data.region, cost_time));
end
end
end

View File

@ -8,7 +8,7 @@
if ( $argc < 2 ) {
$usage = <<<EOF
Usage: php Test.php [ip2region db file] [alrogrithm]
+-Algorithm: binary or b-tree\n
+-Optional Algorithm: binary, b-tree, memory\n
EOF;
exit($usage);
}