diff --git a/maker/golang/xdb/maker.go b/maker/golang/xdb/maker.go
index 570edc2..6f0ce7f 100644
--- a/maker/golang/xdb/maker.go
+++ b/maker/golang/xdb/maker.go
@@ -174,8 +174,9 @@ func (m *Maker) loadSegments() error {
}
// check the order of the data segment
- // if err := seg.RightBehind(last); err != nil {
- if err := seg.After(last); err != nil {
+ if sorting {
+ // just keep going
+ } else if err := seg.After(last); err != nil {
// return err
// @Note: If the continuity is disrupted,
// we will sort all these segments later.
diff --git a/maker/java/pom.xml b/maker/java/pom.xml
index db3f0de..18e77a6 100644
--- a/maker/java/pom.xml
+++ b/maker/java/pom.xml
@@ -4,7 +4,7 @@
org.lionsoul
ip2region-maker
- 3.0.0
+ 3.1.0
jar
ip2region
diff --git a/maker/java/src/main/java/org/lionsoul/ip2region/xdb/Maker.java b/maker/java/src/main/java/org/lionsoul/ip2region/xdb/Maker.java
index b7a1938..18764c2 100644
--- a/maker/java/src/main/java/org/lionsoul/ip2region/xdb/Maker.java
+++ b/maker/java/src/main/java/org/lionsoul/ip2region/xdb/Maker.java
@@ -57,6 +57,8 @@ import java.io.*;
import java.nio.charset.Charset;
import java.util.*;
+import org.lionsoul.ip2region.xdb.Segment.IterateAction;
+
public class Maker {
// constants define
public static final int VersionNo = 3; // 2 for XDB 2.0, 3 for XDB 3.0
@@ -108,7 +110,7 @@ public class Maker {
/// }
this.bytesCharset = Charset.forName("utf-8");
- this.segments = new LinkedList();
+ this.segments = new ArrayList();
this.dstHandle = new RandomAccessFile(dstPath, "rw");
this.indexPolicy = policy;
this.regionPool = new HashMap();
@@ -156,8 +158,9 @@ public class Maker {
private void loadSegments() throws Exception {
log.infof("try to load the segments ... ");
final long tStart = System.currentTimeMillis();
- Segment.iterate(srcFile, new Segment.IterateAction() {
+ final IterateAction itAct = new Segment.IterateAction() {
private Segment last = null;
+ private boolean sorting = false;
@Override
public void before(String line) {
@@ -176,22 +179,53 @@ public class Maker {
throw new Exception("invalid ip segment("+version.name+" expected)");
}
- if (last != null && !seg.after(last)) {
- throw new Exception("discontinuous data segment: last.eip("
- + Util.ipToString(last.endIP)+")+1 != seg.sip("+ Util.ipToString(seg.startIP) + ", "+ seg.region +")");
- }
+ if (sorting) {
+ // just keep going
+ } else if (last != null && !seg.after(last)) {
+ // throw new Exception("discontinuous data segment: last.eip("
+ // + Util.ipToString(last.endIP)+")+1 != seg.sip("+ Util.ipToString(seg.startIP) + ", "+ seg.region +")");
- // allow empty region
- // if (region.length() < 1) {
- // throw new Exception("empty region info for segment `"+seg+"`");
- // }
+ // @Note: If the continuity is disrupted,
+ // we will sort all these segments later.
+ sorting = true;
+ }
segments.add(seg);
last = seg;
}
- });
- log.infof("all segments loaded, length: %d, elapsed: %d ms", segments.size(), System.currentTimeMillis() - tStart);
+ public boolean sorting() {
+ return sorting;
+ }
+ };
+
+ // load iterate all the segments
+ Segment.iterate(srcFile, itAct);
+ final boolean sorting = itAct.sorting();
+
+ // check and sort all the segments
+ if (sorting) {
+ log.infof("try to sort all the segments based on its start ip ...");
+ segments.sort((o1, o2) -> {return Util.ipCompare(o1.startIP, o2.startIP);});
+
+ log.infof("try to check if there is overlap in the segments ...");
+ Segment last = null;
+ for (final Segment seg : segments) {
+ // check the order of the data segment
+ if (last != null && !seg.after(last)) {
+ throw new Exception("overlap checking: last.eip("
+ + Util.ipToString(last.endIP)+") >= seg.sip("+ Util.ipToString(seg.startIP) + ", "+ seg.region +")");
+ }
+
+ // reset the last
+ last = seg;
+ }
+ }
+
+ log.infof(
+ "all segments loaded, length: %d, sorting: %s, elapsed: %d ms",
+ segments.size(), sorting ? "true" : "false", System.currentTimeMillis() - tStart
+ );
}
// init the maker
diff --git a/maker/java/src/main/java/org/lionsoul/ip2region/xdb/Segment.java b/maker/java/src/main/java/org/lionsoul/ip2region/xdb/Segment.java
index 1ab808c..4effb7d 100644
--- a/maker/java/src/main/java/org/lionsoul/ip2region/xdb/Segment.java
+++ b/maker/java/src/main/java/org/lionsoul/ip2region/xdb/Segment.java
@@ -98,11 +98,18 @@ public class Segment {
return Util.ipCompare(ip, startIP) >= 0 && Util.ipCompare(ip, endIP) <= 0;
}
- // check if the current segment just after the specified one.
- public boolean after(final Segment last) {
+ // check if the current segment just right behind the specified one.
+ // which mean last.endIP + 1 = this.startIP
+ public boolean rightBehind(final Segment last) {
return Util.ipCompare(Util.ipAddOne(last.endIP), startIP) == 0;
}
+ // check if the current segment is after the specified one.
+ // which means last.endIP < this.startIP
+ public boolean after(final Segment last) {
+ return Util.ipCompare(last.endIP, startIP) < 0;
+ }
+
// parser the Segment from an input string
public static Segment parse(String input) throws Exception {
final String[] ps = input.trim().split("\\|", 3);
@@ -121,6 +128,11 @@ public class Segment {
// static class to handler the iterate callback
public static interface IterateAction {
+ // need sort all the iterated segments ?
+ default boolean sorting() {
+ return false;
+ }
+
public void before(final String line);
public String filter(final String region);
public void handle(final Segment seg) throws Exception;
@@ -186,7 +198,7 @@ public class Segment {
// check and automatic merging the Consecutive Segments, which means:
// 1, region info is the same
// 2, last.eip+1 = cur.sip
- if (last.region.equals(seg.region) && seg.after(last)) {
+ if (last.region.equals(seg.region) && seg.rightBehind(last)) {
// last.endIP = seg.endIP;
System.arraycopy(seg.endIP, 0, last.endIP, 0, seg.endIP.length);
continue;