ip2region service with thread safe and auto ip version detect supports
This commit is contained in:
parent
efbbb576ee
commit
b5ae94b36d
|
|
@ -9,6 +9,7 @@ import java.io.IOException;
|
|||
import org.lionsoul.ip2region.xdb.InetAddressException;
|
||||
import org.lionsoul.ip2region.xdb.Searcher;
|
||||
import org.lionsoul.ip2region.xdb.Util;
|
||||
import org.lionsoul.ip2region.xdb.XdbException;
|
||||
|
||||
/**
|
||||
* ip2region searcher manager service to provider:
|
||||
|
|
@ -20,15 +21,66 @@ import org.lionsoul.ip2region.xdb.Util;
|
|||
*/
|
||||
public class Ip2Region {
|
||||
|
||||
/* v4 pool */
|
||||
/* v4 pool for cache policy vIndex or NoCache */
|
||||
private final SearcherPool v4Pool;
|
||||
|
||||
/* v6 pool */
|
||||
/* v4 xdb searcher for cache policy cBuffer */
|
||||
private final Searcher v4InMemSearcher;
|
||||
|
||||
/* v6 pool for cache policy vIndex or NoCache*/
|
||||
private final SearcherPool v6Pool;
|
||||
|
||||
/* v6 xdb searcher for cache policy cBuffer */
|
||||
private final Searcher v6InMemSearcher;
|
||||
|
||||
/**
|
||||
* init the ip2reigon with two xdb file path and default cachePolicy vIndex.
|
||||
* set it to null to disabled the search for specified version
|
||||
*
|
||||
* @param v4XdbPath
|
||||
* @param v6XdbPath
|
||||
* @throws XdbException
|
||||
* @throws IOException
|
||||
*/
|
||||
public Ip2Region(String v4XdbPath, String v6XdbPath) throws IOException, XdbException {
|
||||
this(
|
||||
v4XdbPath == null ? null : Config.custom().setXdbPath(v4XdbPath).asV4(),
|
||||
v6XdbPath == null ? null : Config.custom().setXdbPath(v6XdbPath).asV6()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* init the ip2region with specified config.
|
||||
* set it to null for disabled the search for specified version
|
||||
*
|
||||
* @param v4Config
|
||||
* @param v6Config
|
||||
* @throws IOException
|
||||
*/
|
||||
public Ip2Region(Config v4Config, Config v6Config) throws IOException {
|
||||
this.v4Pool = new SearcherPool(v4Config);
|
||||
this.v6Pool = new SearcherPool(v6Config);
|
||||
if (v4Config == null) {
|
||||
// @Note: with IPv4 disabled ?
|
||||
this.v4InMemSearcher = null;
|
||||
this.v4Pool = null;
|
||||
} else if (v4Config.cachePolicy == Config.BufferCache) {
|
||||
this.v4InMemSearcher = Searcher.newWithBuffer(v4Config.ipVersion, v4Config.cBuffer);
|
||||
this.v4Pool = null;
|
||||
} else {
|
||||
this.v4InMemSearcher = null;
|
||||
this.v4Pool = new SearcherPool(v4Config);
|
||||
}
|
||||
|
||||
if (v6Config == null) {
|
||||
// @Note: with IPv6 disabled ?
|
||||
this.v6InMemSearcher = null;
|
||||
this.v6Pool = null;
|
||||
} else if (v6Config.cachePolicy == Config.BufferCache) {
|
||||
this.v6InMemSearcher = Searcher.newWithBuffer(v6Config.ipVersion, v6Config.cBuffer);
|
||||
this.v6Pool = null;
|
||||
} else {
|
||||
this.v6InMemSearcher = null;
|
||||
this.v6Pool = new SearcherPool(v6Config);
|
||||
}
|
||||
}
|
||||
|
||||
public String search(String ipString) throws InetAddressException, IOException, InterruptedException {
|
||||
|
|
@ -36,24 +88,62 @@ public class Ip2Region {
|
|||
}
|
||||
|
||||
public String search(byte[] ipBytes) throws InetAddressException, IOException, InterruptedException {
|
||||
// 1, define the pool with the input ip
|
||||
final SearcherPool pool;
|
||||
if (ipBytes.length == 4) {
|
||||
pool = v4Pool;
|
||||
return v4Search(ipBytes);
|
||||
} else if (ipBytes.length == 16) {
|
||||
pool = v6Pool;
|
||||
return v6Search(ipBytes);
|
||||
} else {
|
||||
throw new InetAddressException("invalid byte ip address with length=" + ipBytes.length);
|
||||
}
|
||||
}
|
||||
|
||||
// 2, get a searcher from the pool
|
||||
final Searcher searcher = pool.borrowSearcher();
|
||||
protected String v4Search(final byte[] ipBytes) throws IOException, InetAddressException, InterruptedException {
|
||||
if (v4InMemSearcher != null) {
|
||||
return v4InMemSearcher.search(ipBytes);
|
||||
}
|
||||
|
||||
// IPv4 search is disabled
|
||||
if (v4Pool == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Searcher searcher = v4Pool.borrowSearcher();
|
||||
try {
|
||||
// 3, do the search
|
||||
return searcher.search(ipBytes);
|
||||
} finally {
|
||||
pool.returnSearcher(searcher);
|
||||
v4Pool.returnSearcher(searcher);
|
||||
}
|
||||
}
|
||||
|
||||
protected String v6Search(final byte[] ipBytes) throws IOException, InetAddressException, InterruptedException {
|
||||
if (v6InMemSearcher != null) {
|
||||
return v6InMemSearcher.search(ipBytes);
|
||||
}
|
||||
|
||||
// IPv6 search is disabled
|
||||
if (v6Pool == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Searcher searcher = v6Pool.borrowSearcher();
|
||||
try {
|
||||
return searcher.search(ipBytes);
|
||||
} finally {
|
||||
v6Pool.returnSearcher(searcher);
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws InterruptedException {
|
||||
close(10000);
|
||||
}
|
||||
|
||||
public void close(long timeoutMillis) throws InterruptedException {
|
||||
if (v4Pool != null) {
|
||||
v4Pool.close(timeoutMillis);
|
||||
}
|
||||
|
||||
if (v6Pool != null) {
|
||||
v6Pool.close(timeoutMillis);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -94,10 +94,14 @@ public class SearcherPool {
|
|||
|
||||
// close the searcher pool
|
||||
public void close() throws InterruptedException {
|
||||
close(10000);
|
||||
}
|
||||
|
||||
public void close(long timeoutMillis) throws InterruptedException {
|
||||
lock.lock();
|
||||
try {
|
||||
while (loanCount > 0) {
|
||||
fullCondition.wait();
|
||||
fullCondition.wait(timeoutMillis);
|
||||
}
|
||||
|
||||
final Iterator<Searcher> it = pool.iterator();
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ public class ConfigTest {
|
|||
|
||||
private static final Log log = Log.getLogger(ConfigTest.class).setLevel(Log.DEBUG);
|
||||
|
||||
public String getDataPath(String xdbFile) {
|
||||
final CodeSource cs = this.getClass().getProtectionDomain().getCodeSource();
|
||||
public static final String getDataPath(String xdbFile) {
|
||||
final CodeSource cs = ConfigTest.class.getProtectionDomain().getCodeSource();
|
||||
if (cs != null) {
|
||||
// log.debugf("code path: %s", cs.getLocation().getPath().concat("../../../../data/"));
|
||||
return cs.getLocation().getPath().concat("../../../../data/").concat(xdbFile);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
package org.lionsoul.ip2region;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.lionsoul.ip2region.xdb.InetAddressException;
|
||||
import org.lionsoul.ip2region.xdb.Log;
|
||||
import org.lionsoul.ip2region.xdb.Util;
|
||||
import org.lionsoul.ip2region.xdb.XdbException;
|
||||
|
||||
public class Ip2RegionTest {
|
||||
|
||||
private static final Log log = Log.getLogger(Ip2RegionTest.class).setLevel(Log.DEBUG);
|
||||
|
||||
@Test
|
||||
public void TestConfigCreate() throws IOException, XdbException, InetAddressException, InterruptedException {
|
||||
final Config v4Config = Config.custom()
|
||||
.setCachePolicy(Config.NoCache)
|
||||
.setSeachers(10)
|
||||
.setXdbPath(ConfigTest.getDataPath("ip2region_v4.xdb"))
|
||||
.asV4();
|
||||
|
||||
final Config v6Config = Config.custom()
|
||||
.setCachePolicy(Config.VIndexCache)
|
||||
.setSeachers(10)
|
||||
.setXdbPath(ConfigTest.getDataPath("ip2region_v6.xdb"))
|
||||
.asV6();
|
||||
|
||||
byte[] v4Bytes = Util.parseIP("1.2.3.4");
|
||||
byte[] v6Bytes = Util.parseIP("240e:3b7:3272:d8d0:db09:c067:8d59:539e");
|
||||
final Ip2Region ip2Region = new Ip2Region(v4Config, v6Config);
|
||||
for (int i = 0; i < 50; i++) {
|
||||
v4Bytes = Util.ipAddOne(v4Bytes);
|
||||
v6Bytes = Util.ipAddOne(v6Bytes);
|
||||
final String v4Region = ip2Region.search(v4Bytes);
|
||||
final String v6Region = ip2Region.search(v6Bytes);
|
||||
log.debugf("search(%s)=%s, search(%s)=%s", Util.ipToString(v4Bytes), v4Region, Util.ipToString(v6Bytes), v6Region);
|
||||
}
|
||||
|
||||
ip2Region.close();
|
||||
log.debugf("ip2region closed gracefully");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestPathCreate() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestInMemSearch() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,31 +1,19 @@
|
|||
package org.lionsoul.ip2region;
|
||||
|
||||
import java.security.CodeSource;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.lionsoul.ip2region.xdb.Log;
|
||||
import org.lionsoul.ip2region.xdb.Searcher;
|
||||
|
||||
public class SearcherPoolTest {
|
||||
|
||||
private static final Log log = Log.getLogger(ConfigTest.class).setLevel(Log.DEBUG);
|
||||
|
||||
public String getDataPath(String xdbFile) {
|
||||
final CodeSource cs = this.getClass().getProtectionDomain().getCodeSource();
|
||||
if (cs != null) {
|
||||
// log.debugf("code path: %s", cs.getLocation().getPath().concat("../../../../data/"));
|
||||
return cs.getLocation().getPath().concat("../../../../data/").concat(xdbFile);
|
||||
} else {
|
||||
return "../../../../data/".concat(xdbFile);
|
||||
}
|
||||
}
|
||||
private static final Log log = Log.getLogger(SearcherPoolTest.class).setLevel(Log.DEBUG);
|
||||
|
||||
@Test
|
||||
public void testV4SeacherPool() throws Exception {
|
||||
final Config v4Config = Config.custom()
|
||||
.setCachePolicy(Config.VIndexCache)
|
||||
.setSeachers(5)
|
||||
.setXdbPath(getDataPath("ip2region_v4.xdb"))
|
||||
.setXdbPath(ConfigTest.getDataPath("ip2region_v4.xdb"))
|
||||
.asV4();
|
||||
|
||||
|
||||
|
|
@ -49,7 +37,7 @@ public class SearcherPoolTest {
|
|||
final Config v6Config = Config.custom()
|
||||
.setCachePolicy(Config.VIndexCache)
|
||||
.setSeachers(5)
|
||||
.setXdbPath(getDataPath("ip2region_v6.xdb"))
|
||||
.setXdbPath(ConfigTest.getDataPath("ip2region_v6.xdb"))
|
||||
.asV6();
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue