add DbSearcher#memorySearch interface

This commit is contained in:
lionsoul 2016-06-30 20:19:17 +08:00
parent 861b8b4622
commit a5df8ff87c
2 changed files with 146 additions and 32 deletions

View File

@ -11,8 +11,9 @@ import java.io.RandomAccessFile;
*/
public class DbSearcher
{
public static final int BTREE_ALGORITHM = 1;
public static final int BIN_ALGORITHM = 2;
public static final int BTREE_ALGORITHM = 1;
public static final int BINARY_ALGORITHM = 2;
public static final int MEMORY_ALGORITYM = 3;
/**
* db config
@ -38,12 +39,18 @@ public class DbSearcher
private long lastIndexPtr = 0;
private int totalIndexBlocks = 0;
/**
* for memory mode
* the original db binary string
*/
private byte[] dbBinStr = null;
/**
* construct class
*
* @param bdConfig
* @param dbFile
* @throws FileNotFoundException
* @param bdConfig
* @param dbFile
* @throws FileNotFoundException
*/
public DbSearcher( DbConfig dbConfig, String dbFile ) throws FileNotFoundException
{
@ -51,11 +58,77 @@ public class DbSearcher
raf = new RandomAccessFile(dbFile, "r");
}
/**
* get the region with a int ip address with memory binary search algorithm
*
* @param ip
* @throws IOException
*/
public DataBlock memorySearch(long ip) throws IOException
{
int blen = IndexBlock.getIndexBlockLength();
if ( dbBinStr == null ) {
dbBinStr = new byte[(int)raf.length()];
raf.seek(0L);
raf.readFully(dbBinStr, 0, dbBinStr.length);
//initialize the global vars
firstIndexPtr = Util.getIntLong(dbBinStr, 0);
lastIndexPtr = Util.getIntLong(dbBinStr, 4);
totalIndexBlocks = (int)((lastIndexPtr - firstIndexPtr)/blen) + 1;
}
//search the index blocks to define the data
int l = 0, h = totalIndexBlocks;
long sip, eip, dataptr = 0;
while ( l <= h ) {
int m = (l + h) >> 1;
int p = (int)(firstIndexPtr + m * blen);
sip = Util.getIntLong(dbBinStr, p);
if ( ip < sip ) {
h = m - 1;
} else {
eip = Util.getIntLong(dbBinStr, p + 4);
if ( ip > eip ) {
l = m + 1;
} else {
dataptr = Util.getIntLong(dbBinStr, p + 8);
break;
}
}
}
//not matched
if ( dataptr == 0 ) return null;
//get the data
int dataLen = (int)((dataptr >> 24) & 0xFF);
int dataPtr = (int)((dataptr & 0x00FFFFFF));
int city_id = (int)Util.getIntLong(dbBinStr, dataPtr);
String region = new String(dbBinStr, dataPtr + 4, dataLen - 4, "UTF-8");
return new DataBlock(city_id, region, dataPtr);
}
/**
* get the region throught the ip address with memory binary search algorithm
*
* @param ip
* @return DataBlock
* @throws IOException
*/
public DataBlock memorySearch( String ip ) throws IOException
{
return memorySearch(Util.ip2long(ip));
}
/**
* get by index ptr
*
* @param indexPtr
* @throws IOException
* @param indexPtr
* @throws IOException
*/
public DataBlock getByIndexPtr( long ptr ) throws IOException
{
@ -82,7 +155,7 @@ public class DbSearcher
/**
* get the region with a int ip address with b-tree algorithm
*
* @param ip
* @param ip
* @throws IOException
*/
public DataBlock btreeSearch( long ip ) throws IOException
@ -210,9 +283,9 @@ public class DbSearcher
/**
* get the region throught the ip address with b-tree search algorithm
*
* @param ip
* @return DataBlock
* @throws IOException
* @param ip
* @return DataBlock
* @throws IOException
*/
public DataBlock btreeSearch( String ip ) throws IOException
{
@ -222,7 +295,7 @@ public class DbSearcher
/**
* get the region with a int ip address with binary search algorithm
*
* @param ip
* @param ip
* @throws IOException
*/
public DataBlock binarySearch( long ip ) throws IOException
@ -280,9 +353,9 @@ public class DbSearcher
/**
* get the region throught the ip address with binary search algorithm
*
* @param ip
* @return DataBlock
* @throws IOException
* @param ip
* @return DataBlock
* @throws IOException
*/
public DataBlock binarySearch( String ip ) throws IOException
{
@ -292,7 +365,7 @@ public class DbSearcher
/**
* get the db config
*
* @return DbConfig
* @return DbConfig
*/
public DbConfig getDbConfig()
{
@ -308,6 +381,8 @@ public class DbSearcher
{
HeaderSip = null; //let gc do its work
HeaderPtr = null;
dbBinStr = null;
raf.close();
}
}

View File

@ -4,6 +4,8 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
@ -25,23 +27,45 @@ public class TestSearcher
return;
}
int algorithm = DbSearcher.BTREE_ALGORITHM;
File file = new File(argv[0]);
if ( file.exists() == false ) {
System.out.println("Error: Invalid ip2region.db file");
return;
}
int algorithm = DbSearcher.BTREE_ALGORITHM;
String algoName = "B-tree";
if ( argv.length > 1 ) {
if ( argv[1].equalsIgnoreCase("binary")) algorithm = DbSearcher.BIN_ALGORITHM;
if ( argv[1].equalsIgnoreCase("binary")) {
algoName = "Binary";
algorithm = DbSearcher.BINARY_ALGORITHM;
} else if ( argv[1].equalsIgnoreCase("memory") ) {
algoName = "Memory";
algorithm = DbSearcher.MEMORY_ALGORITYM;
}
}
try {
System.out.println("initializing "+((algorithm==2)?"Binary":"B-tree")+" ... ");
System.out.println("initializing "+algoName+" ... ");
DbConfig config = new DbConfig();
DbSearcher seacher = new DbSearcher(config, argv[0]);
DbSearcher searcher = new DbSearcher(config, argv[0]);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
//define the method
Method method = null;
switch ( algorithm )
{
case DbSearcher.BTREE_ALGORITHM:
method = searcher.getClass().getMethod("btreeSearch", String.class);
break;
case DbSearcher.BINARY_ALGORITHM:
method = searcher.getClass().getMethod("binarySearch", String.class);
break;
case DbSearcher.MEMORY_ALGORITYM:
method = searcher.getClass().getMethod("memorySearch", String.class);
break;
}
System.out.println("+----------------------------------+");
System.out.println("| ip2region test shell |");
System.out.println("| Author: chenxin619315@gmail.com |");
@ -62,13 +86,13 @@ public class TestSearcher
}
sTime = System.nanoTime();
dataBlock = algorithm==2 ? seacher.binarySearch(line) : seacher.btreeSearch(line);
dataBlock = (DataBlock) method.invoke(searcher, line);
cTime = (System.nanoTime() - sTime) / 1000000;
System.out.printf("%s in %.5f millseconds\n", dataBlock, cTime);
}
reader.close();
seacher.close();
searcher.close();
System.out.println("+--Bye");
} catch (IOException e) {
// TODO Auto-generated catch block
@ -76,6 +100,21 @@ public class TestSearcher
} catch (DbMakerConfigException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}