1 package org.simantics.acorn;
3 import java.io.ByteArrayInputStream;
4 import java.io.IOException;
5 import java.io.OutputStream;
6 import java.nio.file.Files;
7 import java.nio.file.Path;
8 import java.security.MessageDigest;
9 import java.security.NoSuchAlgorithmException;
10 import java.util.ArrayList;
11 import java.util.Arrays;
13 import org.simantics.acorn.exception.InvalidHeadStateException;
14 import org.simantics.databoard.Bindings;
15 import org.simantics.databoard.adapter.AdapterConstructionException;
16 import org.simantics.databoard.binding.mutable.MutableVariant;
17 import org.simantics.databoard.serialization.Serializer;
18 import org.simantics.databoard.util.binary.BinaryMemory;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
22 public class HeadState {
24 private static transient final Logger LOGGER = LoggerFactory.getLogger(HeadState.class);
26 public static final String HEAD_STATE = "head.state";
27 public static final String SHA_1 = "SHA-1";
29 public int headChangeSetId = 0;
30 public long transactionId = 1;
31 public long reservedIds = 3;
33 public ArrayList<String> clusters = new ArrayList<>();
34 public ArrayList<String> files = new ArrayList<>();
35 public ArrayList<String> stream = new ArrayList<>();
36 public ArrayList<String> cs = new ArrayList<>();
37 // public ArrayList<String> ccs = new ArrayList<String>();
39 public long tailChangeSetId = 1;
41 public static HeadState load(Path directory) throws InvalidHeadStateException {
42 Path f = directory.resolve(HEAD_STATE);
45 byte[] bytes = Files.readAllBytes(f);
46 MessageDigest sha1 = MessageDigest.getInstance(SHA_1);
47 int digestLength = sha1.getDigestLength();
48 sha1.update(bytes, digestLength, bytes.length - digestLength);
49 byte[] newChecksum = sha1.digest();
50 if (!Arrays.equals(newChecksum, Arrays.copyOfRange(bytes, 0, digestLength))) {
51 throw new InvalidHeadStateException(
52 "Checksum " + Arrays.toString(newChecksum) + " does not match excpected "
53 + Arrays.toString(Arrays.copyOfRange(bytes, 0, digestLength)) + " for " + f.toAbsolutePath());
55 try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes, digestLength, bytes.length - digestLength)) {
56 HeadState object = (HeadState) org.simantics.databoard.Files.readFile(bais, Bindings.getBindingUnchecked(HeadState.class));
59 } catch (IOException i) {
60 Throwable cause = i.getCause();
61 if(cause instanceof AdapterConstructionException) {
62 HeadState1 old = HeadState1.load(directory);
65 return new HeadState();
66 // throw new InvalidHeadStateException(i);
67 } catch (NoSuchAlgorithmException e) {
68 throw new Error("SHA-1 Algorithm not found", e);
69 } catch (Throwable t) {
70 throw new InvalidHeadStateException(t);
74 public void save(Path directory) throws IOException {
75 Path f = directory.resolve(HEAD_STATE);
77 BinaryMemory rf = new BinaryMemory(4096);
79 MutableVariant v = new MutableVariant(Bindings.getBindingUnchecked(HeadState.class), this);
80 Serializer s = Bindings.getSerializerUnchecked( Bindings.VARIANT );
86 byte[] bytes = rf.toByteBuffer().array();
88 MessageDigest sha1 = MessageDigest.getInstance(SHA_1);
90 byte[] checksum = sha1.digest();
92 try (OutputStream out = Files.newOutputStream(f)) {
97 } catch (NoSuchAlgorithmException e) {
98 throw new Error("SHA-1 digest not found, should not happen", e);
102 public static boolean validateHeadStateIntegrity(Path headState) {
104 byte[] bytes = Files.readAllBytes(headState);
105 MessageDigest sha1 = MessageDigest.getInstance(SHA_1);
106 int digestLength = sha1.getDigestLength();
107 sha1.update(bytes, digestLength, bytes.length - digestLength);
108 byte[] newChecksum = sha1.digest();
109 if (!Arrays.equals(newChecksum, Arrays.copyOfRange(bytes, 0, digestLength))) {
110 LOGGER.error("Checksum " + Arrays.toString(newChecksum) + " does not match excpected " + Arrays.toString(Arrays.copyOfRange(bytes, 0, digestLength)) + " for " + headState.toAbsolutePath());
114 } catch (IOException e) {
115 LOGGER.error("An I/O error occured while validating integrity of head.state", e);
117 } catch (NoSuchAlgorithmException e) {
118 LOGGER.error("SHA-1 digest not found, should not happen", e);
119 throw new Error("SHA-1 digest not found, should not happen", e);