@@ -19,10 +19,9 @@ public final class Reader implements Closeable {
1919 (byte ) 0xCD , (byte ) 0xEF , 'M' , 'a' , 'x' , 'M' , 'i' , 'n' , 'd' , '.' ,
2020 'c' , 'o' , 'm' };
2121
22- private int ipV4Start ;
23- private final Decoder decoder ;
22+ private final int ipV4Start ;
2423 private final Metadata metadata ;
25- private final ThreadBuffer threadBuffer ;
24+ private final BufferHolder bufferHolder ;
2625
2726 /**
2827 * The file mode to use when opening a MaxMind DB.
@@ -63,7 +62,7 @@ public Reader(File database) throws IOException {
6362 * if there is an error reading from the Stream.
6463 */
6564 public Reader (InputStream source ) throws IOException {
66- this (new ThreadBuffer (source ), "<InputStream>" );
65+ this (new BufferHolder (source ), "<InputStream>" );
6766 }
6867
6968 /**
@@ -78,17 +77,19 @@ public Reader(InputStream source) throws IOException {
7877 * if there is an error opening or reading from the file.
7978 */
8079 public Reader (File database , FileMode fileMode ) throws IOException {
81- this (new ThreadBuffer (database , fileMode ), database .getName ());
80+ this (new BufferHolder (database , fileMode ), database .getName ());
8281 }
8382
84- private Reader (ThreadBuffer buffer , String name ) throws IOException {
85- this .threadBuffer = buffer ;
86- int start = this .findMetadataStart (name );
83+ private Reader (BufferHolder bufferHolder , String name ) throws IOException {
84+ this .bufferHolder = bufferHolder ;
8785
88- Decoder metadataDecoder = new Decoder (this .threadBuffer , start );
86+ ByteBuffer buffer = this .bufferHolder .get ();
87+ int start = this .findMetadataStart (buffer , name );
88+
89+ Decoder metadataDecoder = new Decoder (buffer , start );
8990 this .metadata = new Metadata (metadataDecoder .decode (start ).getNode ());
90- this . decoder = new Decoder ( this . threadBuffer ,
91- this .metadata . searchTreeSize + DATA_SECTION_SEPARATOR_SIZE );
91+
92+ this .ipV4Start = this . findIpV4StartNode ( buffer );
9293 }
9394
9495 /**
@@ -101,27 +102,28 @@ private Reader(ThreadBuffer buffer, String name) throws IOException {
101102 * if a file I/O error occurs.
102103 */
103104 public JsonNode get (InetAddress ipAddress ) throws IOException {
104- int pointer = this .findAddressInTree (ipAddress );
105+ ByteBuffer buffer = this .bufferHolder .get ();
106+ int pointer = this .findAddressInTree (buffer , ipAddress );
105107 if (pointer == 0 ) {
106108 return null ;
107109 }
108- return this .resolveDataPointer (pointer );
110+ return this .resolveDataPointer (buffer , pointer );
109111 }
110112
111- private int findAddressInTree (InetAddress address )
113+ private int findAddressInTree (ByteBuffer buffer , InetAddress address )
112114 throws InvalidDatabaseException {
113115 byte [] rawAddress = address .getAddress ();
114116
115117 int bitLength = rawAddress .length * 8 ;
116- int record = this .startNode (bitLength );
118+ int record = this .startNode (buffer , bitLength );
117119
118120 for (int i = 0 ; i < bitLength ; i ++) {
119121 if (record >= this .metadata .nodeCount ) {
120122 break ;
121123 }
122124 int b = 0xFF & rawAddress [i / 8 ];
123125 int bit = 1 & (b >> 7 - (i % 8 ));
124- record = this .readNode (record , bit );
126+ record = this .readNode (buffer , record , bit );
125127 }
126128 if (record == this .metadata .nodeCount ) {
127129 // record is empty
@@ -133,38 +135,31 @@ record = this.readNode(record, bit);
133135 throw new InvalidDatabaseException ("Something bad happened" );
134136 }
135137
136- private int startNode (int bitLength ) throws InvalidDatabaseException {
138+ private int startNode (ByteBuffer buffer , int bitLength ) throws InvalidDatabaseException {
137139 // Check if we are looking up an IPv4 address in an IPv6 tree. If this
138140 // is the case, we can skip over the first 96 nodes.
139141 if (this .metadata .ipVersion == 6 && bitLength == 32 ) {
140- return this .ipV4StartNode () ;
142+ return this .ipV4Start ;
141143 }
142144 // The first node of the tree is always node 0, at the beginning of the
143145 // value
144146 return 0 ;
145147 }
146148
147- private int ipV4StartNode () throws InvalidDatabaseException {
148- // This is a defensive check. There is no reason to call this when you
149- // have an IPv4 tree.
149+ private int findIpV4StartNode (ByteBuffer buffer ) throws InvalidDatabaseException {
150150 if (this .metadata .ipVersion == 4 ) {
151151 return 0 ;
152152 }
153153
154- if (this .ipV4Start != 0 ) {
155- return this .ipV4Start ;
156- }
157154 int node = 0 ;
158155 for (int i = 0 ; i < 96 && node < this .metadata .nodeCount ; i ++) {
159- node = this .readNode (node , 0 );
156+ node = this .readNode (buffer , node , 0 );
160157 }
161- this .ipV4Start = node ;
162158 return node ;
163159 }
164160
165- private int readNode (int nodeNumber , int index )
161+ private int readNode (ByteBuffer buffer , int nodeNumber , int index )
166162 throws InvalidDatabaseException {
167- ByteBuffer buffer = this .threadBuffer .get ();
168163 int baseOffset = nodeNumber * this .metadata .nodeByteSize ;
169164
170165 switch (this .metadata .recordSize ) {
@@ -190,19 +185,21 @@ private int readNode(int nodeNumber, int index)
190185 }
191186 }
192187
193- private JsonNode resolveDataPointer (int pointer ) throws IOException {
188+ private JsonNode resolveDataPointer (ByteBuffer buffer , int pointer ) throws IOException {
194189 int resolved = (pointer - this .metadata .nodeCount )
195190 + this .metadata .searchTreeSize ;
196191
197- if (resolved >= this . threadBuffer . get () .capacity ()) {
192+ if (resolved >= buffer .capacity ()) {
198193 throw new InvalidDatabaseException (
199194 "The MaxMind DB file's search tree is corrupt: "
200195 + "contains pointer larger than the database." );
201196 }
202197
203198 // We only want the data from the decoder, not the offset where it was
204199 // found.
205- return this .decoder .decode (resolved ).getNode ();
200+ Decoder decoder = new Decoder (buffer ,
201+ this .metadata .searchTreeSize + DATA_SECTION_SEPARATOR_SIZE );
202+ return decoder .decode (resolved ).getNode ();
206203 }
207204
208205 /*
@@ -213,9 +210,8 @@ private JsonNode resolveDataPointer(int pointer) throws IOException {
213210 * are much faster algorithms (e.g., Boyer-Moore) for this if speed is ever
214211 * an issue, but I suspect it won't be.
215212 */
216- private int findMetadataStart (String databaseName )
213+ private int findMetadataStart (ByteBuffer buffer , String databaseName )
217214 throws InvalidDatabaseException {
218- ByteBuffer buffer = this .threadBuffer .get ();
219215 int fileSize = buffer .capacity ();
220216
221217 FILE : for (int i = 0 ; i < fileSize - METADATA_START_MARKER .length + 1 ; i ++) {
@@ -245,6 +241,6 @@ Metadata getMetadata() {
245241 */
246242 @ Override
247243 public void close () throws IOException {
248- this .threadBuffer .close ();
244+ this .bufferHolder .close ();
249245 }
250246}
0 commit comments