FormatVersion implements Comparable<FormatVersion> { public boolean writeTo(@NotNull DocumentStore store) throws DocumentStoreException { checkNotNull(store); FormatVersion v = versionOf(store); if (v == this) { return false; } if (!canRead(v)) { throw unableToWrite("Version " + this + " cannot read " + v); } List<Integer> active = Lists.newArrayList(); for (ClusterNodeInfoDocument d : ClusterNodeInfoDocument.all(store)) { if (d.isActive()) { active.add(d.getClusterId()); } } if (!active.isEmpty() && v != V0) { throw unableToWrite("There are active cluster nodes: " + active); } if (v == V0) { UpdateOp op = new UpdateOp(VERSION_ID, true); op.set(PROP_VERSION, toString()); if (!store.create(SETTINGS, Lists.newArrayList(op))) { throw concurrentUpdate(); } } else { UpdateOp op = new UpdateOp(VERSION_ID, false); op.equals(PROP_VERSION, v.toString()); op.set(PROP_VERSION, toString()); if (store.findAndUpdate(SETTINGS, op) == null) { throw concurrentUpdate(); } } return true; } private  FormatVersion(int major, int minor, int micro); static Iterable<FormatVersion> values(); boolean canRead(FormatVersion other); @NotNull static FormatVersion versionOf(@NotNull DocumentStore store); boolean writeTo(@NotNull DocumentStore store); static FormatVersion valueOf(String s); @Override String toString(); @Override boolean equals(Object obj); @Override int compareTo(@NotNull FormatVersion other);  }
@Test public void writeTo() throws Exception { DocumentStore store = new MemoryDocumentStore(); assertFalse(V0.writeTo(store)); for (FormatVersion v : ImmutableList.of(V1_0, V1_2, V1_4, V1_6, V1_8)) { assertTrue(v.writeTo(store)); assertSame(v, FormatVersion.versionOf(store)); } }
@Test(expected = DocumentStoreException.class) public void downgrade() throws Exception { DocumentStore store = new MemoryDocumentStore(); assertTrue(V1_4.writeTo(store)); V1_2.writeTo(store); }
@Test(expected = DocumentStoreException.class) public void activeClusterNodes() throws Exception { DocumentStore store = new MemoryDocumentStore(); V1_0.writeTo(store); ClusterNodeInfo.getInstance(store, NOOP, null, null, 1); V1_2.writeTo(store); }
@Test(expected = DocumentStoreException.class) public void concurrentUpdate1() throws Exception { DocumentStore store = new MemoryDocumentStore() { private final AtomicBoolean once = new AtomicBoolean(false); @Override public <T extends Document> T findAndUpdate(Collection<T> collection, UpdateOp update) { if (collection == SETTINGS && !once.getAndSet(true)) { V1_2.writeTo(this); } return super.findAndUpdate(collection, update); } }; V1_0.writeTo(store); V1_2.writeTo(store); }
@Test(expected = DocumentStoreException.class) public void concurrentUpdate2() throws Exception { DocumentStore store = new MemoryDocumentStore() { private final AtomicBoolean once = new AtomicBoolean(false); @Override public <T extends Document> boolean create(Collection<T> collection, List<UpdateOp> updateOps) { if (collection == SETTINGS && !once.getAndSet(true)) { V1_0.writeTo(this); } return super.create(collection, updateOps); } }; V1_0.writeTo(store); }