blob: b32364e771f572624fc329f3610492a4f3eba840 [file] [log] [blame]
Sithara Punnassery9306e6b2017-02-06 15:38:19 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Sithara Punnassery9306e6b2017-02-06 15:38:19 -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 */
16package org.onosproject.config.impl;
17
Sithara Punnassery06208792017-02-10 16:25:29 -080018import com.google.common.annotations.Beta;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.apache.felix.scr.annotations.Service;
25import org.onlab.util.KryoNamespace;
26import org.onosproject.config.DynamicConfigEvent;
27import org.onosproject.config.DynamicConfigStore;
28import org.onosproject.config.DynamicConfigStoreDelegate;
29import org.onosproject.config.FailedException;
30import org.onosproject.config.Filter;
Henry Yu5c54e772017-04-19 14:13:56 -040031import org.onosproject.config.ResourceIdParser;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080032import org.onosproject.store.AbstractStore;
33import org.onosproject.store.serializers.KryoNamespaces;
34import org.onosproject.store.service.AsyncDocumentTree;
35import org.onosproject.store.service.ConsistentMap;
36import org.onosproject.store.service.DocumentPath;
37import org.onosproject.store.service.DocumentTreeEvent;
38import org.onosproject.store.service.DocumentTreeListener;
Sithara Punnassery44e2a702017-03-06 15:38:10 -080039import org.onosproject.store.service.IllegalDocumentModificationException;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080040import org.onosproject.store.service.MapEvent;
41import org.onosproject.store.service.MapEventListener;
Sithara Punnassery44e2a702017-03-06 15:38:10 -080042import org.onosproject.store.service.NoSuchDocumentPathException;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080043import org.onosproject.store.service.Serializer;
44import org.onosproject.store.service.StorageService;
45import org.onosproject.store.service.Versioned;
Sithara Punnassery44e2a702017-03-06 15:38:10 -080046import org.onosproject.yang.model.DataNode;
47import org.onosproject.yang.model.InnerNode;
48import org.onosproject.yang.model.KeyLeaf;
49import org.onosproject.yang.model.LeafListKey;
50import org.onosproject.yang.model.LeafNode;
51import org.onosproject.yang.model.ListKey;
52import org.onosproject.yang.model.NodeKey;
53import org.onosproject.yang.model.ResourceId;
54import org.onosproject.yang.model.SchemaId;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080055import org.slf4j.Logger;
56import org.slf4j.LoggerFactory;
Henry Yu5c54e772017-04-19 14:13:56 -040057
58import java.math.BigInteger;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080059import java.util.Map;
60import java.util.concurrent.CompletableFuture;
Sithara Punnassery4b091dc2017-03-02 17:22:40 -080061import java.util.concurrent.ExecutionException;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080062
Sithara Punnassery44e2a702017-03-06 15:38:10 -080063import static org.onosproject.config.DynamicConfigEvent.Type.NODE_ADDED;
Sithara Punnassery44e2a702017-03-06 15:38:10 -080064import static org.onosproject.config.DynamicConfigEvent.Type.NODE_DELETED;
Henry Yu5c54e772017-04-19 14:13:56 -040065import static org.onosproject.config.DynamicConfigEvent.Type.NODE_UPDATED;
Sithara Punnassery44e2a702017-03-06 15:38:10 -080066import static org.onosproject.config.DynamicConfigEvent.Type.UNKNOWN_OPRN;
67
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080068/**
69 * Implementation of the dynamic config store.
70 */
Sithara Punnassery06208792017-02-10 16:25:29 -080071@Beta
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080072@Component(immediate = true)
73@Service
74public class DistributedDynamicConfigStore
75 extends AbstractStore<DynamicConfigEvent, DynamicConfigStoreDelegate>
76 implements DynamicConfigStore {
77 private final Logger log = LoggerFactory.getLogger(getClass());
78 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
79 protected StorageService storageService;
80 private AsyncDocumentTree<DataNode.Type> keystore;
Sithara Punnassery4b091dc2017-03-02 17:22:40 -080081 private ConsistentMap<String, LeafNode> objectStore;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080082 private final DocumentTreeListener<DataNode.Type> klistener = new InternalDocTreeListener();
Sithara Punnassery4b091dc2017-03-02 17:22:40 -080083 private final MapEventListener<String, LeafNode> olistener = new InternalMapListener();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080084
85 @Activate
86 public void activateStore() {
87 KryoNamespace.Builder kryoBuilder = new KryoNamespace.Builder()
88 .register(KryoNamespaces.BASIC)
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080089 .register(java.lang.Class.class)
90 .register(DataNode.Type.class)
91 .register(LeafNode.class)
92 .register(InnerNode.class)
93 .register(ResourceId.class)
94 .register(NodeKey.class)
95 .register(SchemaId.class)
Sithara Punnassery43833e12017-03-14 16:29:19 -070096 .register(LeafListKey.class)
97 .register(ListKey.class)
98 .register(KeyLeaf.class)
Henry Yu5c54e772017-04-19 14:13:56 -040099 .register(BigInteger.class)
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800100 .register(java.util.LinkedHashMap.class);
101 keystore = storageService.<DataNode.Type>documentTreeBuilder()
102 .withSerializer(Serializer.using(kryoBuilder.build()))
103 .withName("config-key-store")
104 .withRelaxedReadConsistency()
105 .buildDocumentTree();
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800106 objectStore = storageService.<String, LeafNode>consistentMapBuilder()
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800107 .withSerializer(Serializer.using(kryoBuilder.build()))
108 .withName("config-object-store")
109 .withRelaxedReadConsistency()
110 .build();
111 keystore.addListener(klistener);
112 objectStore.addListener(olistener);
113 log.info("DyanmicConfig Store Active");
114 }
115
116 @Deactivate
117 public void deactivateStore() {
118 keystore.removeListener(klistener);
119 objectStore.removeListener(olistener);
120 log.info("DyanmicConfig Store Stopped");
121 }
122
123 @Override
124 public CompletableFuture<Boolean>
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700125 addNode(ResourceId complete, DataNode node) {
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800126 CompletableFuture<Boolean> eventFuture = CompletableFuture.completedFuture(true);
Sithara Punnasserybb644902017-03-16 22:08:29 -0700127 String spath = ResourceIdParser.parseResId(complete);
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800128 if (spath == null) {
129 throw new FailedException("Invalid RsourceId, cannot create Node");
130 }
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700131 if (spath.compareTo(ResourceIdParser.ROOT) != 0) {
132 if (completeVersioned(keystore.get(DocumentPath.from(spath))) == null) {
133 throw new FailedException("Node or parent doesnot exist");
134 }
Sithara Punnasserybb644902017-03-16 22:08:29 -0700135 }
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800136 spath = ResourceIdParser.appendNodeKey(spath, node.key());
137 parseNode(spath, node);
138 return eventFuture;
139 }
140
141 private void parseNode(String path, DataNode node) {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700142 if (completeVersioned(keystore.get(DocumentPath.from(path))) != null) {
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800143 throw new FailedException("Requested node already present in the" +
Henry Yu5c54e772017-04-19 14:13:56 -0400144 " store, please use an update method");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800145 }
146 if (node.type() == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
147 addLeaf(path, (LeafNode) node);
148 } else if (node.type() == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
149 path = ResourceIdParser.appendLeafList(path, (LeafListKey) node.key());
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700150 if (completeVersioned(keystore.get(DocumentPath.from(path))) != null) {
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800151 throw new FailedException("Requested node already present in the" +
Henry Yu5c54e772017-04-19 14:13:56 -0400152 " store, please use an update method");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800153 }
154 addLeaf(path, (LeafNode) node);
155 } else if (node.type() == DataNode.Type.SINGLE_INSTANCE_NODE) {
156 traverseInner(path, (InnerNode) node);
157 } else if (node.type() == DataNode.Type.MULTI_INSTANCE_NODE) {
158 path = ResourceIdParser.appendKeyList(path, (ListKey) node.key());
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700159 if (completeVersioned(keystore.get(DocumentPath.from(path))) != null) {
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800160 throw new FailedException("Requested node already present in the" +
Henry Yu5c54e772017-04-19 14:13:56 -0400161 " store, please use an update method");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800162 }
163 traverseInner(path, (InnerNode) node);
164 } else {
165 throw new FailedException("Invalid node type");
166 }
167 }
168
169 private void traverseInner(String path, InnerNode node) {
170 addKey(path, node.type());
171 Map<NodeKey, DataNode> entries = node.childNodes();
172 if (entries.size() == 0) {
Henry Yu5c54e772017-04-19 14:13:56 -0400173 return;
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800174 }
175 entries.forEach((k, v) -> {
176 String tempPath;
177 tempPath = ResourceIdParser.appendNodeKey(path, v.key());
178 if (v.type() == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
179 addLeaf(tempPath, (LeafNode) v);
180 } else if (v.type() == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
181 tempPath = ResourceIdParser.appendLeafList(tempPath, (LeafListKey) v.key());
182 addLeaf(tempPath, (LeafNode) v);
183 } else if (v.type() == DataNode.Type.SINGLE_INSTANCE_NODE) {
184 traverseInner(tempPath, (InnerNode) v);
185 } else if (v.type() == DataNode.Type.MULTI_INSTANCE_NODE) {
186 tempPath = ResourceIdParser.appendKeyList(tempPath, (ListKey) v.key());
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700187 traverseInner(tempPath, (InnerNode) v);
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800188 } else {
189 throw new FailedException("Invalid node type");
190 }
191 });
192 }
193
194 private Boolean addLeaf(String path, LeafNode node) {
195 objectStore.put(path, node);
196 return addKey(path, node.type());
197 }
198
199 private Boolean addKey(String path, DataNode.Type type) {
Sithara Punnasseryc70b7e52017-08-10 14:28:08 -0700200 if (completeVersioned(keystore.get(DocumentPath.from(path))) != null) {
201 completeVersioned(keystore.set(DocumentPath.from(path), type));
202 return true;
203 }
204 return complete(keystore.create(DocumentPath.from(path), type));
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800205 }
206
207 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800208 public CompletableFuture<DataNode> readNode(ResourceId path, Filter filter) {
209 CompletableFuture<DataNode> eventFuture = CompletableFuture.completedFuture(null);
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800210 String spath = ResourceIdParser.parseResId(path);
211 DocumentPath dpath = DocumentPath.from(spath);
212 DataNode.Type type = null;
213 CompletableFuture<Versioned<DataNode.Type>> ret = keystore.get(dpath);
214 type = completeVersioned(ret);
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800215 if (type == null) {
216 throw new FailedException("Requested node or some of the parents" +
Henry Yu5c54e772017-04-19 14:13:56 -0400217 "are not present in the requested path");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800218 }
219 DataNode retVal = null;
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800220 if (type == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
221 retVal = readLeaf(spath);
222 } else if (type == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
223 retVal = readLeaf(spath);
224 } else if (type == DataNode.Type.SINGLE_INSTANCE_NODE) {
225 NodeKey key = ResourceIdParser.getInstanceKey(path);
226 if (key == null) {
227 throw new FailedException("Key type did not match node type");
228 }
229 DataNode.Builder superBldr = InnerNode
230 .builder(key.schemaId().name(), key.schemaId().namespace())
231 .type(type);
232 readInner(superBldr, spath);
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800233 retVal = superBldr.build();
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800234 } else if (type == DataNode.Type.MULTI_INSTANCE_NODE) {
235 NodeKey key = ResourceIdParser.getMultiInstanceKey(path);
236 if (key == null) {
237 throw new FailedException("Key type did not match node type");
238 }
239 DataNode.Builder superBldr = InnerNode
240 .builder(key.schemaId().name(), key.schemaId().namespace())
241 .type(type);
242 for (KeyLeaf keyLeaf : ((ListKey) key).keyLeafs()) {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700243 //String tempPath = ResourceIdParser.appendKeyLeaf(spath, keyLeaf);
244 //LeafNode lfnd = readLeaf(tempPath);
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800245 superBldr.addKeyLeaf(keyLeaf.leafSchema().name(),
Henry Yu5c54e772017-04-19 14:13:56 -0400246 keyLeaf.leafSchema().namespace(), String.valueOf(keyLeaf.leafValue()));
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800247 }
248 readInner(superBldr, spath);
249 retVal = superBldr.build();
250 } else {
251 throw new FailedException("Invalid node type");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800252 }
253 if (retVal != null) {
254 eventFuture = CompletableFuture.completedFuture(retVal);
255 } else {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700256 log.info("STORE: Failed to READ node");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800257 }
258 return eventFuture;
259 }
260
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800261 private void readInner(DataNode.Builder superBldr, String spath) {
262 CompletableFuture<Map<String, Versioned<DataNode.Type>>> ret = keystore.getChildren(
263 DocumentPath.from(spath));
264 Map<String, Versioned<DataNode.Type>> entries = null;
265 entries = complete(ret);
Sithara Punnassery18ffcc72017-05-18 14:24:30 -0700266 if ((entries != null) && (!entries.isEmpty())) {
267 entries.forEach((k, v) -> {
268 String[] names = k.split(ResourceIdParser.NM_CHK);
269 String name = names[0];
270 String nmSpc = ResourceIdParser.getNamespace(names[1]);
271 String keyVal = ResourceIdParser.getKeyVal(names[1]);
272 DataNode.Type type = v.value();
273 String tempPath = ResourceIdParser.appendNodeKey(spath, name, nmSpc);
274 if (type == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
275 superBldr.createChildBuilder(name, nmSpc, readLeaf(tempPath).value())
276 .type(type)
277 .exitNode();
278 } else if (type == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
279 String mlpath = ResourceIdParser.appendLeafList(tempPath, keyVal);
280 LeafNode lfnode = readLeaf(mlpath);
281 superBldr.createChildBuilder(name, nmSpc, lfnode.value())
282 .type(type)
283 .addLeafListValue(lfnode.value())
284 .exitNode();
285 //TODO this alone should be sufficient and take the nm, nmspc too
286 } else if (type == DataNode.Type.SINGLE_INSTANCE_NODE) {
287 DataNode.Builder tempBldr = superBldr.createChildBuilder(name, nmSpc)
288 .type(type);
289 readInner(tempBldr, tempPath);
290 } else if (type == DataNode.Type.MULTI_INSTANCE_NODE) {
291 DataNode.Builder tempBldr = superBldr.createChildBuilder(name, nmSpc)
292 .type(type);
293 tempPath = ResourceIdParser.appendMultiInstKey(tempPath, k);
294 String[] keys = k.split(ResourceIdParser.KEY_CHK);
295 for (int i = 1; i < keys.length; i++) {
296 //String curKey = ResourceIdParser.appendKeyLeaf(tempPath, keys[i]);
297 //LeafNode lfnd = readLeaf(curKey);
298 String[] keydata = keys[i].split(ResourceIdParser.NM_CHK);
299 tempBldr.addKeyLeaf(keydata[0], keydata[1], keydata[2]);
300 }
301 readInner(tempBldr, tempPath);
302 } else {
303 throw new FailedException("Invalid node type");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800304 }
Sithara Punnassery18ffcc72017-05-18 14:24:30 -0700305 });
306 }
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800307 superBldr.exitNode();
308 }
309
310 private LeafNode readLeaf(String path) {
311 return objectStore.get(path).value();
312 }
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700313
Sithara Punnassery0da1a9c2017-05-17 16:16:22 -0700314 private void parseForUpdate(String path, DataNode node) {
315 if (node.type() == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
316 addLeaf(path, (LeafNode) node);
317 } else if (node.type() == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
318 path = ResourceIdParser.appendLeafList(path, (LeafListKey) node.key());
319 addLeaf(path, (LeafNode) node);
320 } else if (node.type() == DataNode.Type.SINGLE_INSTANCE_NODE) {
321 traverseInner(path, (InnerNode) node);
322 } else if (node.type() == DataNode.Type.MULTI_INSTANCE_NODE) {
323 path = ResourceIdParser.appendKeyList(path, (ListKey) node.key());
324 traverseInner(path, (InnerNode) node);
325 } else {
326 throw new FailedException("Invalid node type");
327 }
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800328 }
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700329
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800330 @Override
Sithara Punnassery0da1a9c2017-05-17 16:16:22 -0700331 public CompletableFuture<Boolean> updateNode(ResourceId complete, DataNode node) {
332 CompletableFuture<Boolean> eventFuture = CompletableFuture.completedFuture(true);
Sithara Punnassery0da1a9c2017-05-17 16:16:22 -0700333 String spath = ResourceIdParser.parseResId(complete);
334 if (spath == null) {
335 throw new FailedException("Invalid RsourceId, cannot update Node");
336 }
337 if (spath.compareTo(ResourceIdParser.ROOT) != 0) {
338 if (completeVersioned(keystore.get(DocumentPath.from(spath))) == null) {
339 throw new FailedException("Node or parent doesnot exist, cannot update");
340 }
341 }
342 spath = ResourceIdParser.appendNodeKey(spath, node.key());
343 parseForUpdate(spath, node);
344 return eventFuture;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800345 }
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700346
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800347 @Override
Sithara Punnassery18ffcc72017-05-18 14:24:30 -0700348 public CompletableFuture<Boolean> nodeExist(ResourceId complete) {
349 Boolean stat = true;
Sithara Punnassery18ffcc72017-05-18 14:24:30 -0700350 String spath = ResourceIdParser.parseResId(complete);
351 if (spath == null) {
352 stat = false;
353 } else if (completeVersioned(keystore.get(DocumentPath.from(spath))) == null) {
354 stat = false;
355 }
356 return CompletableFuture.completedFuture(stat);
357 }
358
359 @Override
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800360 public CompletableFuture<Boolean> replaceNode(ResourceId path, DataNode node) {
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800361 throw new FailedException("Not yet implemented");
362 }
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700363
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800364 @Override
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800365 public CompletableFuture<Boolean> deleteNode(ResourceId path) {
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800366 throw new FailedException("Not yet implemented");
367 }
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800368
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700369 private void deleteInner(String spath) {
370 CompletableFuture<Map<String, Versioned<DataNode.Type>>> ret = keystore.getChildren(
371 DocumentPath.from(spath));
372 Map<String, Versioned<DataNode.Type>> entries = null;
373 entries = complete(ret);
Sithara Punnassery18ffcc72017-05-18 14:24:30 -0700374 if ((entries != null) && (!entries.isEmpty())) {
375 entries.forEach((k, v) -> {
376 String[] names = k.split(ResourceIdParser.NM_CHK);
377 String name = names[0];
378 String nmSpc = ResourceIdParser.getNamespace(names[1]);
379 String keyVal = ResourceIdParser.getKeyVal(names[1]);
380 DataNode.Type type = v.value();
381 String tempPath = ResourceIdParser.appendNodeKey(spath, name, nmSpc);
382 if (type == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
383 removeLeaf(tempPath);
384 } else if (type == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
385 String mlpath = ResourceIdParser.appendLeafList(tempPath, keyVal);
386 removeLeaf(mlpath);
387 } else if (type == DataNode.Type.SINGLE_INSTANCE_NODE) {
388 deleteInner(tempPath);
389 } else if (type == DataNode.Type.MULTI_INSTANCE_NODE) {
390 tempPath = ResourceIdParser.appendMultiInstKey(tempPath, k);
391 deleteInner(tempPath);
392 } else {
393 throw new FailedException("Invalid node type");
394 }
395 });
396 }
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700397 keystore.removeNode(DocumentPath.from(spath));
398 }
399
400 private void removeLeaf(String path) {
401 keystore.removeNode(DocumentPath.from(path));
402 objectStore.remove(path);
403 }
404
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800405 @Override
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800406 public CompletableFuture<Boolean> deleteNodeRecursive(ResourceId path) {
407 String spath = ResourceIdParser.parseResId(path);
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700408 if (spath == null) {
Sithara Punnasserybc9edb12017-07-20 14:32:33 -0700409 throw new FailedException("Invalid RsourceId, cannot delete Node");
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700410 }
411 if (spath.compareTo(ResourceIdParser.ROOT) == 0) {
412 throw new FailedException("Cannot delete Root");
413 }
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800414 DocumentPath dpath = DocumentPath.from(spath);
415 DataNode.Type type = null;
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700416 CompletableFuture<Versioned<DataNode.Type>> ret = keystore.get(dpath);
417 type = completeVersioned(ret);
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800418 if (type == null) {
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700419 throw new FailedException("Cannot delete, Requested node or some of the parents" +
Henry Yu5c54e772017-04-19 14:13:56 -0400420 "are not present in the requested path");
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800421 }
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700422 DataNode retVal = null;
423 if (type == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
424 removeLeaf(spath);
425 } else if (type == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
426 removeLeaf(spath);
427 } else if (type == DataNode.Type.SINGLE_INSTANCE_NODE) {
428 deleteInner(spath);
429 } else if (type == DataNode.Type.MULTI_INSTANCE_NODE) {
430 deleteInner(spath);
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800431 } else {
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700432 throw new FailedException("Invalid node type");
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800433 }
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700434 return CompletableFuture.completedFuture(true);
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800435 }
436
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800437 public class InternalDocTreeListener implements DocumentTreeListener<DataNode.Type> {
438 @Override
439 public void event(DocumentTreeEvent<DataNode.Type> event) {
440 DynamicConfigEvent.Type type;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800441 ResourceId path;
442 switch (event.type()) {
443 case CREATED:
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800444 type = NODE_ADDED;
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700445 //log.info("NODE added in store");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800446 break;
447 case UPDATED:
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700448 //log.info("NODE updated in store");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800449 type = NODE_UPDATED;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800450 break;
451 case DELETED:
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700452 //log.info("NODE deleted in store");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800453 type = NODE_DELETED;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800454 break;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800455 default:
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700456 //log.info("UNKNOWN operation in store");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800457 type = UNKNOWN_OPRN;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800458 }
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800459 path = ResourceIdParser.getResId(event.path().pathElements());
460 notifyDelegate(new DynamicConfigEvent(type, path));
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800461 }
462 }
463
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800464 public class InternalMapListener implements MapEventListener<String, LeafNode> {
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800465 @Override
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800466 public void event(MapEvent<String, LeafNode> event) {
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800467 switch (event.type()) {
468 case INSERT:
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800469 //log.info("NODE created in store");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800470 break;
471 case UPDATE:
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800472 //log.info("NODE updated in store");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800473 break;
474 case REMOVE:
475 default:
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800476 //log.info("NODE removed in store");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800477 break;
478 }
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800479 }
480 }
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800481
482 private <T> T complete(CompletableFuture<T> future) {
483 try {
484 return future.get();
485 } catch (InterruptedException e) {
486 Thread.currentThread().interrupt();
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700487 if (e == null) {
488 throw new FailedException("Unknown Exception");
489 } else {
490 throw new FailedException(e.getCause().getMessage());
491 }
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800492 } catch (ExecutionException e) {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700493 if (e == null) {
494 throw new FailedException("Unknown Exception");
495 } else if (e.getCause() instanceof IllegalDocumentModificationException) {
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800496 throw new FailedException("Node or parent doesnot exist or is root or is not a Leaf Node");
497 } else if (e.getCause() instanceof NoSuchDocumentPathException) {
498 throw new FailedException("Resource id does not exist");
499 } else {
500 throw new FailedException("Datastore operation failed");
501 }
502 }
503 }
504
505 private <T> T completeVersioned(CompletableFuture<Versioned<T>> future) {
506 try {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700507 if (future.get() != null) {
508 return future.get().value();
509 } else {
510 return null;
511 }
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800512 } catch (InterruptedException e) {
513 Thread.currentThread().interrupt();
514 throw new FailedException(e.getCause().getMessage());
515 } catch (ExecutionException e) {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700516 if (e == null) {
517 throw new FailedException("Unknown Exception");
518 } else if (e.getCause() instanceof IllegalDocumentModificationException) {
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800519 throw new FailedException("Node or parent does not exist or is root or is not a Leaf Node");
520 } else if (e.getCause() instanceof NoSuchDocumentPathException) {
521 throw new FailedException("Resource id does not exist");
522 } else {
523 throw new FailedException("Datastore operation failed");
524 }
525 }
526 }
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800527}