From b996c58218e5ebd64bed56ede4a1ffffcf5acf0d Mon Sep 17 00:00:00 2001 From: Gregory Oschwald Date: Thu, 5 Dec 2013 11:18:57 -0800 Subject: [PATCH 1/2] Added a test of reader in multi-threaded environment --- .../com/maxmind/db/MultiThreadedTest.java | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/test/java/com/maxmind/db/MultiThreadedTest.java diff --git a/src/test/java/com/maxmind/db/MultiThreadedTest.java b/src/test/java/com/maxmind/db/MultiThreadedTest.java new file mode 100644 index 00000000..26099f80 --- /dev/null +++ b/src/test/java/com/maxmind/db/MultiThreadedTest.java @@ -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 task = new Callable() { + @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 task = new Callable() { + @Override + public JsonNode call() throws UnknownHostException, IOException { + return reader.get(InetAddress.getByName("::1.1.1.0")); + } + }; + MultiThreadedTest.runThreads(task); + } + + private static void runThreads(Callable task) + throws InterruptedException, ExecutionException { + int threadCount = 1024; + List> tasks = Collections.nCopies(threadCount, task); + ExecutorService executorService = Executors + .newFixedThreadPool(threadCount); + List> futures = executorService.invokeAll(tasks); + + for (Future future : futures) { + JsonNode record = future.get(); + assertEquals(268435456, record.get("uint32").intValue()); + assertEquals("unicode! ☯ - ♫", record.get("utf8_string") + .textValue()); + } + } +} From d92dac0c0734ec9b7f58a563974b540749267f25 Mon Sep 17 00:00:00 2001 From: Gregory Oschwald Date: Thu, 5 Dec 2013 12:02:23 -0800 Subject: [PATCH 2/2] Added documentation about multi-threaded use --- CHANGELOG.md | 5 +++++ README.md | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0699f91e..0382403d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) ------------------ diff --git a/README.md b/README.md index e9356204..b2c23eb1 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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