diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/collection/FeatureGroup.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/collection/FeatureGroup.java index 89bf956107..1108e59c0e 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/collection/FeatureGroup.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/collection/FeatureGroup.java @@ -1,7 +1,8 @@ package com.onthegomap.planetiler.collection; import com.carrotsearch.hppc.LongLongHashMap; -import com.google.common.primitives.Longs; +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteStreams; import com.onthegomap.planetiler.Profile; import com.onthegomap.planetiler.VectorTile; import com.onthegomap.planetiler.config.PlanetilerConfig; @@ -17,7 +18,6 @@ import java.io.Closeable; import java.io.IOException; import java.nio.file.Path; -import java.security.MessageDigest; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -343,18 +343,19 @@ public TileCoord tileCoord() { } /** - * Generates a hash of the features. The coordinates are not used for the generation of the hash. + * Extracts a feature's data relevant for hashing. The coordinates are not part of it. *
* Used as an optimization to avoid re-encoding and writing the same (ocean) tiles over and over again.
*/
- public byte[] generateContentHash(MessageDigest md) {
+ public byte[] getBytesRelevantForHashing() {
+ ByteArrayDataOutput out = ByteStreams.newDataOutput();
for (var feature : entries) {
long layerId = extractLayerIdFromKey(feature.key());
- md.update(Longs.toByteArray(layerId));
- md.update(feature.value());
- md.update((byte) (extractHasGroupFromKey(feature.key()) ? 1 : 0));
+ out.writeLong(layerId);
+ out.write(feature.value());
+ out.writeBoolean(extractHasGroupFromKey(feature.key()));
}
- return md.digest();
+ return out.toByteArray();
}
private VectorTile.Feature decodeVectorTileFeature(SortableFeature entry) {
diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/mbtiles/MbtilesWriter.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/mbtiles/MbtilesWriter.java
index 5d5a091b7d..a8be587a7a 100644
--- a/planetiler-core/src/main/java/com/onthegomap/planetiler/mbtiles/MbtilesWriter.java
+++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/mbtiles/MbtilesWriter.java
@@ -3,9 +3,9 @@
import static com.onthegomap.planetiler.util.Gzip.gzip;
import static com.onthegomap.planetiler.worker.Worker.joinFutures;
-import com.google.common.collect.Maps;
import com.onthegomap.planetiler.VectorTile;
import com.onthegomap.planetiler.collection.FeatureGroup;
+import com.onthegomap.planetiler.collection.FeatureGroup.TileFeatures;
import com.onthegomap.planetiler.config.MbtilesMetadata;
import com.onthegomap.planetiler.config.PlanetilerConfig;
import com.onthegomap.planetiler.geo.TileCoord;
@@ -21,13 +21,12 @@
import com.onthegomap.planetiler.worker.WorkQueue;
import com.onthegomap.planetiler.worker.WorkerPipeline;
import java.io.IOException;
-import java.nio.ByteBuffer;
import java.nio.file.Path;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -40,6 +39,7 @@
import java.util.concurrent.atomic.LongAccumulator;
import java.util.function.Consumer;
import java.util.function.LongSupplier;
+import java.util.function.Supplier;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import javax.annotation.Nullable;
@@ -68,17 +68,6 @@ public class MbtilesWriter {
private final AtomicReference
diff --git a/planetiler-core/src/test/java/com/onthegomap/planetiler/collection/FeatureGroupTest.java b/planetiler-core/src/test/java/com/onthegomap/planetiler/collection/FeatureGroupTest.java
index 0279930504..2ac61b27de 100644
--- a/planetiler-core/src/test/java/com/onthegomap/planetiler/collection/FeatureGroupTest.java
+++ b/planetiler-core/src/test/java/com/onthegomap/planetiler/collection/FeatureGroupTest.java
@@ -15,8 +15,6 @@
import com.onthegomap.planetiler.render.RenderedFeature;
import com.onthegomap.planetiler.stats.Stats;
import com.onthegomap.planetiler.util.CloseableConusmer;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -292,7 +290,7 @@ void testEncodeLongKeyOrdering(
}
@Test
- void testHasSameContentHash() {
+ void testHasSameBytesRelevantForHashing() {
// should be the "same" even though sort-key is different
putWithIdGroupAndSortKey(
1, 1, "layer", Map.of("id", 1), newPoint(1, 2), 1, true, 2, 3
@@ -303,13 +301,13 @@ void testHasSameContentHash() {
sorter.sort();
var iter = features.iterator();
assertArrayEquals(
- iter.next().generateContentHash(getMessageDigest()),
- iter.next().generateContentHash(getMessageDigest())
+ iter.next().getBytesRelevantForHashing(),
+ iter.next().getBytesRelevantForHashing()
);
}
@Test
- void testDoesNotHaveSameContentHashWhenGeometryChanges() {
+ void testDoesNotHaveSameRelevantBytesForHashingWhenGeometryChanges() {
putWithIdGroupAndSortKey(
1, 1, "layer", Map.of("id", 1), newPoint(1, 2), 1, true, 2, 3
);
@@ -319,13 +317,13 @@ void testDoesNotHaveSameContentHashWhenGeometryChanges() {
sorter.sort();
var iter = features.iterator();
assertArrayNotEquals(
- iter.next().generateContentHash(getMessageDigest()),
- iter.next().generateContentHash(getMessageDigest())
+ iter.next().getBytesRelevantForHashing(),
+ iter.next().getBytesRelevantForHashing()
);
}
@Test
- void testDoesNotHaveSameContentHashWhenAttrsChange() {
+ void testDoesNotHaveSameRelevantBytesForHashingWhenAttrsChange() {
putWithIdGroupAndSortKey(
1, 1, "layer", Map.of("id", 1), newPoint(1, 2), 1, true, 2, 3
);
@@ -335,13 +333,13 @@ void testDoesNotHaveSameContentHashWhenAttrsChange() {
sorter.sort();
var iter = features.iterator();
assertArrayNotEquals(
- iter.next().generateContentHash(getMessageDigest()),
- iter.next().generateContentHash(getMessageDigest())
+ iter.next().getBytesRelevantForHashing(),
+ iter.next().getBytesRelevantForHashing()
);
}
@Test
- void testDoesNotHaveSameContentHashWhenLayerChanges() {
+ void testDoesNotHaveSameRelevantBytesForHashingWhenLayerChanges() {
putWithIdGroupAndSortKey(
1, 1, "layer", Map.of("id", 1), newPoint(1, 2), 1, true, 2, 3
);
@@ -351,13 +349,13 @@ void testDoesNotHaveSameContentHashWhenLayerChanges() {
sorter.sort();
var iter = features.iterator();
assertArrayNotEquals(
- iter.next().generateContentHash(getMessageDigest()),
- iter.next().generateContentHash(getMessageDigest())
+ iter.next().getBytesRelevantForHashing(),
+ iter.next().getBytesRelevantForHashing()
);
}
@Test
- void testDoesNotHaveSameContentHashWhenIdChanges() {
+ void testDoesNotHaveSameRelevantBytesForHashingWhenIdChanges() {
putWithIdGroupAndSortKey(
1, 1, "layer", Map.of("id", 1), newPoint(1, 2), 1, true, 2, 3
);
@@ -367,8 +365,8 @@ void testDoesNotHaveSameContentHashWhenIdChanges() {
sorter.sort();
var iter = features.iterator();
assertArrayNotEquals(
- iter.next().generateContentHash(getMessageDigest()),
- iter.next().generateContentHash(getMessageDigest())
+ iter.next().getBytesRelevantForHashing(),
+ iter.next().getBytesRelevantForHashing()
);
}
@@ -386,14 +384,6 @@ void testEncodeDecodeGeometryMetadata(String geomTypeString, int scale) {
assertEquals(scale, FeatureGroup.decodeScale(encoded));
}
- private MessageDigest getMessageDigest() {
- try {
- return MessageDigest.getInstance("SHA-1");
- } catch (NoSuchAlgorithmException e) {
- throw new IllegalStateException("SHA-1 message digest not available", e);
- }
- }
-
private static void assertArrayNotEquals(byte[] expected, byte[] actual) {
assertFalse(Arrays.equals(expected, actual));
}