Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
CHANGELOG
=========

0.3.2 (201X-XX-XX)
------------------

* Added tests and documentation for mutli-threaded use.

0.3.1 (2013-11-05)
------------------

Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ as they provide a convenient representation of multi-type data structures and
the databind package of Jackson 2 supplies many tools for interacting with the
data in this format.

We recommend reusing the `Reader` object rather than creating a new one for
each lookup. The creation of this object is relatively expensive as it must
read in metadata for the file.

## Example ##

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

```

## Multi-Threaded Use ##

This API fully supports use in multi-threaded applications. In such
applications, we suggest creating one `Reader` object and sharing that among
threads.

## Format ##

The MaxMind DB format is an open format for quickly mapping IP addresses to
Expand Down
86 changes: 86 additions & 0 deletions src/test/java/com/maxmind/db/MultiThreadedTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.maxmind.db;

import static org.junit.Assert.assertEquals;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.junit.Test;

import com.fasterxml.jackson.databind.JsonNode;

public class MultiThreadedTest {

@Test
public void multipleMmapOpens() throws InterruptedException,
ExecutionException {
Callable<JsonNode> task = new Callable<JsonNode>() {
@Override
public JsonNode call() throws UnknownHostException, IOException,
URISyntaxException {
URI file = ReaderTest.class.getResource(
"/maxmind-db/test-data/MaxMind-DB-test-decoder.mmdb")
.toURI();
final Reader reader = new Reader(new File(file));
return reader.get(InetAddress.getByName("::1.1.1.0"));
}
};
MultiThreadedTest.runThreads(task);
}

@Test
public void streamThreadTest() throws IOException, InterruptedException,
ExecutionException {
final Reader reader = new Reader(ReaderTest.class.getResource(
"/maxmind-db/test-data/MaxMind-DB-test-decoder.mmdb")
.openStream());
MultiThreadedTest.threadTest(reader);
}

@Test
public void mmapThreadTest() throws IOException, InterruptedException,
ExecutionException, URISyntaxException {
URI file = ReaderTest.class.getResource(
"/maxmind-db/test-data/MaxMind-DB-test-decoder.mmdb").toURI();
final Reader reader = new Reader(new File(file));
MultiThreadedTest.threadTest(reader);
}

private static void threadTest(final Reader reader) throws InterruptedException,
ExecutionException {
Callable<JsonNode> task = new Callable<JsonNode>() {
@Override
public JsonNode call() throws UnknownHostException, IOException {
return reader.get(InetAddress.getByName("::1.1.1.0"));
}
};
MultiThreadedTest.runThreads(task);
}

private static void runThreads(Callable<JsonNode> task)
throws InterruptedException, ExecutionException {
int threadCount = 1024;
List<Callable<JsonNode>> tasks = Collections.nCopies(threadCount, task);
ExecutorService executorService = Executors
.newFixedThreadPool(threadCount);
List<Future<JsonNode>> futures = executorService.invokeAll(tasks);

for (Future<JsonNode> future : futures) {
JsonNode record = future.get();
assertEquals(268435456, record.get("uint32").intValue());
assertEquals("unicode! ☯ - ♫", record.get("utf8_string")
.textValue());
}
}
}