blob: 8d4f9c3d0f6885a195f3e40d27b088ddabc8ba86 [file] [log] [blame]
Madan Jampani2914e4e2016-09-13 17:48:56 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Madan Jampani2914e4e2016-09-13 17:48:56 -07003 *
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
17package org.onosproject.store.primitives.impl;
18
19import java.util.Map;
20import java.util.concurrent.CompletableFuture;
21
Sithara Punnassery61a80252017-08-07 11:16:08 -070022import org.onosproject.store.primitives.NodeUpdate;
23import org.onosproject.store.primitives.TransactionId;
Madan Jampani2914e4e2016-09-13 17:48:56 -070024import org.onosproject.store.service.AsyncDocumentTree;
25import org.onosproject.store.service.DocumentPath;
26import org.onosproject.store.service.DocumentTreeEvent;
27import org.onosproject.store.service.DocumentTreeListener;
28import org.onosproject.store.service.Serializer;
Sithara Punnassery61a80252017-08-07 11:16:08 -070029import org.onosproject.store.service.TransactionLog;
30import org.onosproject.store.service.Version;
Madan Jampani2914e4e2016-09-13 17:48:56 -070031import org.onosproject.store.service.Versioned;
32
33import com.google.common.collect.Maps;
34
35/**
36 * Default implementation of {@link AsyncDocumentTree}.
37 * <p>
38 * This implementation delegates execution to a backing tree implemented on top of Atomix framework.
39 *
Madan Jampani2914e4e2016-09-13 17:48:56 -070040 * @param <V> tree node value type.
41 */
42public class DefaultDistributedDocumentTree<V> implements AsyncDocumentTree<V> {
43
44 private final String name;
45 private final AsyncDocumentTree<byte[]> backingTree;
46 private final Serializer serializer;
47 private final Map<DocumentTreeListener<V>, InternalBackingDocumentTreeListener> listeners =
48 Maps.newIdentityHashMap();
49
50 DefaultDistributedDocumentTree(String name, AsyncDocumentTree<byte[]> backingTree, Serializer serializer) {
51 this.name = name;
52 this.backingTree = backingTree;
53 this.serializer = serializer;
54 }
55
56 @Override
57 public String name() {
58 return name;
59 }
60
61 @Override
62 public Type primitiveType() {
63 return backingTree.primitiveType();
64 }
65
66 @Override
67 public DocumentPath root() {
68 return backingTree.root();
69 }
70
71 @Override
72 public CompletableFuture<Map<String, Versioned<V>>> getChildren(DocumentPath path) {
73 return backingTree.getChildren(path)
74 .thenApply(map -> Maps.transformValues(map, v -> v.map(serializer::decode)));
75 }
76
77 @Override
78 public CompletableFuture<Versioned<V>> get(DocumentPath path) {
79 return backingTree.get(path)
80 .thenApply(v -> v == null ? null : v.map(serializer::decode));
81 }
82
83 @Override
84 public CompletableFuture<Versioned<V>> set(DocumentPath path, V value) {
85 return backingTree.set(path, serializer.encode(value))
86 .thenApply(v -> v == null ? null : v.map(serializer::decode));
87 }
88
89 @Override
90 public CompletableFuture<Boolean> create(DocumentPath path, V value) {
91 return backingTree.create(path, serializer.encode(value));
92 }
93
94 @Override
Madan Jampani86983282016-09-15 14:55:48 -070095 public CompletableFuture<Boolean> createRecursive(DocumentPath path, V value) {
96 return backingTree.createRecursive(path, serializer.encode(value));
97 }
98
99 @Override
Madan Jampani2914e4e2016-09-13 17:48:56 -0700100 public CompletableFuture<Boolean> replace(DocumentPath path, V newValue, long version) {
101 return backingTree.replace(path, serializer.encode(newValue), version);
102 }
103
104 @Override
105 public CompletableFuture<Boolean> replace(DocumentPath path, V newValue, V currentValue) {
106 return backingTree.replace(path, serializer.encode(newValue), serializer.encode(currentValue));
107 }
108
109 @Override
110 public CompletableFuture<Versioned<V>> removeNode(DocumentPath path) {
111 return backingTree.removeNode(path)
112 .thenApply(v -> v == null ? null : v.map(serializer::decode));
113 }
114
Sithara Punnassery61a80252017-08-07 11:16:08 -0700115
116 @Override
117 public CompletableFuture<Version> begin(TransactionId transactionId) {
118 return backingTree.begin(transactionId);
119 }
120
121 @Override
122 public CompletableFuture<Boolean> prepare(TransactionLog<NodeUpdate<V>> transactionLog) {
123 return backingTree.prepare(transactionLog.map(record -> record.map(serializer::encode)));
124 }
125
126 @Override
127 public CompletableFuture<Void> commit(TransactionId transactionId) {
128 return backingTree.commit(transactionId);
129 }
130
131 @Override
132 public CompletableFuture<Void> rollback(TransactionId transactionId) {
133 return backingTree.rollback(transactionId);
134 }
135
136 @Override
137 public CompletableFuture<Boolean> prepareAndCommit(TransactionLog<NodeUpdate<V>> transactionLog) {
138 return backingTree.prepareAndCommit(transactionLog.map(record -> record.map(serializer::encode)));
139 }
140
141
Madan Jampani2914e4e2016-09-13 17:48:56 -0700142 @Override
143 public CompletableFuture<Void> addListener(DocumentPath path, DocumentTreeListener<V> listener) {
144 synchronized (listeners) {
145 InternalBackingDocumentTreeListener backingListener =
146 listeners.computeIfAbsent(listener, k -> new InternalBackingDocumentTreeListener(listener));
147 return backingTree.addListener(path, backingListener);
148 }
149 }
150
151 @Override
152 public CompletableFuture<Void> removeListener(DocumentTreeListener<V> listener) {
153 synchronized (listeners) {
154 InternalBackingDocumentTreeListener backingListener = listeners.remove(listener);
155 if (backingListener != null) {
156 return backingTree.removeListener(backingListener);
157 } else {
158 return CompletableFuture.completedFuture(null);
159 }
160 }
161 }
162
163 private class InternalBackingDocumentTreeListener implements DocumentTreeListener<byte[]> {
164
165 private final DocumentTreeListener<V> listener;
166
167 InternalBackingDocumentTreeListener(DocumentTreeListener<V> listener) {
168 this.listener = listener;
169 }
170
171 @Override
172 public void event(DocumentTreeEvent<byte[]> event) {
173 listener.event(new DocumentTreeEvent<V>(event.path(),
174 event.type(),
175 event.newValue().map(v -> v.map(serializer::decode)),
176 event.oldValue().map(v -> v.map(serializer::decode))));
177 }
178 }
179}