Skip to content

Commit 0e6c3c6

Browse files
committed
Cache the IPv4 start node in an IPv6 tree
1 parent b58fe1b commit 0e6c3c6

1 file changed

Lines changed: 34 additions & 13 deletions

File tree

src/main/java/com/maxmind/maxminddb/MaxMindDbReader.java

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public final class MaxMindDbReader implements Closeable {
1818
(byte) 0xCD, (byte) 0xEF, 'M', 'a', 'x', 'M', 'i', 'n', 'd', '.',
1919
'c', 'o', 'm' };
2020

21+
private int ipV4Start;
2122
private final Decoder decoder;
2223
private final Metadata metadata;
2324
private final ThreadBuffer threadBuffer;
@@ -93,20 +94,11 @@ private int findAddressInTree(InetAddress address)
9394
throws InvalidDatabaseException {
9495
byte[] rawAddress = address.getAddress();
9596

96-
boolean isIp4AddressInIp6Db = rawAddress.length == 4
97-
&& this.metadata.ipVersion == 6;
98-
int ipStartBit = isIp4AddressInIp6Db ? 96 : 0;
97+
int nodeNum = this.startNode(rawAddress.length * 8);
9998

100-
// The first node of the tree is always node 0, at the beginning of the
101-
// value
102-
int nodeNum = 0;
103-
104-
for (int i = 0; i < rawAddress.length * 8 + ipStartBit; i++) {
105-
int bit = 0;
106-
if (i >= ipStartBit) {
107-
int b = 0xFF & rawAddress[(i - ipStartBit) / 8];
108-
bit = 1 & (b >> 7 - (i % 8));
109-
}
99+
for (int i = 0; i < rawAddress.length * 8; i++) {
100+
int b = 0xFF & rawAddress[i / 8];
101+
int bit = 1 & (b >> 7 - (i % 8));
110102
int record = this.readNode(nodeNum, bit);
111103

112104
if (record == this.metadata.nodeCount) {
@@ -122,6 +114,35 @@ int record = this.readNode(nodeNum, bit);
122114
throw new InvalidDatabaseException("Something bad happened");
123115
}
124116

117+
private int startNode(int length) throws InvalidDatabaseException {
118+
// Check if we are looking up an IPv4 address in an IPv6 tree. If this
119+
// is the case, we can skip over the first 96 nodes.
120+
if (this.metadata.ipVersion == 6 && length == 32) {
121+
return this.ipV4StartNode();
122+
}
123+
// The first node of the tree is always node 0, at the beginning of the
124+
// value
125+
return 0;
126+
}
127+
128+
private int ipV4StartNode() throws InvalidDatabaseException {
129+
// This is a defensive check. There is no reason to call this when you
130+
// have an IPv4 tree.
131+
if (this.metadata.ipVersion == 4) {
132+
return 0;
133+
}
134+
135+
if (this.ipV4Start != 0) {
136+
return this.ipV4Start;
137+
}
138+
int nodeNum = 0;
139+
for (int i = 0; i < 96; i++) {
140+
nodeNum = this.readNode(nodeNum, 0);
141+
}
142+
this.ipV4Start = nodeNum;
143+
return nodeNum;
144+
}
145+
125146
private int readNode(int nodeNumber, int index)
126147
throws InvalidDatabaseException {
127148
ByteBuffer buffer = this.threadBuffer.get();

0 commit comments

Comments
 (0)