Skip to content

Commit

Permalink
Split off API module (data objects shared between core, client and se…
Browse files Browse the repository at this point in the history
…rver)
  • Loading branch information
michaz committed May 25, 2018
1 parent e744897 commit 04514f2
Show file tree
Hide file tree
Showing 76 changed files with 457 additions and 331 deletions.
21 changes: 1 addition & 20 deletions client-hc/pom.xml
Expand Up @@ -36,27 +36,8 @@
<dependencies>
<dependency>
<groupId>com.graphhopper</groupId>
<artifactId>graphhopper-core</artifactId>
<artifactId>shared</artifactId>
<version>${project.parent.version}</version>
<exclusions>
<!-- We cannot yet exclude this as e.g. Helper class uses trove classes
and Helper is used e.g. in PointList
<exclusion>
<groupId>net.sf.trove4j</groupId>
<artifactId>trove4j</artifactId>
</exclusion>
-->
<exclusion>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>xmlgraphics-commons</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>javax.xml.ws</groupId>
Expand Down
Expand Up @@ -247,7 +247,7 @@ public void testCreateGPXFromInstructionList() {
req.getHints().put("instructions", true);
req.getHints().put("calc_points", true);
GHResponse ghResponse = gh.route(req);
String gpx = ghResponse.getBest().getInstructions().createGPX();
String gpx = ghResponse.getBest().getInstructions().createGPX("wurst");
assertTrue(gpx.contains("<gpx"));
assertTrue(gpx.contains("<rtept lat="));
assertTrue(gpx.contains("<trk><name>"));
Expand Down
11 changes: 5 additions & 6 deletions core/pom.xml
Expand Up @@ -36,6 +36,11 @@
</license>
</licenses>
<dependencies>
<dependency>
<groupId>com.graphhopper</groupId>
<artifactId>shared</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>com.carrotsearch</groupId>
<artifactId>hppc</artifactId>
Expand Down Expand Up @@ -66,12 +71,6 @@
<version>${jackson.version}</version>
</dependency>

<dependency>
<groupId>com.vividsolutions</groupId>
<artifactId>jts-core</artifactId>
<version>1.14.0</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
Expand Down
100 changes: 99 additions & 1 deletion core/src/main/java/com/graphhopper/storage/MMapDataAccess.java
Expand Up @@ -19,16 +19,25 @@

import com.graphhopper.util.Constants;
import com.graphhopper.util.Helper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

/**
* A DataAccess implementation using a memory-mapped file, i.e. a facility of the
Expand All @@ -49,6 +58,9 @@
* @author Michael Zilske
*/
public final class MMapDataAccess extends AbstractDataAccess {

private static final Logger LOGGER = LoggerFactory.getLogger(MMapDataAccess.class);

private final boolean allowWrites;
private RandomAccessFile raFile;
private List<ByteBuffer> segments = new ArrayList<>();
Expand All @@ -58,6 +70,92 @@ public final class MMapDataAccess extends AbstractDataAccess {
this.allowWrites = allowWrites;
}

public static boolean jreIsMinimumJava9() {
final StringTokenizer st = new StringTokenizer(System.getProperty("java.specification.version"), ".");
int JVM_MAJOR_VERSION = Integer.parseInt(st.nextToken());
int JVM_MINOR_VERSION;
if (st.hasMoreTokens()) {
JVM_MINOR_VERSION = Integer.parseInt(st.nextToken());
} else {
JVM_MINOR_VERSION = 0;
}
return JVM_MAJOR_VERSION > 1 || (JVM_MAJOR_VERSION == 1 && JVM_MINOR_VERSION >= 9);
}

public static void cleanMappedByteBuffer(final ByteBuffer buffer) {
// TODO avoid reflection on every call
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
if (jreIsMinimumJava9()) {
// >=JDK9 class sun.misc.Unsafe { void invokeCleaner(ByteBuffer buf) }
final Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
// fetch the unsafe instance and bind it to the virtual MethodHandle
final Field f = unsafeClass.getDeclaredField("theUnsafe");
f.setAccessible(true);
final Object theUnsafe = f.get(null);
final Method method = unsafeClass.getDeclaredMethod("invokeCleaner", ByteBuffer.class);
try {
method.invoke(theUnsafe, buffer);
return null;
} catch (Throwable t) {
throw new RuntimeException(t);
}
}

if (buffer.getClass().getSimpleName().equals("MappedByteBufferAdapter")) {
if (!Constants.ANDROID)
throw new RuntimeException("MappedByteBufferAdapter only supported for Android at the moment");

// For Android 4.1 call ((MappedByteBufferAdapter)buffer).free() see #914
Class<?> directByteBufferClass = Class.forName("java.nio.MappedByteBufferAdapter");
callBufferFree(buffer, directByteBufferClass);
} else {
// <=JDK8 class DirectByteBuffer { sun.misc.Cleaner cleaner(Buffer buf) }
// then call sun.misc.Cleaner.clean
final Class<?> directByteBufferClass = Class.forName("java.nio.DirectByteBuffer");
try {
final Method dbbCleanerMethod = directByteBufferClass.getMethod("cleaner");
dbbCleanerMethod.setAccessible(true);
// call: cleaner = ((DirectByteBuffer)buffer).cleaner()
final Object cleaner = dbbCleanerMethod.invoke(buffer);
if (cleaner != null) {
final Class<?> cleanerMethodReturnType = dbbCleanerMethod.getReturnType();
final Method cleanMethod = cleanerMethodReturnType.getDeclaredMethod("clean");
cleanMethod.setAccessible(true);
// call: ((sun.misc.Cleaner)cleaner).clean()
cleanMethod.invoke(cleaner);
}
} catch (NoSuchMethodException ex2) {
if (Constants.ANDROID)
// For Android 5.1.1 call ((DirectByteBuffer)buffer).free() see #933
callBufferFree(buffer, directByteBufferClass);
else
// ignore if method cleaner or clean is not available
LOGGER.warn("NoSuchMethodException | " + System.getProperty("java.version"), ex2);
}
}

return null;
}
});
} catch (PrivilegedActionException e) {
throw new RuntimeException("Unable to unmap the mapped buffer", e);
}
}

