All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.jackrabbit.oak.plugins.document.FormatVersion Maven / Gradle / Ivy

There is a newer version: 1.62.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.jackrabbit.oak.plugins.document;

import java.util.List;

import javax.annotation.Nonnull;

import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.apache.jackrabbit.oak.plugins.document.Collection.SETTINGS;

/**
 * The format version currently in use by the DocumentNodeStore and written
 * to the underlying DocumentStore. A version {@link #canRead} the current or
 * older versions.
 */
public final class FormatVersion implements Comparable {

    /**
     * A dummy version when none is available.
     */
    static final FormatVersion V0 = new FormatVersion(0, 0, 0);

    /**
     * Format version for Oak 1.0.
     */
    static final FormatVersion V1_0 = new FormatVersion(1, 0, 0);

    /**
     * Format version for Oak 1.2.
     * 

* Changes introduced with this version: *

    *
  • _lastRev entries are only updated for implicit changes (OAK-2131)
  • *
*/ static final FormatVersion V1_2 = new FormatVersion(1, 2, 0); /** * Format version for Oak 1.4. *

* Changes introduced with this version: *

    *
  • journalGC in settings collection (OAK-4528)
  • *
  • startTime in clusterNode entries, revision vector in checkpoint (OAK-3646)
  • *
  • discovery lite with clusterView in settings collection (OAK-2844)
  • *
*/ static final FormatVersion V1_4 = new FormatVersion(1, 4, 0); /** * Format version for Oak 1.6. *

* Changes introduced with this version: *

    *
  • bundle nodes into document (OAK-1312)
  • *
  • journal entries with change set summary for JCR observation (OAK-5101)
  • *
*/ static final FormatVersion V1_6 = new FormatVersion(1, 6, 0); /** * Format version for Oak 1.8. *

* Changes introduced with this version: *

    *
  • SplitDocType.DEFAULT_NO_BRANCH (OAK-5869)
  • *
  • journal entries with invalidate-only changes (OAK-5964)
  • *
*/ static final FormatVersion V1_8 = new FormatVersion(1, 8, 0); /** * The ID of the document in the settings collection that contains the * version information. */ private static final String VERSION_ID = "version"; /** * @return well known format versions. */ public static Iterable values() { return ImmutableList.of(V0, V1_0, V1_2, V1_4, V1_6, V1_8); } /** * Name of the version property. */ private static final String PROP_VERSION = "_v"; private final int major, minor, micro; private FormatVersion(int major, int minor, int micro) { this.major = major; this.minor = minor; this.micro = micro; } /** * Returns {@code true} if {@code this} version can read data written by the * {@code other} version. * * @param other the version the data was written in. * @return {@code true} if this version can read, {@code false} otherwise. */ public boolean canRead(FormatVersion other) { return compareTo(checkNotNull(other)) >= 0; } /** * Reads the {@link FormatVersion} from the given store. This method * returns {@link FormatVersion#V0} if the store currently does not have a * version set. * * @param store the store to read from. * @return the format version of the store. * @throws DocumentStoreException if an error occurs while reading from the * store. */ @Nonnull public static FormatVersion versionOf(@Nonnull DocumentStore store) throws DocumentStoreException { checkNotNull(store); FormatVersion v = V0; Document d = store.find(SETTINGS, VERSION_ID); if (d != null) { Object p = d.get(PROP_VERSION); if (p != null) { try { v = valueOf(p.toString()); } catch (IllegalArgumentException e) { throw new DocumentStoreException(e); } } } return v; } /** * Writes this version to the given document store. The write operation will * fail with a {@link DocumentStoreException} if the version change is * considered incompatible or cannot be applied for some other reason. This * includes: *
    *
  • An attempt to downgrade the existing version
  • *
  • There are active cluster nodes using an existing version
  • *
  • The version was changed concurrently
  • *
* * @param store the document store. * @return {@code true} if the version in the store was updated, * {@code false} otherwise. This method will also return {@code false} * if the version in the store equals this version and now update was * required. * @throws DocumentStoreException if the write operation fails. Reasons * include: 1) an attempt to downgrade the existing version, 2) there * are active cluster nodes using an existing version, 3) the version * was changed concurrently. */ public boolean writeTo(@Nonnull DocumentStore store) throws DocumentStoreException { checkNotNull(store); FormatVersion v = versionOf(store); if (v == this) { // already on this version return false; } if (!canRead(v)) { // never downgrade throw unableToWrite("Version " + this + " cannot read " + v); } List 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; } /** * Returns a format version for the given String representation. This method * either returns one of the well known versions or an entirely new version * if the version is not well known. * * @param s the String representation of a format version. * @return the parsed format version. * @throws IllegalArgumentException if the string is malformed. */ public static FormatVersion valueOf(String s) throws IllegalArgumentException { String[] parts = s.split("\\."); if (parts.length != 3) { throw new IllegalArgumentException(s); } int[] elements = new int[parts.length]; for (int i = 0; i < parts.length; i++) { try { elements[i] = Integer.parseInt(parts[i]); } catch (NumberFormatException e) { throw new IllegalArgumentException(s); } } FormatVersion v = new FormatVersion(elements[0], elements[1], elements[2]); for (FormatVersion known : values()) { if (v.equals(known)) { v = known; break; } } return v; } @Override public String toString() { return major + "." + minor + "." + micro; } @Override public boolean equals(Object obj) { return obj instanceof FormatVersion && compareTo((FormatVersion) obj) == 0; } @Override public int compareTo(@Nonnull FormatVersion other) { checkNotNull(other); return ComparisonChain.start() .compare(major, other.major) .compare(minor, other.minor) .compare(micro, other.micro) .result(); } private static DocumentStoreException concurrentUpdate() { return unableToWrite("Version was updated concurrently"); } private static DocumentStoreException unableToWrite(String reason) { return new DocumentStoreException( "Unable to write format version. " + reason); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy