blob: 1e82e3a1e4520559d8ce6e436402db8c08b4a32f [file] [log] [blame]
Madan Jampani5e5b3d62016-02-01 16:03:33 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Madan Jampani5e5b3d62016-02-01 16:03:33 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Madan Jampani74da78b2016-02-09 21:18:36 -080017package org.onosproject.store.primitives;
Madan Jampani5e5b3d62016-02-01 16:03:33 -080018
Madan Jampani5e5b3d62016-02-01 16:03:33 -080019import static com.google.common.base.Preconditions.checkNotNull;
20import static com.google.common.base.Preconditions.checkState;
21
Jordan Halterman948d6592017-04-20 17:18:24 -070022import java.util.Objects;
Madan Jampani74da78b2016-02-09 21:18:36 -080023import java.util.function.Function;
24
Madan Jampani3780d4b2016-04-04 18:18:24 -070025import org.onlab.util.ByteArraySizeHashPrinter;
26
Madan Jampani5e5b3d62016-02-01 16:03:33 -080027import com.google.common.base.MoreObjects;
28
29/**
30 * Map update operation.
31 *
32 * @param <K> map key type
33 * @param <V> map value type
Madan Jampani5e5b3d62016-02-01 16:03:33 -080034 */
35public final class MapUpdate<K, V> {
36
37 /**
38 * Type of database update operation.
39 */
40 public enum Type {
Jordan Halterman948d6592017-04-20 17:18:24 -070041
Madan Jampani5e5b3d62016-02-01 16:03:33 -080042 /**
Jordan Halterman5f97a302017-04-26 23:41:31 -070043 * Acquires a read lock on a key.
44 * <p>
45 * This record type will check to ensure that the lock version matches the current version for the key
46 * in the map and acquire a read lock on the key for the duration of the transaction.
Madan Jampani5e5b3d62016-02-01 16:03:33 -080047 */
Jordan Halterman5f97a302017-04-26 23:41:31 -070048 LOCK,
Madan Jampani5e5b3d62016-02-01 16:03:33 -080049
50 /**
Jordan Halterman5f97a302017-04-26 23:41:31 -070051 * Checks the version of a key without locking the key.
52 * <p>
53 * This record type will perform a simple version check during the prepare phase of the two-phase commit
54 * protocol to ensure that the key has not changed during a transaction.
55 */
56 VERSION_MATCH,
57
58 /**
59 * Updates an entry if the current version matches specified version.
Madan Jampani5e5b3d62016-02-01 16:03:33 -080060 */
61 PUT_IF_VERSION_MATCH,
62
63 /**
Jordan Halterman5f97a302017-04-26 23:41:31 -070064 * Removes an entry if the current version matches specified version.
Madan Jampani5e5b3d62016-02-01 16:03:33 -080065 */
66 REMOVE_IF_VERSION_MATCH,
Madan Jampani5e5b3d62016-02-01 16:03:33 -080067 }
68
69 private Type type;
70 private K key;
71 private V value;
Jordan Halterman5f97a302017-04-26 23:41:31 -070072 private long version = -1;
Madan Jampani5e5b3d62016-02-01 16:03:33 -080073
74 /**
75 * Returns the type of update operation.
76 * @return type of update.
77 */
78 public Type type() {
79 return type;
80 }
81
82 /**
83 * Returns the item key being updated.
84 * @return item key
85 */
86 public K key() {
87 return key;
88 }
89
90 /**
91 * Returns the new value.
92 * @return item's target value.
93 */
94 public V value() {
95 return value;
96 }
97
98 /**
Madan Jampani5e5b3d62016-02-01 16:03:33 -080099 * Returns the expected current version in the database for the key.
100 * @return expected version.
101 */
Jordan Halterman5f97a302017-04-26 23:41:31 -0700102 public long version() {
103 return version;
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800104 }
105
Madan Jampani74da78b2016-02-09 21:18:36 -0800106 /**
107 * Transforms this instance into an instance of different paramterized types.
108 *
109 * @param keyMapper transcoder for key type
110 * @param valueMapper transcoder to value type
111 * @return new instance
112 * @param <S> key type of returned instance
113 * @param <T> value type of returned instance
114 */
115 public <S, T> MapUpdate<S, T> map(Function<K, S> keyMapper, Function<V, T> valueMapper) {
116 return MapUpdate.<S, T>newBuilder()
Madan Jampani74da78b2016-02-09 21:18:36 -0800117 .withType(type)
118 .withKey(keyMapper.apply(key))
119 .withValue(value == null ? null : valueMapper.apply(value))
Jordan Halterman5f97a302017-04-26 23:41:31 -0700120 .withVersion(version)
Madan Jampani74da78b2016-02-09 21:18:36 -0800121 .build();
122 }
123
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800124 @Override
Jordan Halterman948d6592017-04-20 17:18:24 -0700125 public int hashCode() {
Jordan Halterman5f97a302017-04-26 23:41:31 -0700126 return Objects.hash(type, key, value, version);
Jordan Halterman948d6592017-04-20 17:18:24 -0700127 }
128
129 @Override
130 public boolean equals(Object object) {
131 if (object instanceof MapUpdate) {
132 MapUpdate that = (MapUpdate) object;
133 return this.type == that.type
134 && Objects.equals(this.key, that.key)
135 && Objects.equals(this.value, that.value)
Jordan Halterman5f97a302017-04-26 23:41:31 -0700136 && Objects.equals(this.version, that.version);
Jordan Halterman948d6592017-04-20 17:18:24 -0700137 }
138 return false;
139 }
140
141 @Override
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800142 public String toString() {
143 return MoreObjects.toStringHelper(this)
144 .add("type", type)
145 .add("key", key)
Madan Jampani3780d4b2016-04-04 18:18:24 -0700146 .add("value", value instanceof byte[] ? new ByteArraySizeHashPrinter((byte[]) value) : value)
Jordan Halterman5f97a302017-04-26 23:41:31 -0700147 .add("version", version)
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800148 .toString();
149 }
150
151 /**
152 * Creates a new builder instance.
153 *
154 * @param <K> key type
155 * @param <V> value type
156 * @return builder.
157 */
158 public static <K, V> Builder<K, V> newBuilder() {
159 return new Builder<>();
160 }
161
162 /**
163 * MapUpdate builder.
164 *
165 * @param <K> key type
166 * @param <V> value type
167 */
168 public static final class Builder<K, V> {
169
170 private MapUpdate<K, V> update = new MapUpdate<>();
171
172 public MapUpdate<K, V> build() {
173 validateInputs();
174 return update;
175 }
176
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800177 public Builder<K, V> withType(Type type) {
178 update.type = checkNotNull(type, "type cannot be null");
179 return this;
180 }
181
182 public Builder<K, V> withKey(K key) {
183 update.key = checkNotNull(key, "key cannot be null");
184 return this;
185 }
186
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800187 public Builder<K, V> withValue(V value) {
Madan Jampani74da78b2016-02-09 21:18:36 -0800188 update.value = value;
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800189 return this;
190 }
191
Jordan Halterman5f97a302017-04-26 23:41:31 -0700192 public Builder<K, V> withVersion(long version) {
193 update.version = version;
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800194 return this;
195 }
196
197 private void validateInputs() {
198 checkNotNull(update.type, "type must be specified");
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800199 switch (update.type) {
Jordan Halterman5f97a302017-04-26 23:41:31 -0700200 case VERSION_MATCH:
201 break;
202 case LOCK:
203 checkNotNull(update.key, "key must be specified");
204 checkState(update.version >= 0, "version must be specified");
205 break;
206 case PUT_IF_VERSION_MATCH:
207 checkNotNull(update.key, "key must be specified");
208 checkNotNull(update.value, "value must be specified.");
209 checkState(update.version >= 0, "version must be specified");
210 break;
211 case REMOVE_IF_VERSION_MATCH:
212 checkNotNull(update.key, "key must be specified");
213 checkState(update.version >= 0, "version must be specified");
214 break;
215 default:
216 throw new IllegalStateException("Unknown operation type");
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800217 }
Jordan Halterman5f97a302017-04-26 23:41:31 -0700218
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800219 }
220 }
221}