private static void callBufferFree(ByteBuffer buffer, Class<?> directByteBufferClass)
throws InvocationTargetException, IllegalAccessException {
try {
final Method dbbFreeMethod = directByteBufferClass.getMethod("free");
dbbFreeMethod.setAccessible(true);
dbbFreeMethod.invoke(buffer);
} catch (NoSuchMethodException ex2) {
LOGGER.warn("NoSuchMethodException | " + System.getProperty("java.version"), ex2);
}
}

private void initRandomAccessFile() {
if (raFile != null) {
return;
Expand Down Expand Up @@ -362,7 +460,7 @@ public int getSegments() {
private void clean(int from, int to) {
for (int i = from; i < to; i++) {
ByteBuffer bb = segments.get(i);
Helper.cleanMappedByteBuffer(bb);
cleanMappedByteBuffer(bb);
segments.set(i, null);
}
}
Expand Down
19 changes: 0 additions & 19 deletions core/src/main/java/com/graphhopper/util/PathMerger.java
Expand Up @@ -157,25 +157,6 @@ public void doWork(PathWrapper altRsp, List<Path> paths, Translation tr) {
}
}

/**
* Merges <code>otherDetails</code> into the <code>pathDetails</code>.
* <p>
* This method makes sure that Entry list around via points are merged correctly.
* See #1091 and the misplaced PathDetail after waypoints.
*/
public static void merge(List<PathDetail> pathDetails, List<PathDetail> otherDetails) {
// Make sure that the PathDetail list is merged correctly at via points
if (!pathDetails.isEmpty() && !otherDetails.isEmpty()) {
PathDetail lastDetail = pathDetails.get(pathDetails.size() - 1);
if (lastDetail.getValue().equals(otherDetails.get(0).getValue())) {
lastDetail.setLast(otherDetails.get(0).getLast());
otherDetails.remove(0);
}
}

pathDetails.addAll(otherDetails);
}

/**
* This method iterates over all instructions and uses the available context to improve the instructions.
* If the requests contains a heading, this method can transform the first continue to a u-turn if the heading
Expand Down

0 comments on commit 04514f2

Please sign in to comment.