97b3ab5ed6f9c445a315f4211d801b773060c02f
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / persisted / PayloadVersion.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.cluster.datastore.persisted;
9
10 import com.google.common.annotations.Beta;
11 import com.google.common.annotations.VisibleForTesting;
12 import com.google.common.base.Preconditions;
13 import java.io.DataInput;
14 import java.io.DataOutput;
15 import java.io.IOException;
16 import javax.annotation.Nonnull;
17 import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeStreamVersion;
18 import org.opendaylight.yangtools.concepts.WritableObject;
19
20 /**
21  * Enumeration of all ABI versions supported by this implementation of persistence. An ABI version has to be bumped
22  * whenever:
23  * <ul>
24  * <li>a new event is defined</li>
25  * <li>serialization format is changed</li>
26  * </ul>
27  *
28  * <p>
29  * This version effectively defines the protocol version between actors participating on a particular shard. A shard
30  * participant instance should oppose RAFT candidates which produce persistence of an unsupported version. If a follower
31  * encounters an unsupported version it must not become fully-operational, as it does not have an accurate view
32  * of shard state.
33  *
34  * @author Robert Varga
35  */
36 @Beta
37 public enum PayloadVersion implements WritableObject {
38     // NOTE: enumeration values need to be sorted in ascending order of their version to keep Comparable working
39
40     /**
41      * Version which is older than any other version. This version exists purely for testing purposes.
42      */
43     @VisibleForTesting
44     TEST_PAST_VERSION(0) {
45         @Override
46         public NormalizedNodeStreamVersion getStreamVersion() {
47             throw new UnsupportedOperationException();
48         }
49     },
50
51     /**
52      * Initial ABI version, as shipped with Boron Simultaneous release.
53      */
54     // We seed the initial version to be the same as DataStoreVersions.BORON_VERSION for compatibility reasons.
55     BORON(5) {
56         @Override
57         public NormalizedNodeStreamVersion getStreamVersion() {
58             return NormalizedNodeStreamVersion.LITHIUM;
59         }
60     },
61
62     /**
63      * Revised payload version. Payloads remain the same as {@link #BORON}, but messages bearing QNames in any shape
64      * are using {@link NormalizedNodeStreamVersion#SODIUM}, which improves encoding.
65      */
66     SODIUM(6) {
67         @Override
68         public NormalizedNodeStreamVersion getStreamVersion() {
69             return NormalizedNodeStreamVersion.SODIUM;
70         }
71     },
72
73     /**
74      * Version which is newer than any other version. This version exists purely for testing purposes.
75      */
76     @VisibleForTesting
77     TEST_FUTURE_VERSION(65535) {
78         @Override
79         public NormalizedNodeStreamVersion getStreamVersion() {
80             throw new UnsupportedOperationException();
81         }
82     };
83
84     private final short value;
85
86     PayloadVersion(final int intVersion) {
87         Preconditions.checkArgument(intVersion >= 0 && intVersion <= 65535);
88         value = (short) intVersion;
89     }
90
91     /**
92      * Return the unsigned short integer identifying this version.
93      *
94      * @return Unsigned short integer identifying this version
95      */
96     public short shortValue() {
97         return value;
98     }
99
100     /**
101      * Return the NormalizedNode stream version corresponding to this particular ABI.
102      *
103      * @return Stream Version to use for this ABI version
104      */
105     @Nonnull
106     public abstract NormalizedNodeStreamVersion getStreamVersion();
107
108     /**
109      * Return the codebase-native persistence version. This version is the default version allocated to messages
110      * at runtime. Conversion to previous versions may incur additional overhead (such as object allocation).
111      *
112      * @return Current {@link PayloadVersion}
113      */
114     @Nonnull
115     public static PayloadVersion current() {
116         return SODIUM;
117     }
118
119     /**
120      * Return the {@link PayloadVersion} corresponding to an unsigned short integer. This method is provided for callers
121      * which provide their own recovery strategy in case of version incompatibility.
122      *
123      * @param version Short integer as returned from {@link #shortValue()}
124      * @return {@link PayloadVersion}
125      * @throws FutureVersionException if the specified integer identifies a future version
126      * @throws PastVersionException if the specified integer identifies a past version which is no longer supported
127      */
128     @Nonnull
129     public static PayloadVersion valueOf(final short version) throws FutureVersionException, PastVersionException {
130         switch (Short.toUnsignedInt(version)) {
131             case 0:
132             case 1:
133             case 2:
134             case 3:
135             case 4:
136                 throw new PastVersionException(version, BORON);
137             case 5:
138                 return BORON;
139             case 6:
140                 return SODIUM;
141             default:
142                 throw new FutureVersionException(version, SODIUM);
143         }
144     }
145
146     @Override
147     public void writeTo(final DataOutput out) throws IOException {
148         out.writeShort(value);
149     }
150
151     /**
152      * Read an {@link PayloadVersion} from a {@link DataInput}. This method is provided for callers which do not have
153      * a recovery strategy for dealing with unsupported versions.
154      *
155      * @param in Input from which to read
156      * @return An {@link PayloadVersion}
157      * @throws IOException If read fails or an unsupported version is encountered
158      */
159     @Nonnull
160     public static PayloadVersion readFrom(@Nonnull final DataInput in) throws IOException {
161         final short s = in.readShort();
162         try {
163             return valueOf(s);
164         } catch (FutureVersionException | PastVersionException e) {
165             throw new IOException("Unsupported version", e);
166         }
167     }
168 }