HIGUCHI Yuta
Committed by Gerrit Code Review

Some improvements around EventuallyConsistentMapBuilder serializer handling.

- Allow directly passing KryoNamespace
- Add some registration id gap before ECMap's internal registration
- Some improvements for ease of registration issue investigation
-- Add friendly name to ECMap's internal KryoNamespace
-- Add backtrace information

Change-Id: I7c87b3aefbaea4b2ed12b38c3e0813e9d195c7a9
...@@ -182,6 +182,11 @@ public final class VtnEventuallyConsistentMapTest<K, V> extends VtnEventuallyCon ...@@ -182,6 +182,11 @@ public final class VtnEventuallyConsistentMapTest<K, V> extends VtnEventuallyCon
182 } 182 }
183 183
184 @Override 184 @Override
185 + public EventuallyConsistentMapBuilder<K, V> withSerializer(KryoNamespace serializer) {
186 + return this;
187 + }
188 +
189 + @Override
185 public EventuallyConsistentMapBuilder<K, V> 190 public EventuallyConsistentMapBuilder<K, V>
186 withTimestampProvider(BiFunction<K, V, Timestamp> timestampProvider) { 191 withTimestampProvider(BiFunction<K, V, Timestamp> timestampProvider) {
187 return this; 192 return this;
......
...@@ -67,6 +67,20 @@ public interface EventuallyConsistentMapBuilder<K, V> { ...@@ -67,6 +67,20 @@ public interface EventuallyConsistentMapBuilder<K, V> {
67 KryoNamespace.Builder serializerBuilder); 67 KryoNamespace.Builder serializerBuilder);
68 68
69 /** 69 /**
70 + * Sets a serializer that can be used to create a serializer that
71 + * can serialize both the keys and values put into the map. The serializer
72 + * builder should be pre-populated with any classes that will be put into
73 + * the map.
74 + * <p>
75 + * Note: This is a mandatory parameter.
76 + * </p>
77 + *
78 + * @param serializer serializer
79 + * @return this EventuallyConsistentMapBuilder
80 + */
81 + EventuallyConsistentMapBuilder<K, V> withSerializer(KryoNamespace serializer);
82 +
83 + /**
70 * Sets the function to use for generating timestamps for map updates. 84 * Sets the function to use for generating timestamps for map updates.
71 * <p> 85 * <p>
72 * The client must provide an {@code BiFunction<K, V, Timestamp>} 86 * The client must provide an {@code BiFunction<K, V, Timestamp>}
......
...@@ -179,6 +179,11 @@ public final class TestEventuallyConsistentMap<K, V> extends EventuallyConsisten ...@@ -179,6 +179,11 @@ public final class TestEventuallyConsistentMap<K, V> extends EventuallyConsisten
179 } 179 }
180 180
181 @Override 181 @Override
182 + public EventuallyConsistentMapBuilder<K, V> withSerializer(KryoNamespace serializer) {
183 + return this;
184 + }
185 +
186 + @Override
182 public EventuallyConsistentMapBuilder<K, V> 187 public EventuallyConsistentMapBuilder<K, V>
183 withTimestampProvider(BiFunction<K, V, Timestamp> timestampProvider) { 188 withTimestampProvider(BiFunction<K, V, Timestamp> timestampProvider) {
184 return this; 189 return this;
......
...@@ -42,6 +42,7 @@ public class EventuallyConsistentMapBuilderImpl<K, V> ...@@ -42,6 +42,7 @@ public class EventuallyConsistentMapBuilderImpl<K, V>
42 private final ClusterCommunicationService clusterCommunicator; 42 private final ClusterCommunicationService clusterCommunicator;
43 43
44 private String name; 44 private String name;
45 + private KryoNamespace serializer;
45 private KryoNamespace.Builder serializerBuilder; 46 private KryoNamespace.Builder serializerBuilder;
46 private ExecutorService eventExecutor; 47 private ExecutorService eventExecutor;
47 private ExecutorService communicationExecutor; 48 private ExecutorService communicationExecutor;
...@@ -85,6 +86,12 @@ public class EventuallyConsistentMapBuilderImpl<K, V> ...@@ -85,6 +86,12 @@ public class EventuallyConsistentMapBuilderImpl<K, V>
85 } 86 }
86 87
87 @Override 88 @Override
89 + public EventuallyConsistentMapBuilder<K, V> withSerializer(KryoNamespace serializer) {
90 + this.serializer = checkNotNull(serializer);
91 + return this;
92 + }
93 +
94 + @Override
88 public EventuallyConsistentMapBuilder<K, V> withTimestampProvider( 95 public EventuallyConsistentMapBuilder<K, V> withTimestampProvider(
89 BiFunction<K, V, Timestamp> timestampProvider) { 96 BiFunction<K, V, Timestamp> timestampProvider) {
90 this.timestampProvider = checkNotNull(timestampProvider); 97 this.timestampProvider = checkNotNull(timestampProvider);
...@@ -147,13 +154,16 @@ public class EventuallyConsistentMapBuilderImpl<K, V> ...@@ -147,13 +154,16 @@ public class EventuallyConsistentMapBuilderImpl<K, V>
147 @Override 154 @Override
148 public EventuallyConsistentMap<K, V> build() { 155 public EventuallyConsistentMap<K, V> build() {
149 checkNotNull(name, "name is a mandatory parameter"); 156 checkNotNull(name, "name is a mandatory parameter");
150 - checkNotNull(serializerBuilder, "serializerBuilder is a mandatory parameter");
151 checkNotNull(timestampProvider, "timestampProvider is a mandatory parameter"); 157 checkNotNull(timestampProvider, "timestampProvider is a mandatory parameter");
158 + if (serializer == null && serializerBuilder != null) {
159 + serializer = serializerBuilder.build(name);
160 + }
161 + checkNotNull(serializer, "serializer is a mandatory parameter");
152 162
153 return new EventuallyConsistentMapImpl<>(name, 163 return new EventuallyConsistentMapImpl<>(name,
154 clusterService, 164 clusterService,
155 clusterCommunicator, 165 clusterCommunicator,
156 - serializerBuilder, 166 + serializer,
157 timestampProvider, 167 timestampProvider,
158 peerUpdateFunction, 168 peerUpdateFunction,
159 eventExecutor, 169 eventExecutor,
......
...@@ -58,7 +58,6 @@ import org.onosproject.store.serializers.StoreSerializer; ...@@ -58,7 +58,6 @@ import org.onosproject.store.serializers.StoreSerializer;
58 import org.onosproject.store.service.EventuallyConsistentMap; 58 import org.onosproject.store.service.EventuallyConsistentMap;
59 import org.onosproject.store.service.EventuallyConsistentMapEvent; 59 import org.onosproject.store.service.EventuallyConsistentMapEvent;
60 import org.onosproject.store.service.EventuallyConsistentMapListener; 60 import org.onosproject.store.service.EventuallyConsistentMapListener;
61 -import org.onosproject.store.service.Serializer;
62 import org.onosproject.store.service.WallClockTimestamp; 61 import org.onosproject.store.service.WallClockTimestamp;
63 import org.slf4j.Logger; 62 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory; 63 import org.slf4j.LoggerFactory;
...@@ -138,7 +137,7 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -138,7 +137,7 @@ public class EventuallyConsistentMapImpl<K, V>
138 * @param mapName a String identifier for the map. 137 * @param mapName a String identifier for the map.
139 * @param clusterService the cluster service 138 * @param clusterService the cluster service
140 * @param clusterCommunicator the cluster communications service 139 * @param clusterCommunicator the cluster communications service
141 - * @param serializerBuilder a Kryo namespace builder that can serialize 140 + * @param serializer a Kryo namespace that can serialize
142 * both K and V 141 * both K and V
143 * @param timestampProvider provider of timestamps for K and V 142 * @param timestampProvider provider of timestamps for K and V
144 * @param peerUpdateFunction function that provides a set of nodes to immediately 143 * @param peerUpdateFunction function that provides a set of nodes to immediately
...@@ -159,7 +158,7 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -159,7 +158,7 @@ public class EventuallyConsistentMapImpl<K, V>
159 EventuallyConsistentMapImpl(String mapName, 158 EventuallyConsistentMapImpl(String mapName,
160 ClusterService clusterService, 159 ClusterService clusterService,
161 ClusterCommunicationService clusterCommunicator, 160 ClusterCommunicationService clusterCommunicator,
162 - KryoNamespace.Builder serializerBuilder, 161 + KryoNamespace ns,
163 BiFunction<K, V, Timestamp> timestampProvider, 162 BiFunction<K, V, Timestamp> timestampProvider,
164 BiFunction<K, V, Collection<NodeId>> peerUpdateFunction, 163 BiFunction<K, V, Collection<NodeId>> peerUpdateFunction,
165 ExecutorService eventExecutor, 164 ExecutorService eventExecutor,
...@@ -172,25 +171,14 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -172,25 +171,14 @@ public class EventuallyConsistentMapImpl<K, V>
172 boolean persistent, 171 boolean persistent,
173 PersistenceService persistenceService) { 172 PersistenceService persistenceService) {
174 this.mapName = mapName; 173 this.mapName = mapName;
175 - this.serializer = createSerializer(serializerBuilder); 174 + this.serializer = createSerializer(ns);
176 this.persistenceService = persistenceService; 175 this.persistenceService = persistenceService;
177 this.persistent = 176 this.persistent =
178 persistent; 177 persistent;
179 if (persistent) { 178 if (persistent) {
180 items = this.persistenceService.<K, MapValue<V>>persistentMapBuilder() 179 items = this.persistenceService.<K, MapValue<V>>persistentMapBuilder()
181 .withName(PERSISTENT_LOCAL_MAP_NAME) 180 .withName(PERSISTENT_LOCAL_MAP_NAME)
182 - .withSerializer(new Serializer() { 181 + .withSerializer(this.serializer)
183 -
184 - @Override
185 - public <T> byte[] encode(T object) {
186 - return EventuallyConsistentMapImpl.this.serializer.encode(object);
187 - }
188 -
189 - @Override
190 - public <T> T decode(byte[] bytes) {
191 - return EventuallyConsistentMapImpl.this.serializer.decode(bytes);
192 - }
193 - })
194 .build(); 182 .build();
195 } else { 183 } else {
196 items = Maps.newConcurrentMap(); 184 items = Maps.newConcurrentMap();
...@@ -268,18 +256,21 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -268,18 +256,21 @@ public class EventuallyConsistentMapImpl<K, V>
268 this.lightweightAntiEntropy = !convergeFaster; 256 this.lightweightAntiEntropy = !convergeFaster;
269 } 257 }
270 258
271 - private StoreSerializer createSerializer(KryoNamespace.Builder builder) { 259 + private StoreSerializer createSerializer(KryoNamespace ns) {
272 - return StoreSerializer.using(builder 260 + return StoreSerializer.using(KryoNamespace.newBuilder()
273 - .register(KryoNamespaces.BASIC) 261 + .register(ns)
274 - .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID) 262 + // not so robust way to avoid collision with other
275 - .register(LogicalTimestamp.class) 263 + // user supplied registrations
276 - .register(WallClockTimestamp.class) 264 + .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID + 100)
277 - .register(AntiEntropyAdvertisement.class) 265 + .register(KryoNamespaces.BASIC)
278 - .register(AntiEntropyResponse.class) 266 + .register(LogicalTimestamp.class)
279 - .register(UpdateEntry.class) 267 + .register(WallClockTimestamp.class)
280 - .register(MapValue.class) 268 + .register(AntiEntropyAdvertisement.class)
281 - .register(MapValue.Digest.class) 269 + .register(AntiEntropyResponse.class)
282 - .build(name())); 270 + .register(UpdateEntry.class)
271 + .register(MapValue.class)
272 + .register(MapValue.Digest.class)
273 + .build(name() + "-ecmap"));
283 } 274 }
284 275
285 @Override 276 @Override
......
...@@ -20,11 +20,12 @@ import java.io.OutputStream; ...@@ -20,11 +20,12 @@ import java.io.OutputStream;
20 import java.nio.ByteBuffer; 20 import java.nio.ByteBuffer;
21 21
22 import org.onlab.util.KryoNamespace; 22 import org.onlab.util.KryoNamespace;
23 +import org.onosproject.store.service.Serializer;
23 24
24 /** 25 /**
25 * Service to serialize Objects into byte array. 26 * Service to serialize Objects into byte array.
26 */ 27 */
27 -public interface StoreSerializer { 28 +public interface StoreSerializer extends Serializer {
28 29
29 /** 30 /**
30 * Serializes the specified object into bytes. 31 * Serializes the specified object into bytes.
...@@ -32,6 +33,7 @@ public interface StoreSerializer { ...@@ -32,6 +33,7 @@ public interface StoreSerializer {
32 * @param obj object to be serialized 33 * @param obj object to be serialized
33 * @return serialized bytes 34 * @return serialized bytes
34 */ 35 */
36 + @Override
35 byte[] encode(final Object obj); 37 byte[] encode(final Object obj);
36 38
37 /** 39 /**
...@@ -57,6 +59,7 @@ public interface StoreSerializer { ...@@ -57,6 +59,7 @@ public interface StoreSerializer {
57 * @return deserialized object 59 * @return deserialized object
58 * @param <T> decoded type 60 * @param <T> decoded type
59 */ 61 */
62 + @Override
60 <T> T decode(final byte[] bytes); 63 <T> T decode(final byte[] bytes);
61 64
62 /** 65 /**
......
...@@ -125,9 +125,11 @@ public final class KryoNamespace implements KryoFactory, KryoPool { ...@@ -125,9 +125,11 @@ public final class KryoNamespace implements KryoFactory, KryoPool {
125 if (!types.isEmpty()) { 125 if (!types.isEmpty()) {
126 if (id != FLOATING_ID && id < blockHeadId + types.size()) { 126 if (id != FLOATING_ID && id < blockHeadId + types.size()) {
127 127
128 - log.warn("requested nextId {} could potentially overlap " + 128 + if (log.isWarnEnabled()) {
129 - "with existing registrations {}+{} ", 129 + log.warn("requested nextId {} could potentially overlap " +
130 - id, blockHeadId, types.size()); 130 + "with existing registrations {}+{} ",
131 + id, blockHeadId, types.size(), new RuntimeException());
132 + }
131 } 133 }
132 blocks.add(new RegistrationBlock(this.blockHeadId, types)); 134 blocks.add(new RegistrationBlock(this.blockHeadId, types));
133 types = new ArrayList<>(); 135 types = new ArrayList<>();
......