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

@ -12,7 +12,8 @@ import java.io.RandomAccessFile;
public class DbSearcher public class DbSearcher
{ {
public static final int BTREE_ALGORITHM = 1; public static final int BTREE_ALGORITHM = 1;
public static final int BIN_ALGORITHM = 2; public static final int BINARY_ALGORITHM = 2;
public static final int MEMORY_ALGORITYM = 3;
/** /**
* db config * db config
@ -38,6 +39,12 @@ public class DbSearcher
private long lastIndexPtr = 0; private long lastIndexPtr = 0;
private int totalIndexBlocks = 0; private int totalIndexBlocks = 0;
/**
* for memory mode
* the original db binary string
*/
private byte[] dbBinStr = null;
/** /**
* construct class * construct class
* *
@ -51,6 +58,72 @@ public class DbSearcher
raf = new RandomAccessFile(dbFile, "r"); 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 * get by index ptr
* *
@ -308,6 +381,8 @@ public class DbSearcher
{ {
HeaderSip = null; //let gc do its work HeaderSip = null; //let gc do its work
HeaderPtr = null; HeaderPtr = null;
dbBinStr = null;
raf.close(); raf.close();
} }
} }

View File

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