Madan Jampani
Committed by Gerrit Code Review

StorageService API for creating AsyncDocumentTree primitive

Change-Id: Ib7c3f19beb7b26a5b69161cf972c3c64d0be94b3
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
15 */ 15 */
16 package org.onosproject.vtnrsc.util; 16 package org.onosproject.vtnrsc.util;
17 17
18 +import org.onosproject.store.service.AsyncDocumentTree;
18 import org.onosproject.store.service.Topic; 19 import org.onosproject.store.service.Topic;
19 import org.onosproject.store.service.ConsistentTreeMapBuilder; 20 import org.onosproject.store.service.ConsistentTreeMapBuilder;
20 import org.onosproject.store.service.WorkQueue; 21 import org.onosproject.store.service.WorkQueue;
...@@ -81,4 +82,9 @@ public class VtnStorageServiceAdapter implements StorageService { ...@@ -81,4 +82,9 @@ public class VtnStorageServiceAdapter implements StorageService {
81 public <T> Topic<T> getTopic(String name, Serializer serializer) { 82 public <T> Topic<T> getTopic(String name, Serializer serializer) {
82 return null; 83 return null;
83 } 84 }
85 +
86 + @Override
87 + public <V> AsyncDocumentTree<V> getDocumentTree(String name, Serializer serializer) {
88 + return null;
89 + }
84 } 90 }
......
...@@ -22,9 +22,10 @@ import org.onosproject.store.service.AsyncAtomicValue; ...@@ -22,9 +22,10 @@ import org.onosproject.store.service.AsyncAtomicValue;
22 import org.onosproject.store.service.AsyncConsistentMap; 22 import org.onosproject.store.service.AsyncConsistentMap;
23 import org.onosproject.store.service.AsyncConsistentTreeMap; 23 import org.onosproject.store.service.AsyncConsistentTreeMap;
24 import org.onosproject.store.service.AsyncDistributedSet; 24 import org.onosproject.store.service.AsyncDistributedSet;
25 +import org.onosproject.store.service.AsyncDocumentTree;
25 import org.onosproject.store.service.AsyncLeaderElector; 26 import org.onosproject.store.service.AsyncLeaderElector;
26 -import org.onosproject.store.service.WorkQueue;
27 import org.onosproject.store.service.Serializer; 27 import org.onosproject.store.service.Serializer;
28 +import org.onosproject.store.service.WorkQueue;
28 29
29 /** 30 /**
30 * Interface for entity that can create instances of different distributed primitives. 31 * Interface for entity that can create instances of different distributed primitives.
...@@ -99,6 +100,16 @@ public interface DistributedPrimitiveCreator { ...@@ -99,6 +100,16 @@ public interface DistributedPrimitiveCreator {
99 <E> WorkQueue<E> newWorkQueue(String name, Serializer serializer); 100 <E> WorkQueue<E> newWorkQueue(String name, Serializer serializer);
100 101
101 /** 102 /**
103 + * Creates a new {@code AsyncDocumentTree}.
104 + *
105 + * @param <V> document tree node value type
106 + * @param name tree name
107 + * @param serializer serializer
108 + * @return document tree
109 + */
110 + <V> AsyncDocumentTree<V> newAsyncDocumentTree(String name, Serializer serializer);
111 +
112 + /**
102 * Returns the names of all created {@code AsyncConsistentMap} instances. 113 * Returns the names of all created {@code AsyncConsistentMap} instances.
103 * @return set of {@code AsyncConsistentMap} names 114 * @return set of {@code AsyncConsistentMap} names
104 */ 115 */
......
...@@ -114,12 +114,21 @@ public interface StorageService { ...@@ -114,12 +114,21 @@ public interface StorageService {
114 * @param <E> work element type 114 * @param <E> work element type
115 * @param name work queue name 115 * @param name work queue name
116 * @param serializer serializer 116 * @param serializer serializer
117 - *
118 * @return WorkQueue instance 117 * @return WorkQueue instance
119 */ 118 */
120 <E> WorkQueue<E> getWorkQueue(String name, Serializer serializer); 119 <E> WorkQueue<E> getWorkQueue(String name, Serializer serializer);
121 120
122 /** 121 /**
122 + * Returns an instance of {@code AsyncDocumentTree} with specified name.
123 + *
124 + * @param <V> tree node value type
125 + * @param name document tree name
126 + * @param serializer serializer
127 + * @return AsyncDocumentTree instance
128 + */
129 + <V> AsyncDocumentTree<V> getDocumentTree(String name, Serializer serializer);
130 +
131 + /**
123 * Returns an instance of {@code Topic} with specified name. 132 * Returns an instance of {@code Topic} with specified name.
124 * 133 *
125 * @param <T> topic message type 134 * @param <T> topic message type
......
...@@ -64,7 +64,13 @@ public class StorageServiceAdapter implements StorageService { ...@@ -64,7 +64,13 @@ public class StorageServiceAdapter implements StorageService {
64 return null; 64 return null;
65 } 65 }
66 66
67 + @Override
67 public <V> ConsistentTreeMapBuilder<V> consistentTreeMapBuilder() { 68 public <V> ConsistentTreeMapBuilder<V> consistentTreeMapBuilder() {
68 return null; 69 return null;
69 } 70 }
71 +
72 + @Override
73 + public <V> AsyncDocumentTree<V> getDocumentTree(String name, Serializer serializer) {
74 + return null;
75 + }
70 } 76 }
......
...@@ -106,7 +106,6 @@ public final class CatalystSerializers { ...@@ -106,7 +106,6 @@ public final class CatalystSerializers {
106 serializer.register(DocumentTreeUpdateResult.class, factory); 106 serializer.register(DocumentTreeUpdateResult.class, factory);
107 serializer.register(DocumentTreeUpdateResult.Status.class, factory); 107 serializer.register(DocumentTreeUpdateResult.Status.class, factory);
108 serializer.register(DocumentTreeEvent.class, factory); 108 serializer.register(DocumentTreeEvent.class, factory);
109 - serializer.register(DocumentTreeEvent.Type.class, factory);
110 serializer.register(Maps.immutableEntry("a", "b").getClass(), factory); 109 serializer.register(Maps.immutableEntry("a", "b").getClass(), factory);
111 serializer.register(ImmutableList.of().getClass(), factory); 110 serializer.register(ImmutableList.of().getClass(), factory);
112 111
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
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 +
17 +package org.onosproject.store.primitives.impl;
18 +
19 +import java.util.Map;
20 +import java.util.concurrent.CompletableFuture;
21 +
22 +import org.onosproject.store.service.AsyncDocumentTree;
23 +import org.onosproject.store.service.DocumentPath;
24 +import org.onosproject.store.service.DocumentTreeEvent;
25 +import org.onosproject.store.service.DocumentTreeListener;
26 +import org.onosproject.store.service.Serializer;
27 +import org.onosproject.store.service.Versioned;
28 +
29 +import com.google.common.collect.Maps;
30 +
31 +/**
32 + * Default implementation of {@link AsyncDocumentTree}.
33 + * <p>
34 + * This implementation delegates execution to a backing tree implemented on top of Atomix framework.
35 + *
36 + * @See AtomixDocumentTree
37 + *
38 + * @param <V> tree node value type.
39 + */
40 +public class DefaultDistributedDocumentTree<V> implements AsyncDocumentTree<V> {
41 +
42 + private final String name;
43 + private final AsyncDocumentTree<byte[]> backingTree;
44 + private final Serializer serializer;
45 + private final Map<DocumentTreeListener<V>, InternalBackingDocumentTreeListener> listeners =
46 + Maps.newIdentityHashMap();
47 +
48 + DefaultDistributedDocumentTree(String name, AsyncDocumentTree<byte[]> backingTree, Serializer serializer) {
49 + this.name = name;
50 + this.backingTree = backingTree;
51 + this.serializer = serializer;
52 + }
53 +
54 + @Override
55 + public String name() {
56 + return name;
57 + }
58 +
59 + @Override
60 + public Type primitiveType() {
61 + return backingTree.primitiveType();
62 + }
63 +
64 + @Override
65 + public DocumentPath root() {
66 + return backingTree.root();
67 + }
68 +
69 + @Override
70 + public CompletableFuture<Map<String, Versioned<V>>> getChildren(DocumentPath path) {
71 + return backingTree.getChildren(path)
72 + .thenApply(map -> Maps.transformValues(map, v -> v.map(serializer::decode)));
73 + }
74 +
75 + @Override
76 + public CompletableFuture<Versioned<V>> get(DocumentPath path) {
77 + return backingTree.get(path)
78 + .thenApply(v -> v == null ? null : v.map(serializer::decode));
79 + }
80 +
81 + @Override
82 + public CompletableFuture<Versioned<V>> set(DocumentPath path, V value) {
83 + return backingTree.set(path, serializer.encode(value))
84 + .thenApply(v -> v == null ? null : v.map(serializer::decode));
85 + }
86 +
87 + @Override
88 + public CompletableFuture<Boolean> create(DocumentPath path, V value) {
89 + return backingTree.create(path, serializer.encode(value));
90 + }
91 +
92 + @Override
93 + public CompletableFuture<Boolean> replace(DocumentPath path, V newValue, long version) {
94 + return backingTree.replace(path, serializer.encode(newValue), version);
95 + }
96 +
97 + @Override
98 + public CompletableFuture<Boolean> replace(DocumentPath path, V newValue, V currentValue) {
99 + return backingTree.replace(path, serializer.encode(newValue), serializer.encode(currentValue));
100 + }
101 +
102 + @Override
103 + public CompletableFuture<Versioned<V>> removeNode(DocumentPath path) {
104 + return backingTree.removeNode(path)
105 + .thenApply(v -> v == null ? null : v.map(serializer::decode));
106 + }
107 +
108 + @Override
109 + public CompletableFuture<Void> addListener(DocumentPath path, DocumentTreeListener<V> listener) {
110 + synchronized (listeners) {
111 + InternalBackingDocumentTreeListener backingListener =
112 + listeners.computeIfAbsent(listener, k -> new InternalBackingDocumentTreeListener(listener));
113 + return backingTree.addListener(path, backingListener);
114 + }
115 + }
116 +
117 + @Override
118 + public CompletableFuture<Void> removeListener(DocumentTreeListener<V> listener) {
119 + synchronized (listeners) {
120 + InternalBackingDocumentTreeListener backingListener = listeners.remove(listener);
121 + if (backingListener != null) {
122 + return backingTree.removeListener(backingListener);
123 + } else {
124 + return CompletableFuture.completedFuture(null);
125 + }
126 + }
127 + }
128 +
129 + private class InternalBackingDocumentTreeListener implements DocumentTreeListener<byte[]> {
130 +
131 + private final DocumentTreeListener<V> listener;
132 +
133 + InternalBackingDocumentTreeListener(DocumentTreeListener<V> listener) {
134 + this.listener = listener;
135 + }
136 +
137 + @Override
138 + public void event(DocumentTreeEvent<byte[]> event) {
139 + listener.event(new DocumentTreeEvent<V>(event.path(),
140 + event.type(),
141 + event.newValue().map(v -> v.map(serializer::decode)),
142 + event.oldValue().map(v -> v.map(serializer::decode))));
143 + }
144 + }
145 +}
...@@ -29,6 +29,7 @@ import org.onosproject.store.service.AsyncAtomicValue; ...@@ -29,6 +29,7 @@ import org.onosproject.store.service.AsyncAtomicValue;
29 import org.onosproject.store.service.AsyncConsistentMap; 29 import org.onosproject.store.service.AsyncConsistentMap;
30 import org.onosproject.store.service.AsyncConsistentTreeMap; 30 import org.onosproject.store.service.AsyncConsistentTreeMap;
31 import org.onosproject.store.service.AsyncDistributedSet; 31 import org.onosproject.store.service.AsyncDistributedSet;
32 +import org.onosproject.store.service.AsyncDocumentTree;
32 import org.onosproject.store.service.AsyncLeaderElector; 33 import org.onosproject.store.service.AsyncLeaderElector;
33 import org.onosproject.store.service.Serializer; 34 import org.onosproject.store.service.Serializer;
34 import org.onosproject.store.service.WorkQueue; 35 import org.onosproject.store.service.WorkQueue;
...@@ -108,6 +109,11 @@ public class FederatedDistributedPrimitiveCreator implements DistributedPrimitiv ...@@ -108,6 +109,11 @@ public class FederatedDistributedPrimitiveCreator implements DistributedPrimitiv
108 } 109 }
109 110
110 @Override 111 @Override
112 + public <V> AsyncDocumentTree<V> newAsyncDocumentTree(String name, Serializer serializer) {
113 + return getCreator(name).newAsyncDocumentTree(name, serializer);
114 + }
115 +
116 + @Override
111 public Set<String> getAsyncConsistentMapNames() { 117 public Set<String> getAsyncConsistentMapNames() {
112 return members.values() 118 return members.values()
113 .stream() 119 .stream()
......
...@@ -43,6 +43,7 @@ import org.onosproject.store.primitives.TransactionId; ...@@ -43,6 +43,7 @@ import org.onosproject.store.primitives.TransactionId;
43 import org.onosproject.store.serializers.KryoNamespaces; 43 import org.onosproject.store.serializers.KryoNamespaces;
44 import org.onosproject.store.service.AsyncAtomicValue; 44 import org.onosproject.store.service.AsyncAtomicValue;
45 import org.onosproject.store.service.AsyncConsistentMap; 45 import org.onosproject.store.service.AsyncConsistentMap;
46 +import org.onosproject.store.service.AsyncDocumentTree;
46 import org.onosproject.store.service.AtomicCounterBuilder; 47 import org.onosproject.store.service.AtomicCounterBuilder;
47 import org.onosproject.store.service.AtomicValueBuilder; 48 import org.onosproject.store.service.AtomicValueBuilder;
48 import org.onosproject.store.service.ConsistentMap; 49 import org.onosproject.store.service.ConsistentMap;
...@@ -180,6 +181,12 @@ public class StorageManager implements StorageService, StorageAdminService { ...@@ -180,6 +181,12 @@ public class StorageManager implements StorageService, StorageAdminService {
180 } 181 }
181 182
182 @Override 183 @Override
184 + public <V> AsyncDocumentTree<V> getDocumentTree(String name, Serializer serializer) {
185 + checkPermission(STORAGE_WRITE);
186 + return federatedPrimitiveCreator.newAsyncDocumentTree(name, serializer);
187 + }
188 +
189 + @Override
183 public List<MapInfo> getMapInfo() { 190 public List<MapInfo> getMapInfo() {
184 return listMapInfo(federatedPrimitiveCreator); 191 return listMapInfo(federatedPrimitiveCreator);
185 } 192 }
......
...@@ -41,6 +41,7 @@ import org.onosproject.store.primitives.DistributedPrimitiveCreator; ...@@ -41,6 +41,7 @@ import org.onosproject.store.primitives.DistributedPrimitiveCreator;
41 import org.onosproject.store.primitives.resources.impl.AtomixConsistentMap; 41 import org.onosproject.store.primitives.resources.impl.AtomixConsistentMap;
42 import org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMap; 42 import org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMap;
43 import org.onosproject.store.primitives.resources.impl.AtomixCounter; 43 import org.onosproject.store.primitives.resources.impl.AtomixCounter;
44 +import org.onosproject.store.primitives.resources.impl.AtomixDocumentTree;
44 import org.onosproject.store.primitives.resources.impl.AtomixLeaderElector; 45 import org.onosproject.store.primitives.resources.impl.AtomixLeaderElector;
45 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueue; 46 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueue;
46 import org.onosproject.store.serializers.KryoNamespaces; 47 import org.onosproject.store.serializers.KryoNamespaces;
...@@ -49,6 +50,7 @@ import org.onosproject.store.service.AsyncAtomicValue; ...@@ -49,6 +50,7 @@ import org.onosproject.store.service.AsyncAtomicValue;
49 import org.onosproject.store.service.AsyncConsistentMap; 50 import org.onosproject.store.service.AsyncConsistentMap;
50 import org.onosproject.store.service.AsyncConsistentTreeMap; 51 import org.onosproject.store.service.AsyncConsistentTreeMap;
51 import org.onosproject.store.service.AsyncDistributedSet; 52 import org.onosproject.store.service.AsyncDistributedSet;
53 +import org.onosproject.store.service.AsyncDocumentTree;
52 import org.onosproject.store.service.AsyncLeaderElector; 54 import org.onosproject.store.service.AsyncLeaderElector;
53 import org.onosproject.store.service.DistributedPrimitive.Status; 55 import org.onosproject.store.service.DistributedPrimitive.Status;
54 import org.onosproject.store.service.PartitionClientInfo; 56 import org.onosproject.store.service.PartitionClientInfo;
...@@ -191,6 +193,12 @@ public class StoragePartitionClient implements DistributedPrimitiveCreator, Mana ...@@ -191,6 +193,12 @@ public class StoragePartitionClient implements DistributedPrimitiveCreator, Mana
191 } 193 }
192 194
193 @Override 195 @Override
196 + public <V> AsyncDocumentTree<V> newAsyncDocumentTree(String name, Serializer serializer) {
197 + AtomixDocumentTree atomixDocumentTree = client.getResource(name, AtomixDocumentTree.class).join();
198 + return new DefaultDistributedDocumentTree<>(name, atomixDocumentTree, serializer);
199 + }
200 +
201 + @Override
194 public AsyncLeaderElector newAsyncLeaderElector(String name) { 202 public AsyncLeaderElector newAsyncLeaderElector(String name) {
195 AtomixLeaderElector leaderElector = client.getResource(name, AtomixLeaderElector.class) 203 AtomixLeaderElector leaderElector = client.getResource(name, AtomixLeaderElector.class)
196 .thenCompose(AtomixLeaderElector::setupCache) 204 .thenCompose(AtomixLeaderElector::setupCache)
......
...@@ -65,7 +65,7 @@ public class AtomixDocumentTreeState ...@@ -65,7 +65,7 @@ public class AtomixDocumentTreeState
65 65
66 private final Logger log = getLogger(getClass()); 66 private final Logger log = getLogger(getClass());
67 private final Map<Long, Commit<? extends Listen>> listeners = new HashMap<>(); 67 private final Map<Long, Commit<? extends Listen>> listeners = new HashMap<>();
68 - private final AtomicLong versionCounter = new AtomicLong(0); 68 + private AtomicLong versionCounter = new AtomicLong(0);
69 private final DocumentTree<TreeNodeValue> docTree = new DefaultDocumentTree<>(versionCounter::incrementAndGet); 69 private final DocumentTree<TreeNodeValue> docTree = new DefaultDocumentTree<>(versionCounter::incrementAndGet);
70 70
71 public AtomixDocumentTreeState(Properties properties) { 71 public AtomixDocumentTreeState(Properties properties) {
...@@ -79,7 +79,7 @@ public class AtomixDocumentTreeState ...@@ -79,7 +79,7 @@ public class AtomixDocumentTreeState
79 79
80 @Override 80 @Override
81 public void install(SnapshotReader reader) { 81 public void install(SnapshotReader reader) {
82 - versionCounter.set(reader.readLong()); 82 + versionCounter = new AtomicLong(reader.readLong());
83 } 83 }
84 84
85 @Override 85 @Override
...@@ -101,8 +101,7 @@ public class AtomixDocumentTreeState ...@@ -101,8 +101,7 @@ public class AtomixDocumentTreeState
101 commit.close(); 101 commit.close();
102 return; 102 return;
103 } 103 }
104 - commit.session() 104 + commit.session().onStateChange(
105 - .onStateChange(
106 state -> { 105 state -> {
107 if (state == ServerSession.State.CLOSED 106 if (state == ServerSession.State.CLOSED
108 || state == ServerSession.State.EXPIRED) { 107 || state == ServerSession.State.EXPIRED) {
...@@ -262,11 +261,10 @@ public class AtomixDocumentTreeState ...@@ -262,11 +261,10 @@ public class AtomixDocumentTreeState
262 result.created() ? Type.CREATED : result.newValue() == null ? Type.DELETED : Type.UPDATED, 261 result.created() ? Type.CREATED : result.newValue() == null ? Type.DELETED : Type.UPDATED,
263 Optional.ofNullable(result.newValue()), 262 Optional.ofNullable(result.newValue()),
264 Optional.ofNullable(result.oldValue())); 263 Optional.ofNullable(result.oldValue()));
265 - Object message = ImmutableList.of(event); 264 + listeners.values()
266 - listeners.values().forEach(commit -> { 265 + .forEach(commit -> commit.session()
267 - commit.session().publish(AtomixDocumentTree.CHANGE_SUBJECT, message); 266 + .publish(AtomixDocumentTree.CHANGE_SUBJECT,
268 - System.out.println("Sent " + message + " to " + commit.session().id()); 267 + ImmutableList.of(event)));
269 - });
270 } 268 }
271 269
272 @Override 270 @Override
......
...@@ -320,10 +320,6 @@ public class AtomixDocumentTreeTest extends AtomixTestBase { ...@@ -320,10 +320,6 @@ public class AtomixDocumentTreeTest extends AtomixTestBase {
320 } 320 }
321 } 321 }
322 322
323 - public boolean eventReceived() {
324 - return !queue.isEmpty();
325 - }
326 -
327 public DocumentTreeEvent<byte[]> event() throws InterruptedException { 323 public DocumentTreeEvent<byte[]> event() throws InterruptedException {
328 return queue.take(); 324 return queue.take();
329 } 325 }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
15 */ 15 */
16 package org.onosproject.pcelabelstore.util; 16 package org.onosproject.pcelabelstore.util;
17 17
18 +import org.onosproject.store.service.AsyncDocumentTree;
18 import org.onosproject.store.service.AtomicCounterBuilder; 19 import org.onosproject.store.service.AtomicCounterBuilder;
19 import org.onosproject.store.service.AtomicValueBuilder; 20 import org.onosproject.store.service.AtomicValueBuilder;
20 import org.onosproject.store.service.ConsistentMapBuilder; 21 import org.onosproject.store.service.ConsistentMapBuilder;
...@@ -83,4 +84,9 @@ public class StorageServiceAdapter implements StorageService { ...@@ -83,4 +84,9 @@ public class StorageServiceAdapter implements StorageService {
83 // TODO Auto-generated method stub 84 // TODO Auto-generated method stub
84 return null; 85 return null;
85 } 86 }
87 +
88 + @Override
89 + public <V> AsyncDocumentTree<V> getDocumentTree(String name, Serializer serializer) {
90 + return null;
91 + }
86 } 92 }
......