blob: 5acdacd7f0087fc566faee6bb9f54accdf7068ef [file] [log] [blame]
Sithara Punnassery9306e6b2017-02-06 15:38:19 -08001/*
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 */
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 Punnassery43833e12017-03-14 16:29:19 -070059import java.util.List;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080060import java.util.Map;
61import java.util.concurrent.CompletableFuture;
Sithara Punnassery4b091dc2017-03-02 17:22:40 -080062import java.util.concurrent.ExecutionException;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080063
Sithara Punnassery44e2a702017-03-06 15:38:10 -080064import static org.onosproject.config.DynamicConfigEvent.Type.NODE_ADDED;
Sithara Punnassery44e2a702017-03-06 15:38:10 -080065import static org.onosproject.config.DynamicConfigEvent.Type.NODE_DELETED;
Henry Yu5c54e772017-04-19 14:13:56 -040066import static org.onosproject.config.DynamicConfigEvent.Type.NODE_UPDATED;
Sithara Punnassery44e2a702017-03-06 15:38:10 -080067import static org.onosproject.config.DynamicConfigEvent.Type.UNKNOWN_OPRN;
68
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080069/**
70 * Implementation of the dynamic config store.
71 */
Sithara Punnassery06208792017-02-10 16:25:29 -080072@Beta
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080073@Component(immediate = true)
74@Service
75public class DistributedDynamicConfigStore
76 extends AbstractStore<DynamicConfigEvent, DynamicConfigStoreDelegate>
77 implements DynamicConfigStore {
78 private final Logger log = LoggerFactory.getLogger(getClass());
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected StorageService storageService;
81 private AsyncDocumentTree<DataNode.Type> keystore;
Sithara Punnassery4b091dc2017-03-02 17:22:40 -080082 private ConsistentMap<String, LeafNode> objectStore;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080083 private final DocumentTreeListener<DataNode.Type> klistener = new InternalDocTreeListener();
Sithara Punnassery4b091dc2017-03-02 17:22:40 -080084 private final MapEventListener<String, LeafNode> olistener = new InternalMapListener();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080085
86 @Activate
87 public void activateStore() {
88 KryoNamespace.Builder kryoBuilder = new KryoNamespace.Builder()
89 .register(KryoNamespaces.BASIC)
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080090 .register(java.lang.Class.class)
91 .register(DataNode.Type.class)
92 .register(LeafNode.class)
93 .register(InnerNode.class)
94 .register(ResourceId.class)
95 .register(NodeKey.class)
96 .register(SchemaId.class)
Sithara Punnassery43833e12017-03-14 16:29:19 -070097 .register(LeafListKey.class)
98 .register(ListKey.class)
99 .register(KeyLeaf.class)
Henry Yu5c54e772017-04-19 14:13:56 -0400100 .register(BigInteger.class)
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800101 .register(java.util.LinkedHashMap.class);
102 keystore = storageService.<DataNode.Type>documentTreeBuilder()
103 .withSerializer(Serializer.using(kryoBuilder.build()))
104 .withName("config-key-store")
105 .withRelaxedReadConsistency()
106 .buildDocumentTree();
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800107 objectStore = storageService.<String, LeafNode>consistentMapBuilder()
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800108 .withSerializer(Serializer.using(kryoBuilder.build()))
109 .withName("config-object-store")
110 .withRelaxedReadConsistency()
111 .build();
112 keystore.addListener(klistener);
113 objectStore.addListener(olistener);
114 log.info("DyanmicConfig Store Active");
115 }
116
117 @Deactivate
118 public void deactivateStore() {
119 keystore.removeListener(klistener);
120 objectStore.removeListener(olistener);
121 log.info("DyanmicConfig Store Stopped");
122 }
123
124 @Override
125 public CompletableFuture<Boolean>
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700126 addNode(ResourceId complete, DataNode node) {
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800127 CompletableFuture<Boolean> eventFuture = CompletableFuture.completedFuture(true);
Sithara Punnassery43833e12017-03-14 16:29:19 -0700128 List<NodeKey> nodeKeyList = complete.nodeKeys();
129 NodeKey f = nodeKeyList.get(0);
130 if (f.schemaId().name().compareTo("/") == 0) {
131 nodeKeyList.remove(0);
132 }
Sithara Punnasserybb644902017-03-16 22:08:29 -0700133 String spath = ResourceIdParser.parseResId(complete);
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800134 if (spath == null) {
135 throw new FailedException("Invalid RsourceId, cannot create Node");
136 }
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700137 if (spath.compareTo(ResourceIdParser.ROOT) != 0) {
138 if (completeVersioned(keystore.get(DocumentPath.from(spath))) == null) {
139 throw new FailedException("Node or parent doesnot exist");
140 }
Sithara Punnasserybb644902017-03-16 22:08:29 -0700141 }
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800142 spath = ResourceIdParser.appendNodeKey(spath, node.key());
143 parseNode(spath, node);
144 return eventFuture;
145 }
146
147 private void parseNode(String path, DataNode node) {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700148 if (completeVersioned(keystore.get(DocumentPath.from(path))) != null) {
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800149 throw new FailedException("Requested node already present in the" +
Henry Yu5c54e772017-04-19 14:13:56 -0400150 " store, please use an update method");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800151 }
152 if (node.type() == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
153 addLeaf(path, (LeafNode) node);
154 } else if (node.type() == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
155 path = ResourceIdParser.appendLeafList(path, (LeafListKey) node.key());
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700156 if (completeVersioned(keystore.get(DocumentPath.from(path))) != null) {
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800157 throw new FailedException("Requested node already present in the" +
Henry Yu5c54e772017-04-19 14:13:56 -0400158 " store, please use an update method");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800159 }
160 addLeaf(path, (LeafNode) node);
161 } else if (node.type() == DataNode.Type.SINGLE_INSTANCE_NODE) {
162 traverseInner(path, (InnerNode) node);
163 } else if (node.type() == DataNode.Type.MULTI_INSTANCE_NODE) {
164 path = ResourceIdParser.appendKeyList(path, (ListKey) node.key());
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700165 if (completeVersioned(keystore.get(DocumentPath.from(path))) != null) {
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800166 throw new FailedException("Requested node already present in the" +
Henry Yu5c54e772017-04-19 14:13:56 -0400167 " store, please use an update method");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800168 }
169 traverseInner(path, (InnerNode) node);
170 } else {
171 throw new FailedException("Invalid node type");
172 }
173 }
174
175 private void traverseInner(String path, InnerNode node) {
176 addKey(path, node.type());
177 Map<NodeKey, DataNode> entries = node.childNodes();
178 if (entries.size() == 0) {
Henry Yu5c54e772017-04-19 14:13:56 -0400179 return;
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800180 }
181 entries.forEach((k, v) -> {
182 String tempPath;
183 tempPath = ResourceIdParser.appendNodeKey(path, v.key());
184 if (v.type() == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
185 addLeaf(tempPath, (LeafNode) v);
186 } else if (v.type() == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
187 tempPath = ResourceIdParser.appendLeafList(tempPath, (LeafListKey) v.key());
188 addLeaf(tempPath, (LeafNode) v);
189 } else if (v.type() == DataNode.Type.SINGLE_INSTANCE_NODE) {
190 traverseInner(tempPath, (InnerNode) v);
191 } else if (v.type() == DataNode.Type.MULTI_INSTANCE_NODE) {
192 tempPath = ResourceIdParser.appendKeyList(tempPath, (ListKey) v.key());
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700193 traverseInner(tempPath, (InnerNode) v);
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800194 } else {
195 throw new FailedException("Invalid node type");
196 }
197 });
198 }
199
200 private Boolean addLeaf(String path, LeafNode node) {
201 objectStore.put(path, node);
202 return addKey(path, node.type());
203 }
204
205 private Boolean addKey(String path, DataNode.Type type) {
206 Boolean stat = false;
207 CompletableFuture<Boolean> ret = keystore.create(DocumentPath.from(path), type);
208 return complete(ret);
209 }
210
211 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800212 public CompletableFuture<DataNode> readNode(ResourceId path, Filter filter) {
213 CompletableFuture<DataNode> eventFuture = CompletableFuture.completedFuture(null);
Sithara Punnassery43833e12017-03-14 16:29:19 -0700214 List<NodeKey> nodeKeyList = path.nodeKeys();
215 NodeKey f = nodeKeyList.get(0);
216 if (f.schemaId().name().compareTo("/") == 0) {
217 nodeKeyList.remove(0);
218 }
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800219 String spath = ResourceIdParser.parseResId(path);
220 DocumentPath dpath = DocumentPath.from(spath);
221 DataNode.Type type = null;
222 CompletableFuture<Versioned<DataNode.Type>> ret = keystore.get(dpath);
223 type = completeVersioned(ret);
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800224 if (type == null) {
225 throw new FailedException("Requested node or some of the parents" +
Henry Yu5c54e772017-04-19 14:13:56 -0400226 "are not present in the requested path");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800227 }
228 DataNode retVal = null;
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800229 if (type == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
230 retVal = readLeaf(spath);
231 } else if (type == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
232 retVal = readLeaf(spath);
233 } else if (type == DataNode.Type.SINGLE_INSTANCE_NODE) {
234 NodeKey key = ResourceIdParser.getInstanceKey(path);
235 if (key == null) {
236 throw new FailedException("Key type did not match node type");
237 }
238 DataNode.Builder superBldr = InnerNode
239 .builder(key.schemaId().name(), key.schemaId().namespace())
240 .type(type);
241 readInner(superBldr, spath);
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800242 retVal = superBldr.build();
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800243 } else if (type == DataNode.Type.MULTI_INSTANCE_NODE) {
244 NodeKey key = ResourceIdParser.getMultiInstanceKey(path);
245 if (key == null) {
246 throw new FailedException("Key type did not match node type");
247 }
248 DataNode.Builder superBldr = InnerNode
249 .builder(key.schemaId().name(), key.schemaId().namespace())
250 .type(type);
251 for (KeyLeaf keyLeaf : ((ListKey) key).keyLeafs()) {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700252 //String tempPath = ResourceIdParser.appendKeyLeaf(spath, keyLeaf);
253 //LeafNode lfnd = readLeaf(tempPath);
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800254 superBldr.addKeyLeaf(keyLeaf.leafSchema().name(),
Henry Yu5c54e772017-04-19 14:13:56 -0400255 keyLeaf.leafSchema().namespace(), String.valueOf(keyLeaf.leafValue()));
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800256 }
257 readInner(superBldr, spath);
258 retVal = superBldr.build();
259 } else {
260 throw new FailedException("Invalid node type");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800261 }
262 if (retVal != null) {
263 eventFuture = CompletableFuture.completedFuture(retVal);
264 } else {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700265 log.info("STORE: Failed to READ node");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800266 }
267 return eventFuture;
268 }
269
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800270 private void readInner(DataNode.Builder superBldr, String spath) {
271 CompletableFuture<Map<String, Versioned<DataNode.Type>>> ret = keystore.getChildren(
272 DocumentPath.from(spath));
273 Map<String, Versioned<DataNode.Type>> entries = null;
274 entries = complete(ret);
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700275 /*if ((entries == null) || (entries.size() == 0)) {
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800276 throw new FailedException("Inner node cannot have empty children map");
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700277 }*/
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800278 entries.forEach((k, v) -> {
Sithara Punnasserybda82502017-03-22 19:08:19 -0700279 String[] names = k.split(ResourceIdParser.NM_CHK);
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800280 String name = names[0];
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700281 String nmSpc = ResourceIdParser.getNamespace(names[1]);
282 String keyVal = ResourceIdParser.getKeyVal(names[1]);
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800283 DataNode.Type type = v.value();
284 String tempPath = ResourceIdParser.appendNodeKey(spath, name, nmSpc);
285 if (type == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
286 superBldr.createChildBuilder(name, nmSpc, readLeaf(tempPath).value())
287 .type(type)
288 .exitNode();
289 } else if (type == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700290 String mlpath = ResourceIdParser.appendLeafList(tempPath, keyVal);
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800291 LeafNode lfnode = readLeaf(mlpath);
292 superBldr.createChildBuilder(name, nmSpc, lfnode.value())
293 .type(type)
294 .addLeafListValue(lfnode.value())
295 .exitNode();
296 //TODO this alone should be sufficient and take the nm, nmspc too
297 } else if (type == DataNode.Type.SINGLE_INSTANCE_NODE) {
298 DataNode.Builder tempBldr = superBldr.createChildBuilder(name, nmSpc)
299 .type(type);
300 readInner(tempBldr, tempPath);
301 } else if (type == DataNode.Type.MULTI_INSTANCE_NODE) {
302 DataNode.Builder tempBldr = superBldr.createChildBuilder(name, nmSpc)
303 .type(type);
304 tempPath = ResourceIdParser.appendMultiInstKey(tempPath, k);
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700305 String[] keys = k.split(ResourceIdParser.KEY_CHK);
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800306 for (int i = 1; i < keys.length; i++) {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700307 //String curKey = ResourceIdParser.appendKeyLeaf(tempPath, keys[i]);
308 //LeafNode lfnd = readLeaf(curKey);
Sithara Punnasserybda82502017-03-22 19:08:19 -0700309 String[] keydata = keys[i].split(ResourceIdParser.NM_CHK);
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700310 tempBldr.addKeyLeaf(keydata[0], keydata[1], keydata[2]);
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800311 }
312 readInner(tempBldr, tempPath);
313 } else {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700314 throw new FailedException("Invalid node type");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800315 }
316 });
317 superBldr.exitNode();
318 }
319
320 private LeafNode readLeaf(String path) {
321 return objectStore.get(path).value();
322 }
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700323
Sithara Punnassery0da1a9c2017-05-17 16:16:22 -0700324 private void parseForUpdate(String path, DataNode node) {
325 if (node.type() == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
326 addLeaf(path, (LeafNode) node);
327 } else if (node.type() == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
328 path = ResourceIdParser.appendLeafList(path, (LeafListKey) node.key());
329 addLeaf(path, (LeafNode) node);
330 } else if (node.type() == DataNode.Type.SINGLE_INSTANCE_NODE) {
331 traverseInner(path, (InnerNode) node);
332 } else if (node.type() == DataNode.Type.MULTI_INSTANCE_NODE) {
333 path = ResourceIdParser.appendKeyList(path, (ListKey) node.key());
334 traverseInner(path, (InnerNode) node);
335 } else {
336 throw new FailedException("Invalid node type");
337 }
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800338 }
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700339
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800340 @Override
Sithara Punnassery0da1a9c2017-05-17 16:16:22 -0700341 public CompletableFuture<Boolean> updateNode(ResourceId complete, DataNode node) {
342 CompletableFuture<Boolean> eventFuture = CompletableFuture.completedFuture(true);
343 List<NodeKey> nodeKeyList = complete.nodeKeys();
344 NodeKey f = nodeKeyList.get(0);
345 if (f.schemaId().name().compareTo("/") == 0) {
346 nodeKeyList.remove(0);
347 }
348 String spath = ResourceIdParser.parseResId(complete);
349 if (spath == null) {
350 throw new FailedException("Invalid RsourceId, cannot update Node");
351 }
352 if (spath.compareTo(ResourceIdParser.ROOT) != 0) {
353 if (completeVersioned(keystore.get(DocumentPath.from(spath))) == null) {
354 throw new FailedException("Node or parent doesnot exist, cannot update");
355 }
356 }
357 spath = ResourceIdParser.appendNodeKey(spath, node.key());
358 parseForUpdate(spath, node);
359 return eventFuture;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800360 }
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700361
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800362 @Override
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800363 public CompletableFuture<Boolean> replaceNode(ResourceId path, DataNode node) {
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800364 throw new FailedException("Not yet implemented");
365 }
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700366
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800367 @Override
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800368 public CompletableFuture<Boolean> deleteNode(ResourceId path) {
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800369 throw new FailedException("Not yet implemented");
370 }
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800371
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700372 private void deleteInner(String spath) {
373 CompletableFuture<Map<String, Versioned<DataNode.Type>>> ret = keystore.getChildren(
374 DocumentPath.from(spath));
375 Map<String, Versioned<DataNode.Type>> entries = null;
376 entries = complete(ret);
377 /*if ((entries == null) || (entries.size() == 0)) {
378 throw new FailedException("Inner node cannot have empty children map");
379 }*/
380 entries.forEach((k, v) -> {
381 String[] names = k.split(ResourceIdParser.NM_CHK);
382 String name = names[0];
383 String nmSpc = ResourceIdParser.getNamespace(names[1]);
384 String keyVal = ResourceIdParser.getKeyVal(names[1]);
385 DataNode.Type type = v.value();
386 String tempPath = ResourceIdParser.appendNodeKey(spath, name, nmSpc);
387 if (type == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
388 removeLeaf(tempPath);
389 } else if (type == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
390 String mlpath = ResourceIdParser.appendLeafList(tempPath, keyVal);
391 removeLeaf(mlpath);
392 } else if (type == DataNode.Type.SINGLE_INSTANCE_NODE) {
393 deleteInner(tempPath);
394 } else if (type == DataNode.Type.MULTI_INSTANCE_NODE) {
395 tempPath = ResourceIdParser.appendMultiInstKey(tempPath, k);
396 deleteInner(tempPath);
397 } else {
398 throw new FailedException("Invalid node type");
399 }
400 });
401 keystore.removeNode(DocumentPath.from(spath));
402 }
403
404 private void removeLeaf(String path) {
405 keystore.removeNode(DocumentPath.from(path));
406 objectStore.remove(path);
407 }
408
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800409 @Override
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800410 public CompletableFuture<Boolean> deleteNodeRecursive(ResourceId path) {
Sithara Punnassery43833e12017-03-14 16:29:19 -0700411 List<NodeKey> nodeKeyList = path.nodeKeys();
412 NodeKey f = nodeKeyList.get(0);
413 if (f.schemaId().name().compareTo("/") == 0) {
414 nodeKeyList.remove(0);
415 }
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800416 String spath = ResourceIdParser.parseResId(path);
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700417 if (spath == null) {
418 throw new FailedException("Invalid RsourceId, cannot create Node");
419 }
420 if (spath.compareTo(ResourceIdParser.ROOT) == 0) {
421 throw new FailedException("Cannot delete Root");
422 }
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800423 DocumentPath dpath = DocumentPath.from(spath);
424 DataNode.Type type = null;
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700425 CompletableFuture<Versioned<DataNode.Type>> ret = keystore.get(dpath);
426 type = completeVersioned(ret);
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800427 if (type == null) {
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700428 throw new FailedException("Cannot delete, Requested node or some of the parents" +
Henry Yu5c54e772017-04-19 14:13:56 -0400429 "are not present in the requested path");
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800430 }
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700431 DataNode retVal = null;
432 if (type == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
433 removeLeaf(spath);
434 } else if (type == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
435 removeLeaf(spath);
436 } else if (type == DataNode.Type.SINGLE_INSTANCE_NODE) {
437 deleteInner(spath);
438 } else if (type == DataNode.Type.MULTI_INSTANCE_NODE) {
439 deleteInner(spath);
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800440 } else {
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700441 throw new FailedException("Invalid node type");
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800442 }
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700443 return CompletableFuture.completedFuture(true);
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800444 }
445
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800446 public class InternalDocTreeListener implements DocumentTreeListener<DataNode.Type> {
447 @Override
448 public void event(DocumentTreeEvent<DataNode.Type> event) {
449 DynamicConfigEvent.Type type;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800450 ResourceId path;
451 switch (event.type()) {
452 case CREATED:
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800453 type = NODE_ADDED;
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700454 //log.info("NODE added in store");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800455 break;
456 case UPDATED:
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700457 //log.info("NODE updated in store");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800458 type = NODE_UPDATED;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800459 break;
460 case DELETED:
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700461 //log.info("NODE deleted in store");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800462 type = NODE_DELETED;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800463 break;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800464 default:
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700465 //log.info("UNKNOWN operation in store");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800466 type = UNKNOWN_OPRN;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800467 }
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800468 path = ResourceIdParser.getResId(event.path().pathElements());
469 notifyDelegate(new DynamicConfigEvent(type, path));
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800470 }
471 }
472
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800473 public class InternalMapListener implements MapEventListener<String, LeafNode> {
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800474 @Override
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800475 public void event(MapEvent<String, LeafNode> event) {
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800476 switch (event.type()) {
477 case INSERT:
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800478 //log.info("NODE created in store");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800479 break;
480 case UPDATE:
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800481 //log.info("NODE updated in store");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800482 break;
483 case REMOVE:
484 default:
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800485 //log.info("NODE removed in store");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800486 break;
487 }
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800488 }
489 }
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800490
491 private <T> T complete(CompletableFuture<T> future) {
492 try {
493 return future.get();
494 } catch (InterruptedException e) {
495 Thread.currentThread().interrupt();
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700496 if (e == null) {
497 throw new FailedException("Unknown Exception");
498 } else {
499 throw new FailedException(e.getCause().getMessage());
500 }
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800501 } catch (ExecutionException e) {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700502 if (e == null) {
503 throw new FailedException("Unknown Exception");
504 } else if (e.getCause() instanceof IllegalDocumentModificationException) {
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800505 throw new FailedException("Node or parent doesnot exist or is root or is not a Leaf Node");
506 } else if (e.getCause() instanceof NoSuchDocumentPathException) {
507 throw new FailedException("Resource id does not exist");
508 } else {
509 throw new FailedException("Datastore operation failed");
510 }
511 }
512 }
513
514 private <T> T completeVersioned(CompletableFuture<Versioned<T>> future) {
515 try {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700516 if (future.get() != null) {
517 return future.get().value();
518 } else {
519 return null;
520 }
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800521 } catch (InterruptedException e) {
522 Thread.currentThread().interrupt();
523 throw new FailedException(e.getCause().getMessage());
524 } catch (ExecutionException e) {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700525 if (e == null) {
526 throw new FailedException("Unknown Exception");
527 } else if (e.getCause() instanceof IllegalDocumentModificationException) {
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800528 throw new FailedException("Node or parent does not exist or is root or is not a Leaf Node");
529 } else if (e.getCause() instanceof NoSuchDocumentPathException) {
530 throw new FailedException("Resource id does not exist");
531 } else {
532 throw new FailedException("Datastore operation failed");
533 }
534 }
535 }
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800536}