nodejs client finish binary search
This commit is contained in:
parent
401e5bc795
commit
63cd3fa085
|
|
@ -1,55 +1,87 @@
|
||||||
/**
|
/**
|
||||||
* ip2region client for nodejs
|
* ip2region client for nodejs
|
||||||
*
|
*
|
||||||
* project: https://github.com/lionsoul2016/ip2region
|
* project: https://github.com/lionsoul2014/ip2region
|
||||||
*
|
*
|
||||||
* @author dongyado<dongyado@gmail.com>
|
* @author dongyado<dongyado@gmail.com>
|
||||||
* */
|
* */
|
||||||
|
|
||||||
|
|
||||||
function Ip2region(db_path)
|
|
||||||
{
|
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
|
||||||
var ipbase = [16777216, 65536, 256, 1]; // for ip2long
|
var ipbase = [16777216, 65536, 256, 1]; // for ip2long
|
||||||
var db_file_path = null;
|
var ip2region = {};
|
||||||
var db_fd = null;
|
ip2region.db_file_path = null;
|
||||||
|
ip2region.db_fd = null;
|
||||||
// db file check
|
|
||||||
if (typeof(db_path) == "undefined" || fs.exists(db_path) ) {
|
|
||||||
throw("[ip2region] db file not exists : " + db_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
db_file_path = db_path;
|
|
||||||
|
|
||||||
try {
|
|
||||||
db_fd = fs.openSync(db_file_path, 'r');
|
|
||||||
} catch(e) {
|
|
||||||
throw("[ip2region] Can not open ip2region.db file , path : " + db_file_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
var totalBlocks = 0;
|
var totalBlocks = 0;
|
||||||
var firstIndexPtr = 0;
|
var firstIndexPtr = 0;
|
||||||
var lastIndexPtr = 0;
|
var lastIndexPtr = 0;
|
||||||
var superBlock = new Buffer(8);
|
var superBlock = new Buffer(8);
|
||||||
|
|
||||||
this.binarySearch = function(ip)
|
var indexBlockLength = 12;
|
||||||
{
|
var totalHeaderLength = 4096;
|
||||||
if (typeof(ip) == 'string') ip = ip2long(ip);
|
|
||||||
|
|
||||||
// init basic search environment
|
|
||||||
if (totalBlocks == 0) {
|
/**
|
||||||
fs.readSync(ip2r.db_fd, superBlock, 0, 8, 0);
|
* binary search
|
||||||
firstIndexPtr = getLong(superBlock, 0);
|
* */
|
||||||
lastIndexPtr = getLong(superBlock, 4);
|
ip2region.binarySearch = function(ip)
|
||||||
}
|
{
|
||||||
|
if( typeof(ip) == 'string' )
|
||||||
|
ip = ip2long(ip);
|
||||||
|
|
||||||
// search
|
// search
|
||||||
|
var low = 0;
|
||||||
|
var mid = 0;
|
||||||
|
var high = totalBlocks;
|
||||||
|
var dataPos = 0;
|
||||||
|
var pos = 0;
|
||||||
|
var sip = 0;
|
||||||
|
var eip = 0;
|
||||||
|
var indexBuffer = new Buffer(12);
|
||||||
|
|
||||||
return ip2long(ip);
|
// binary search
|
||||||
|
while( low <= high ) {
|
||||||
|
mid = ((low + high) >> 1);
|
||||||
|
pos = firstIndexPtr + mid * indexBlockLength;
|
||||||
|
fs.readSync(this.db_fd, indexBuffer, 0, indexBlockLength, pos);
|
||||||
|
sip = getLong(indexBuffer, 0);
|
||||||
|
|
||||||
|
//console.log( ' sip : ' + sip + ' eip : ' + eip );
|
||||||
|
if ( ip < sip) {
|
||||||
|
high = mid - 1;
|
||||||
|
} else {
|
||||||
|
eip = getLong(indexBuffer, 4);
|
||||||
|
if ( ip > eip ) {
|
||||||
|
low = mid + 1;
|
||||||
|
} else {
|
||||||
|
dataPos = getLong(indexBuffer, 8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read data
|
||||||
|
if (dataPos == 0) return null;
|
||||||
|
var dataLen = ((dataPos >> 24) & 0xFF);
|
||||||
|
var dataPos = (dataPos & 0x00FFFFFF);
|
||||||
|
var dataBuffer = new Buffer(dataLen);
|
||||||
|
|
||||||
|
fs.readSync(this.db_fd, dataBuffer, 0, dataLen, dataPos);
|
||||||
|
|
||||||
|
var city_id = getLong(dataBuffer, 0);
|
||||||
|
var data = dataBuffer.toString('utf8', 4, dataLen);
|
||||||
|
|
||||||
|
//console.log(city_id);
|
||||||
|
//console.log(data);
|
||||||
|
|
||||||
|
return { city: city_id, region: data };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.btreeSearch = function(ip)
|
/**
|
||||||
|
* btree search
|
||||||
|
* */
|
||||||
|
ip2region.btreeSearch = function(ip)
|
||||||
{
|
{
|
||||||
return ip2long(ip);
|
return ip2long(ip);
|
||||||
}
|
}
|
||||||
|
|
@ -74,13 +106,53 @@ function Ip2region(db_path)
|
||||||
* */
|
* */
|
||||||
function getLong(buffer, offset)
|
function getLong(buffer, offset)
|
||||||
{
|
{
|
||||||
return (
|
var val = (
|
||||||
(buffer[offset] & 0x000000FF) |
|
(buffer[offset] & 0x000000FF) |
|
||||||
((buffer[offset + 1] << 8) & 0x0000FF00) |
|
((buffer[offset + 1] << 8) & 0x0000FF00) |
|
||||||
((buffer[offset + 2] << 16) & 0x00FF0000) |
|
((buffer[offset + 2] << 16) & 0x00FF0000) |
|
||||||
((buffer[offset + 3] << 24) & 0xFF000000)
|
((buffer[offset + 3] << 24) & 0xFF000000)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// convert to unsigned int
|
||||||
|
if (val < 0) {
|
||||||
|
val = val >>> 0;
|
||||||
}
|
}
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Ip2region;
|
|
||||||
|
// api for create
|
||||||
|
exports.create = function(db_path) {
|
||||||
|
|
||||||
|
// db file check
|
||||||
|
if (typeof(db_path) == "undefined" || fs.exists(db_path) ) {
|
||||||
|
throw("[ip2region] db file not exists : " + db_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
ip2region.db_file_path = db_path;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ip2region.db_fd = fs.openSync(ip2region.db_file_path, 'r');
|
||||||
|
} catch(e) {
|
||||||
|
throw("[ip2region] Can not open ip2region.db file , path : "
|
||||||
|
+ ip2region.db_file_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// init basic search environment
|
||||||
|
if (totalBlocks == 0) {
|
||||||
|
fs.readSync(ip2region.db_fd, superBlock, 0, 8, 0);
|
||||||
|
firstIndexPtr = getLong(superBlock, 0);
|
||||||
|
lastIndexPtr = getLong(superBlock, 4);
|
||||||
|
totalBlocks = (lastIndexPtr - firstIndexPtr)
|
||||||
|
/ indexBlockLength + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ip2region;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// api for destroy
|
||||||
|
exports.destroy = function(ip2rObj){
|
||||||
|
ip2rObj.db_file_path = null;
|
||||||
|
fs.closeSync(ip2rObj.db_fd);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,13 @@
|
||||||
* */
|
* */
|
||||||
|
|
||||||
var Ip2region = require('./ip2region');
|
var Ip2region = require('./ip2region');
|
||||||
var ip2region = new Ip2region('../../data/ip2region.db');
|
//var ip2region = new Ip2region();
|
||||||
|
|
||||||
console.log(ip2region.binarySearch("255.255.255.255"));
|
// 1. create a ip2region object
|
||||||
|
var ipObj = Ip2region.create('../../data/ip2region.db');
|
||||||
|
|
||||||
|
// 2. use
|
||||||
|
console.log(ipObj.binarySearch("120.24.78.68"));
|
||||||
|
|
||||||
|
// 3. destroy
|
||||||
|
Ip2region.destroy(ipObj);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue