Skip to content

Commit 0a01ffd

Browse files
Optimize file I/O
1 parent 2c2bbc7 commit 0a01ffd

File tree

3 files changed

+62
-28
lines changed

3 files changed

+62
-28
lines changed

com/ip2location/IP2Location.java

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
* <p>
3737
*
3838
* @author IP2Location.com
39-
* @version 8.6.0
39+
* @version 8.7.0
4040
*/
4141
public class IP2Location {
4242
private static final Pattern pattern = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"); // IPv4
@@ -218,10 +218,11 @@ private boolean LoadBIN() throws IOException {
218218
try {
219219
if (IPDatabasePath.length() > 0) {
220220
aFile = new RandomAccessFile(IPDatabasePath, "r");
221-
final FileChannel inChannel = aFile.getChannel();
222-
final MappedByteBuffer _HeaderBuffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, 64); // 64 bytes header
223-
221+
byte[] _HeaderData = new byte[64];
222+
aFile.read(_HeaderData);
223+
ByteBuffer _HeaderBuffer = ByteBuffer.wrap(_HeaderData);
224224
_HeaderBuffer.order(ByteOrder.LITTLE_ENDIAN);
225+
225226
_MetaData = new MetaData();
226227

227228
_MetaData.setDBType(_HeaderBuffer.get(0));
@@ -309,8 +310,17 @@ private boolean LoadBIN() throws IOException {
309310
CATEGORY_ENABLED = (CATEGORY_POSITION[dbtype] != 0);
310311

311312
if (_MetaData.getIndexed()) {
312-
final MappedByteBuffer _IndexBuffer = inChannel.map(FileChannel.MapMode.READ_ONLY, _MetaData.getIndexBaseAddr() - 1, _MetaData.getBaseAddr() - _MetaData.getIndexBaseAddr()); // reading indexes
313+
int readLen = _IndexArrayIPv4.length;
314+
if (_MetaData.getIndexedIPv6()) {
315+
readLen += _IndexArrayIPv6.length;
316+
}
317+
318+
byte[] _IndexData = new byte[readLen * 8]; // 4 bytes for both from row and to row
319+
aFile.seek(_MetaData.getIndexBaseAddr() - 1);
320+
aFile.read(_IndexData);
321+
ByteBuffer _IndexBuffer = ByteBuffer.wrap(_IndexData);
313322
_IndexBuffer.order(ByteOrder.LITTLE_ENDIAN);
323+
314324
int pointer = 0;
315325

316326
// read IPv4 index
@@ -331,7 +341,7 @@ private boolean LoadBIN() throws IOException {
331341
}
332342

333343
if (UseMemoryMappedFile) {
334-
CreateMappedBytes(inChannel);
344+
CreateMappedBytes();
335345
} else {
336346
DestroyMappedBytes();
337347
}
@@ -365,6 +375,8 @@ public IPResult IPQuery(String IPAddress) throws IOException {
365375
RandomAccessFile filehandle = null;
366376
ByteBuffer mybuffer = null;
367377
ByteBuffer mydatabuffer = null;
378+
byte[] row;
379+
byte[] fullrow = null;
368380

369381
try {
370382
if (IPAddress == null || IPAddress.length() == 0) {
@@ -407,6 +419,7 @@ public IPResult IPQuery(String IPAddress) throws IOException {
407419
long position;
408420
BigInteger ipfrom;
409421
BigInteger ipto;
422+
int firstcol = 4; // IP From is 4 bytes
410423

411424
// Read BIN if haven't done so
412425
if (_MetaData == null) {
@@ -444,6 +457,8 @@ public IPResult IPQuery(String IPAddress) throws IOException {
444457
high = _IndexArrayIPv4[indexaddr][1];
445458
}
446459
} else { // IPv6
460+
firstcol = 16; // IPv6 is 16 bytes
461+
447462
if (_MetaData.getOldBIN()) {
448463
record.status = "IPV6_NOT_SUPPORTED";
449464
return record;
@@ -475,26 +490,28 @@ public IPResult IPQuery(String IPAddress) throws IOException {
475490
rowoffset2 = rowoffset + mycolumnsize;
476491

477492
if (UseMemoryMappedFile) {
493+
// only reading the IP From fields
478494
overcapacity = (rowoffset2 >= mybufcapacity);
495+
ipfrom = read32or128(rowoffset, myiptype, mybuffer, filehandle);
496+
ipto = (overcapacity) ? BigInteger.ZERO : read32or128(rowoffset2, myiptype, mybuffer, filehandle);
497+
} else {
498+
// reading IP From + whole row + next IP From
499+
fullrow = readRow(rowoffset, mycolumnsize + firstcol, mybuffer, filehandle);
500+
ipfrom = read32or128Row(fullrow, 0, firstcol);
501+
ipto = (overcapacity) ? BigInteger.ZERO : read32or128Row(fullrow, mycolumnsize, firstcol);
479502
}
480503

481-
ipfrom = read32or128(rowoffset, myiptype, mybuffer, filehandle);
482-
ipto = (overcapacity) ? BigInteger.ZERO : read32or128(rowoffset2, myiptype, mybuffer, filehandle);
483-
484504
if (ipno.compareTo(ipfrom) >= 0 && ipno.compareTo(ipto) < 0) {
485-
int firstcol = 4; // IP From is 4 bytes
486-
if (myiptype == 6) { // IPv6
487-
firstcol = 16; // IPv6 is 16 bytes
488-
}
489505

490-
// read the row here after the IP From column (remaining columns are all 4 bytes)
491506
int rowlen = mycolumnsize - firstcol;
492-
byte[] row;
493-
row = readRow(rowoffset + firstcol, rowlen, mybuffer, filehandle);
494507

495508
if (UseMemoryMappedFile) {
509+
row = readRow(rowoffset + firstcol, rowlen, mybuffer, filehandle);
496510
mydatabuffer = _MapDataBuffer.duplicate(); // this is to enable reading of a range of bytes in multi-threaded environment
497511
mydatabuffer.order(ByteOrder.LITTLE_ENDIAN);
512+
} else {
513+
row = new byte[rowlen];
514+
System.arraycopy(fullrow, firstcol, row, (int) 0, rowlen); // extract the actual row data
498515
}
499516

500517
if (COUNTRY_ENABLED) {
@@ -881,6 +898,13 @@ private byte[] readRow(final long position, final long mylen, final ByteBuffer m
881898
return row;
882899
}
883900

901+
private BigInteger read32or128Row(byte[] row, final int from, final int len) throws IOException {
902+
byte[] buf = new byte[len];
903+
System.arraycopy(row, from, buf, (int) 0, len);
904+
reverse(buf);
905+
return new BigInteger(1, buf);
906+
}
907+
884908
private BigInteger read32or128(final long position, final int myiptype, final ByteBuffer mybuffer, final RandomAccessFile filehandle) throws IOException {
885909
if (myiptype == 4) {
886910
return read32(position, mybuffer, filehandle);
@@ -930,27 +954,37 @@ private BigInteger read32(final long position, final ByteBuffer mybuffer, final
930954
}
931955

932956
private String readStr(long position, final ByteBuffer mydatabuffer, final RandomAccessFile filehandle) throws IOException {
933-
final int size;
957+
int size = 257; // max size of string field + 1 byte for the position
958+
final int len;
959+
final byte[] data = new byte[size];
934960
byte[] buf;
935961

936962
if (UseMemoryMappedFile) {
937963
position = position - _MapDataOffset; // position stored in BIN file is for full file, not just the mapped data segment, so need to minus
938-
size = _MapDataBuffer.get((int) position); // use absolute offset to be thread-safe (keep using the original buffer since is absolute position & just reading 1 byte)
939-
940964
try {
941-
buf = new byte[size];
942-
mydatabuffer.position((int) position + 1);
943-
mydatabuffer.get(buf, 0, size);
965+
mydatabuffer.position((int) position);
966+
if (mydatabuffer.remaining() < size) {
967+
size = mydatabuffer.remaining();
968+
}
969+
mydatabuffer.get(data, 0, size);
970+
len = data[0];
971+
972+
buf = new byte[len];
973+
System.arraycopy(data, 1, buf, (int) 0, len);
944974

945975
} catch (NegativeArraySizeException e) {
946976
return null;
947977
}
978+
948979
} else {
949980
filehandle.seek(position);
950-
size = filehandle.read();
951981
try {
952-
buf = new byte[size];
953-
filehandle.read(buf, 0, size);
982+
filehandle.read(data, 0, size);
983+
len = data[0];
984+
985+
buf = new byte[len];
986+
System.arraycopy(data, 1, buf, (int) 0, len);
987+
954988
} catch (NegativeArraySizeException e) {
955989
return null;
956990
}

com/ip2location/IP2LocationWebService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
* <p>
2929
*
3030
* @author IP2Location.com
31-
* @version 8.6.0
31+
* @version 8.7.0
3232
*/
3333
public class IP2LocationWebService {
3434
private static final Pattern pattern = Pattern.compile("^[\\dA-Z]{10}$");

com/ip2location/IPResult.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* <p>
1010
*
1111
* @author IP2Location.com
12-
* @version 8.6.0
12+
* @version 8.7.0
1313
*/
1414
public class IPResult {
1515
static final String NOT_SUPPORTED = "Not_Supported";
@@ -38,7 +38,7 @@ public class IPResult {
3838
String category;
3939
String status;
4040
boolean delay = false;
41-
String version = "Version 8.6.0";
41+
String version = "Version 8.7.0";
4242

4343
IPResult(String ipstring) {
4444
ip_address = ipstring;

0 commit comments

Comments
 (0)