Skip to content

Commit cf24286

Browse files
committed
Merge pull request #3 from maxmind/greg/threading-test-docs
Added threading tests and docs.
2 parents eb40843 + d92dac0 commit cf24286

File tree

3 files changed

+101
-0
lines changed

3 files changed

+101
-0
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
0.3.2 (201X-XX-XX)
5+
------------------
6+
7+
* Added tests and documentation for mutli-threaded use.
8+
49
0.3.1 (2013-11-05)
510
------------------
611

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ as they provide a convenient representation of multi-type data structures and
4242
the databind package of Jackson 2 supplies many tools for interacting with the
4343
data in this format.
4444

45+
We recommend reusing the `Reader` object rather than creating a new one for
46+
each lookup. The creation of this object is relatively expensive as it must
47+
read in metadata for the file.
48+
4549
## Example ##
4650

4751
```java
@@ -59,6 +63,12 @@ reader.close();
5963

6064
```
6165

66+
## Multi-Threaded Use ##
67+
68+
This API fully supports use in multi-threaded applications. In such
69+
applications, we suggest creating one `Reader` object and sharing that among
70+
threads.
71+
6272
## Format ##
6373

6474
The MaxMind DB format is an open format for quickly mapping IP addresses to
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package com.maxmind.db;
2+
3+
import static org.junit.Assert.assertEquals;
4+
5+
import java.io.File;
6+
import java.io.IOException;
7+
import java.net.InetAddress;
8+
import java.net.URI;
9+
import java.net.URISyntaxException;
10+
import java.net.UnknownHostException;
11+
import java.util.Collections;
12+
import java.util.List;
13+
import java.util.concurrent.Callable;
14+
import java.util.concurrent.ExecutionException;
15+
import java.util.concurrent.ExecutorService;
16+
import java.util.concurrent.Executors;
17+
import java.util.concurrent.Future;
18+
19+
import org.junit.Test;
20+
21+
import com.fasterxml.jackson.databind.JsonNode;
22+
23+
public class MultiThreadedTest {
24+
25+
@Test
26+
public void multipleMmapOpens() throws InterruptedException,
27+
ExecutionException {
28+
Callable<JsonNode> task = new Callable<JsonNode>() {
29+
@Override
30+
public JsonNode call() throws UnknownHostException, IOException,
31+
URISyntaxException {
32+
URI file = ReaderTest.class.getResource(
33+
"/maxmind-db/test-data/MaxMind-DB-test-decoder.mmdb")
34+
.toURI();
35+
final Reader reader = new Reader(new File(file));
36+
return reader.get(InetAddress.getByName("::1.1.1.0"));
37+
}
38+
};
39+
MultiThreadedTest.runThreads(task);
40+
}
41+
42+
@Test
43+
public void streamThreadTest() throws IOException, InterruptedException,
44+
ExecutionException {
45+
final Reader reader = new Reader(ReaderTest.class.getResource(
46+
"/maxmind-db/test-data/MaxMind-DB-test-decoder.mmdb")
47+
.openStream());
48+
MultiThreadedTest.threadTest(reader);
49+
}
50+
51+
@Test
52+
public void mmapThreadTest() throws IOException, InterruptedException,
53+
ExecutionException, URISyntaxException {
54+
URI file = ReaderTest.class.getResource(
55+
"/maxmind-db/test-data/MaxMind-DB-test-decoder.mmdb").toURI();
56+
final Reader reader = new Reader(new File(file));
57+
MultiThreadedTest.threadTest(reader);
58+
}
59+
60+
private static void threadTest(final Reader reader) throws InterruptedException,
61+
ExecutionException {
62+
Callable<JsonNode> task = new Callable<JsonNode>() {
63+
@Override
64+
public JsonNode call() throws UnknownHostException, IOException {
65+
return reader.get(InetAddress.getByName("::1.1.1.0"));
66+
}
67+
};
68+
MultiThreadedTest.runThreads(task);
69+
}
70+
71+
private static void runThreads(Callable<JsonNode> task)
72+
throws InterruptedException, ExecutionException {
73+
int threadCount = 1024;
74+
List<Callable<JsonNode>> tasks = Collections.nCopies(threadCount, task);
75+
ExecutorService executorService = Executors
76+
.newFixedThreadPool(threadCount);
77+
List<Future<JsonNode>> futures = executorService.invokeAll(tasks);
78+
79+
for (Future<JsonNode> future : futures) {
80+
JsonNode record = future.get();
81+
assertEquals(268435456, record.get("uint32").intValue());
82+
assertEquals("unicode! ☯ - ♫", record.get("utf8_string")
83+
.textValue());
84+
}
85+
}
86+
}

0 commit comments

Comments
 (0)