Skip to content

Commit 8cc0e64

Browse files
committed
Fix Fingerprinter
Change-Id: Ie6ad71a184aef656781837ebb2e9b5031bef500a
1 parent 9ab9819 commit 8cc0e64

File tree

3 files changed

+65
-11
lines changed

3 files changed

+65
-11
lines changed

Changes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
- [performance] Add leaf cache. (diewald)
2+
- [bugfix] Fix fingerprinter (wasn't threadsafe; diewald)
23

34
0.64.5 2025-12-03
45
- [maintenance] Update to Java 21 (diewald)

src/main/java/de/ids_mannheim/korap/util/Fingerprinter.java

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,15 @@ public class Fingerprinter {
1212
private final static Logger log = LoggerFactory
1313
.getLogger(Fingerprinter.class);
1414

15-
private static MessageDigest md;
16-
1715
public static String create (String key) {
1816
try {
19-
md = MessageDigest.getInstance("MD5");
17+
MessageDigest md = MessageDigest.getInstance("MD5");
18+
md.update(key.getBytes());
19+
return new String(Base64.getUrlEncoder().encode(md.digest()));
2020
}
2121
catch (NoSuchAlgorithmException e) {
2222
log.error(e.getMessage());
2323
return e.getMessage();
24-
};
25-
26-
md.update(key.getBytes());
27-
String code = new String(Base64.getUrlEncoder().encode(md.digest()));
28-
29-
md.reset();
30-
return code;
31-
24+
}
3225
}
3326
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package de.ids_mannheim.korap.util;
2+
3+
import static org.junit.Assert.assertTrue;
4+
5+
import java.util.ArrayList;
6+
import java.util.List;
7+
import java.util.concurrent.CountDownLatch;
8+
import java.util.concurrent.ExecutorService;
9+
import java.util.concurrent.Executors;
10+
11+
import org.junit.Test;
12+
13+
public class TestKrillFingerprint {
14+
15+
@Test
16+
public void testMessageDigestThreadSafety() throws Exception {
17+
18+
int threads = 16;
19+
int iterationsPerThread = 5_000;
20+
21+
ExecutorService pool = Executors.newFixedThreadPool(threads);
22+
23+
CountDownLatch start = new CountDownLatch(1);
24+
CountDownLatch done = new CountDownLatch(threads);
25+
26+
List<Throwable> errors = new ArrayList<>();
27+
28+
for (int t = 0; t < threads; t++) {
29+
pool.submit(() -> {
30+
try {
31+
start.await();
32+
for (int i = 0; i < iterationsPerThread; i++) {
33+
Fingerprinter.create("key-" + i);
34+
}
35+
}
36+
catch (Throwable e) {
37+
synchronized (errors) {
38+
errors.add(e);
39+
}
40+
}
41+
finally {
42+
done.countDown();
43+
}
44+
});
45+
}
46+
47+
start.countDown();
48+
done.await();
49+
pool.shutdown();
50+
51+
if (!errors.isEmpty()) {
52+
errors.forEach(Throwable::printStackTrace);
53+
}
54+
55+
assertTrue(
56+
"Thread-safety violation detected: " + errors,
57+
errors.isEmpty()
58+
);
59+
}
60+
}

0 commit comments

Comments
 (0)