1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.buildcache.hash;
20
21 import java.io.IOException;
22 import java.nio.ByteBuffer;
23 import java.nio.channels.FileChannel;
24 import java.nio.file.Files;
25 import java.nio.file.Path;
26
27 import net.openhft.hashing.LongHashFunction;
28
29 import static java.nio.channels.FileChannel.MapMode.READ_ONLY;
30 import static java.nio.file.StandardOpenOption.READ;
31
32
33
34
35 public class Zah implements Hash.Factory {
36
37 public enum MemoryPolicy {
38 Standard,
39 MemoryMappedBuffers
40 }
41
42 private final String name;
43 private final LongHashFunction hash;
44 private final MemoryPolicy memoryPolicy;
45
46 public Zah(String name, LongHashFunction hash, MemoryPolicy memoryPolicy) {
47 this.name = name;
48 this.hash = hash;
49 this.memoryPolicy = memoryPolicy != null ? memoryPolicy : MemoryPolicy.Standard;
50 }
51
52 @Override
53 public String getAlgorithm() {
54 return name;
55 }
56
57 @Override
58 public Hash.Algorithm algorithm() {
59 switch (memoryPolicy) {
60 case MemoryMappedBuffers:
61 return new AlgorithmWithMM();
62 default:
63 return new Algorithm();
64 }
65 }
66
67 @Override
68 public Hash.Checksum checksum(int count) {
69 return new Zah.Checksum(ByteBuffer.allocate(capacity(count)));
70 }
71
72 static int capacity(int count) {
73
74 return count * Long.SIZE / Byte.SIZE;
75 }
76
77 class Algorithm implements Hash.Algorithm {
78
79 @Override
80 public byte[] hash(byte[] array) {
81 return HexUtils.toByteArray(hash.hashBytes(array));
82 }
83
84 @Override
85 public byte[] hash(Path path) throws IOException {
86 return hash(Files.readAllBytes(path));
87 }
88 }
89
90 class AlgorithmWithMM implements Hash.Algorithm {
91
92 @Override
93 public byte[] hash(byte[] array) {
94 return HexUtils.toByteArray(hash.hashBytes(array));
95 }
96
97 @Override
98 public byte[] hash(Path path) throws IOException {
99 try (FileChannel channel = FileChannel.open(path, READ);
100 CloseableBuffer buffer = CloseableBuffer.mappedBuffer(channel, READ_ONLY)) {
101 return HexUtils.toByteArray(hash.hashBytes(buffer.getBuffer()));
102 }
103 }
104 }
105
106 class Checksum implements Hash.Checksum {
107
108 private final ByteBuffer buffer;
109
110 Checksum(ByteBuffer buffer) {
111 this.buffer = buffer;
112 }
113
114 @Override
115 public void update(byte[] hash) {
116 buffer.put(hash);
117 }
118
119 @Override
120 public byte[] digest() {
121 return HexUtils.toByteArray(hash.hashBytes(buffer, 0, buffer.position()));
122 }
123 }
124 }