blob: 8a84f065c21ff840d3b0280e767aa7e10096a528 [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 *
Sithara Punnasseryc3658c72017-08-07 11:16:08 -07008 * http://www.apache.org/licenses/LICENSE-2.0
Sithara Punnassery9306e6b2017-02-06 15:38:19 -08009 *
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 Punnasserydb3591b2017-08-10 19:44:53 -070043import org.onosproject.store.service.Ordering;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080044import org.onosproject.store.service.Serializer;
45import org.onosproject.store.service.StorageService;
46import org.onosproject.store.service.Versioned;
Sithara Punnassery44e2a702017-03-06 15:38:10 -080047import org.onosproject.yang.model.DataNode;
48import org.onosproject.yang.model.InnerNode;
49import org.onosproject.yang.model.KeyLeaf;
50import org.onosproject.yang.model.LeafListKey;
51import org.onosproject.yang.model.LeafNode;
52import org.onosproject.yang.model.ListKey;
53import org.onosproject.yang.model.NodeKey;
54import org.onosproject.yang.model.ResourceId;
55import org.onosproject.yang.model.SchemaId;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080056import org.slf4j.Logger;
57import org.slf4j.LoggerFactory;
Henry Yu5c54e772017-04-19 14:13:56 -040058
59import java.math.BigInteger;
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()
Sithara Punnasserydb3591b2017-08-10 19:44:53 -0700106 .withOrdering(Ordering.INSERTION)
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800107 .buildDocumentTree();
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800108 objectStore = storageService.<String, LeafNode>consistentMapBuilder()
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800109 .withSerializer(Serializer.using(kryoBuilder.build()))
110 .withName("config-object-store")
111 .withRelaxedReadConsistency()
112 .build();
113 keystore.addListener(klistener);
114 objectStore.addListener(olistener);
115 log.info("DyanmicConfig Store Active");
116 }
117
118 @Deactivate
119 public void deactivateStore() {
120 keystore.removeListener(klistener);
121 objectStore.removeListener(olistener);
122 log.info("DyanmicConfig Store Stopped");
123 }
124
125 @Override
126 public CompletableFuture<Boolean>
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700127 addNode(ResourceId complete, DataNode node) {
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800128 CompletableFuture<Boolean> eventFuture = CompletableFuture.completedFuture(true);
Sithara Punnasserybb644902017-03-16 22:08:29 -0700129 String spath = ResourceIdParser.parseResId(complete);
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800130 if (spath == null) {
131 throw new FailedException("Invalid RsourceId, cannot create Node");
132 }
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700133 if (spath.compareTo(ResourceIdParser.ROOT) != 0) {
134 if (completeVersioned(keystore.get(DocumentPath.from(spath))) == null) {
135 throw new FailedException("Node or parent doesnot exist");
136 }
Sithara Punnasserybb644902017-03-16 22:08:29 -0700137 }
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800138 spath = ResourceIdParser.appendNodeKey(spath, node.key());
139 parseNode(spath, node);
140 return eventFuture;
141 }
142
143 private void parseNode(String path, DataNode node) {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700144 if (completeVersioned(keystore.get(DocumentPath.from(path))) != null) {
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800145 throw new FailedException("Requested node already present in the" +
Henry Yu5c54e772017-04-19 14:13:56 -0400146 " store, please use an update method");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800147 }
148 if (node.type() == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
149 addLeaf(path, (LeafNode) node);
150 } else if (node.type() == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
151 path = ResourceIdParser.appendLeafList(path, (LeafListKey) node.key());
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700152 if (completeVersioned(keystore.get(DocumentPath.from(path))) != null) {
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800153 throw new FailedException("Requested node already present in the" +
Henry Yu5c54e772017-04-19 14:13:56 -0400154 " store, please use an update method");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800155 }
156 addLeaf(path, (LeafNode) node);
157 } else if (node.type() == DataNode.Type.SINGLE_INSTANCE_NODE) {
158 traverseInner(path, (InnerNode) node);
159 } else if (node.type() == DataNode.Type.MULTI_INSTANCE_NODE) {
160 path = ResourceIdParser.appendKeyList(path, (ListKey) node.key());
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700161 if (completeVersioned(keystore.get(DocumentPath.from(path))) != null) {
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800162 throw new FailedException("Requested node already present in the" +
Henry Yu5c54e772017-04-19 14:13:56 -0400163 " store, please use an update method");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800164 }
165 traverseInner(path, (InnerNode) node);
166 } else {
167 throw new FailedException("Invalid node type");
168 }
169 }
170
171 private void traverseInner(String path, InnerNode node) {
172 addKey(path, node.type());
173 Map<NodeKey, DataNode> entries = node.childNodes();
174 if (entries.size() == 0) {
Henry Yu5c54e772017-04-19 14:13:56 -0400175 return;
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800176 }
177 entries.forEach((k, v) -> {
178 String tempPath;
179 tempPath = ResourceIdParser.appendNodeKey(path, v.key());
180 if (v.type() == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
181 addLeaf(tempPath, (LeafNode) v);
182 } else if (v.type() == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
183 tempPath = ResourceIdParser.appendLeafList(tempPath, (LeafListKey) v.key());
184 addLeaf(tempPath, (LeafNode) v);
185 } else if (v.type() == DataNode.Type.SINGLE_INSTANCE_NODE) {
186 traverseInner(tempPath, (InnerNode) v);
187 } else if (v.type() == DataNode.Type.MULTI_INSTANCE_NODE) {
188 tempPath = ResourceIdParser.appendKeyList(tempPath, (ListKey) v.key());
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700189 traverseInner(tempPath, (InnerNode) v);
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800190 } else {
191 throw new FailedException("Invalid node type");
192 }
193 });
194 }
195
196 private Boolean addLeaf(String path, LeafNode node) {
197 objectStore.put(path, node);
198 return addKey(path, node.type());
199 }
200
201 private Boolean addKey(String path, DataNode.Type type) {
Sithara Punnasseryc70b7e52017-08-10 14:28:08 -0700202 if (completeVersioned(keystore.get(DocumentPath.from(path))) != null) {
203 completeVersioned(keystore.set(DocumentPath.from(path), type));
204 return true;
205 }
206 return complete(keystore.create(DocumentPath.from(path), type));
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800207 }
208
209 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800210 public CompletableFuture<DataNode> readNode(ResourceId path, Filter filter) {
211 CompletableFuture<DataNode> eventFuture = CompletableFuture.completedFuture(null);
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800212 String spath = ResourceIdParser.parseResId(path);
213 DocumentPath dpath = DocumentPath.from(spath);
214 DataNode.Type type = null;
215 CompletableFuture<Versioned<DataNode.Type>> ret = keystore.get(dpath);
216 type = completeVersioned(ret);
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800217 if (type == null) {
218 throw new FailedException("Requested node or some of the parents" +
Henry Yu5c54e772017-04-19 14:13:56 -0400219 "are not present in the requested path");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800220 }
221 DataNode retVal = null;
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800222 if (type == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
223 retVal = readLeaf(spath);
224 } else if (type == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
225 retVal = readLeaf(spath);
226 } else if (type == DataNode.Type.SINGLE_INSTANCE_NODE) {
227 NodeKey key = ResourceIdParser.getInstanceKey(path);
228 if (key == null) {
229 throw new FailedException("Key type did not match node type");
230 }
231 DataNode.Builder superBldr = InnerNode
232 .builder(key.schemaId().name(), key.schemaId().namespace())
233 .type(type);
234 readInner(superBldr, spath);
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800235 retVal = superBldr.build();
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800236 } else if (type == DataNode.Type.MULTI_INSTANCE_NODE) {
237 NodeKey key = ResourceIdParser.getMultiInstanceKey(path);
238 if (key == null) {
239 throw new FailedException("Key type did not match node type");
240 }
241 DataNode.Builder superBldr = InnerNode
242 .builder(key.schemaId().name(), key.schemaId().namespace())
243 .type(type);
244 for (KeyLeaf keyLeaf : ((ListKey) key).keyLeafs()) {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700245 //String tempPath = ResourceIdParser.appendKeyLeaf(spath, keyLeaf);
246 //LeafNode lfnd = readLeaf(tempPath);
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800247 superBldr.addKeyLeaf(keyLeaf.leafSchema().name(),
Henry Yu5c54e772017-04-19 14:13:56 -0400248 keyLeaf.leafSchema().namespace(), String.valueOf(keyLeaf.leafValue()));
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800249 }
250 readInner(superBldr, spath);
251 retVal = superBldr.build();
252 } else {
253 throw new FailedException("Invalid node type");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800254 }
255 if (retVal != null) {
256 eventFuture = CompletableFuture.completedFuture(retVal);
257 } else {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700258 log.info("STORE: Failed to READ node");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800259 }
260 return eventFuture;
261 }
262
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800263 private void readInner(DataNode.Builder superBldr, String spath) {
264 CompletableFuture<Map<String, Versioned<DataNode.Type>>> ret = keystore.getChildren(
265 DocumentPath.from(spath));
266 Map<String, Versioned<DataNode.Type>> entries = null;
267 entries = complete(ret);
Sithara Punnassery18ffcc72017-05-18 14:24:30 -0700268 if ((entries != null) && (!entries.isEmpty())) {
269 entries.forEach((k, v) -> {
270 String[] names = k.split(ResourceIdParser.NM_CHK);
271 String name = names[0];
272 String nmSpc = ResourceIdParser.getNamespace(names[1]);
273 String keyVal = ResourceIdParser.getKeyVal(names[1]);
274 DataNode.Type type = v.value();
275 String tempPath = ResourceIdParser.appendNodeKey(spath, name, nmSpc);
276 if (type == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
277 superBldr.createChildBuilder(name, nmSpc, readLeaf(tempPath).value())
278 .type(type)
279 .exitNode();
280 } else if (type == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
281 String mlpath = ResourceIdParser.appendLeafList(tempPath, keyVal);
282 LeafNode lfnode = readLeaf(mlpath);
283 superBldr.createChildBuilder(name, nmSpc, lfnode.value())
284 .type(type)
285 .addLeafListValue(lfnode.value())
286 .exitNode();
287 //TODO this alone should be sufficient and take the nm, nmspc too
288 } else if (type == DataNode.Type.SINGLE_INSTANCE_NODE) {
289 DataNode.Builder tempBldr = superBldr.createChildBuilder(name, nmSpc)
290 .type(type);
291 readInner(tempBldr, tempPath);
292 } else if (type == DataNode.Type.MULTI_INSTANCE_NODE) {
293 DataNode.Builder tempBldr = superBldr.createChildBuilder(name, nmSpc)
294 .type(type);
295 tempPath = ResourceIdParser.appendMultiInstKey(tempPath, k);
296 String[] keys = k.split(ResourceIdParser.KEY_CHK);
297 for (int i = 1; i < keys.length; i++) {
298 //String curKey = ResourceIdParser.appendKeyLeaf(tempPath, keys[i]);
299 //LeafNode lfnd = readLeaf(curKey);
300 String[] keydata = keys[i].split(ResourceIdParser.NM_CHK);
301 tempBldr.addKeyLeaf(keydata[0], keydata[1], keydata[2]);
302 }
303 readInner(tempBldr, tempPath);
304 } else {
305 throw new FailedException("Invalid node type");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800306 }
Sithara Punnassery18ffcc72017-05-18 14:24:30 -0700307 });
308 }
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800309 superBldr.exitNode();
310 }
311
312 private LeafNode readLeaf(String path) {
313 return objectStore.get(path).value();
314 }
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700315
Sithara Punnassery0da1a9c2017-05-17 16:16:22 -0700316 private void parseForUpdate(String path, DataNode node) {
317 if (node.type() == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
318 addLeaf(path, (LeafNode) node);
319 } else if (node.type() == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
320 path = ResourceIdParser.appendLeafList(path, (LeafListKey) node.key());
321 addLeaf(path, (LeafNode) node);
322 } else if (node.type() == DataNode.Type.SINGLE_INSTANCE_NODE) {
323 traverseInner(path, (InnerNode) node);
324 } else if (node.type() == DataNode.Type.MULTI_INSTANCE_NODE) {
325 path = ResourceIdParser.appendKeyList(path, (ListKey) node.key());
326 traverseInner(path, (InnerNode) node);
327 } else {
328 throw new FailedException("Invalid node type");
329 }
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800330 }
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700331
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800332 @Override
Sithara Punnassery0da1a9c2017-05-17 16:16:22 -0700333 public CompletableFuture<Boolean> updateNode(ResourceId complete, DataNode node) {
334 CompletableFuture<Boolean> eventFuture = CompletableFuture.completedFuture(true);
Sithara Punnassery0da1a9c2017-05-17 16:16:22 -0700335 String spath = ResourceIdParser.parseResId(complete);
336 if (spath == null) {
337 throw new FailedException("Invalid RsourceId, cannot update Node");
338 }
339 if (spath.compareTo(ResourceIdParser.ROOT) != 0) {
340 if (completeVersioned(keystore.get(DocumentPath.from(spath))) == null) {
341 throw new FailedException("Node or parent doesnot exist, cannot update");
342 }
343 }
344 spath = ResourceIdParser.appendNodeKey(spath, node.key());
345 parseForUpdate(spath, node);
346 return eventFuture;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800347 }
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700348
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800349 @Override
Sithara Punnassery18ffcc72017-05-18 14:24:30 -0700350 public CompletableFuture<Boolean> nodeExist(ResourceId complete) {
351 Boolean stat = true;
Sithara Punnassery18ffcc72017-05-18 14:24:30 -0700352 String spath = ResourceIdParser.parseResId(complete);
353 if (spath == null) {
354 stat = false;
355 } else if (completeVersioned(keystore.get(DocumentPath.from(spath))) == null) {
356 stat = false;
357 }
358 return CompletableFuture.completedFuture(stat);
359 }
360
361 @Override
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800362 public CompletableFuture<Boolean> replaceNode(ResourceId path, DataNode node) {
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800363 throw new FailedException("Not yet implemented");
364 }
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700365
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800366 @Override
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800367 public CompletableFuture<Boolean> deleteNode(ResourceId path) {
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800368 throw new FailedException("Not yet implemented");
369 }
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800370
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700371 private void deleteInner(String spath) {
372 CompletableFuture<Map<String, Versioned<DataNode.Type>>> ret = keystore.getChildren(
373 DocumentPath.from(spath));
374 Map<String, Versioned<DataNode.Type>> entries = null;
375 entries = complete(ret);
Sithara Punnassery18ffcc72017-05-18 14:24:30 -0700376 if ((entries != null) && (!entries.isEmpty())) {
377 entries.forEach((k, v) -> {
378 String[] names = k.split(ResourceIdParser.NM_CHK);
379 String name = names[0];
380 String nmSpc = ResourceIdParser.getNamespace(names[1]);
381 String keyVal = ResourceIdParser.getKeyVal(names[1]);
382 DataNode.Type type = v.value();
383 String tempPath = ResourceIdParser.appendNodeKey(spath, name, nmSpc);
384 if (type == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
385 removeLeaf(tempPath);
386 } else if (type == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
387 String mlpath = ResourceIdParser.appendLeafList(tempPath, keyVal);
388 removeLeaf(mlpath);
389 } else if (type == DataNode.Type.SINGLE_INSTANCE_NODE) {
390 deleteInner(tempPath);
391 } else if (type == DataNode.Type.MULTI_INSTANCE_NODE) {
392 tempPath = ResourceIdParser.appendMultiInstKey(tempPath, k);
393 deleteInner(tempPath);
394 } else {
395 throw new FailedException("Invalid node type");
396 }
397 });
398 }
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700399 keystore.removeNode(DocumentPath.from(spath));
400 }
401
402 private void removeLeaf(String path) {
403 keystore.removeNode(DocumentPath.from(path));
404 objectStore.remove(path);
405 }
406
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800407 @Override
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800408 public CompletableFuture<Boolean> deleteNodeRecursive(ResourceId path) {
409 String spath = ResourceIdParser.parseResId(path);
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700410 if (spath == null) {
Sithara Punnasserybc9edb12017-07-20 14:32:33 -0700411 throw new FailedException("Invalid RsourceId, cannot delete Node");
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700412 }
413 if (spath.compareTo(ResourceIdParser.ROOT) == 0) {
414 throw new FailedException("Cannot delete Root");
415 }
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800416 DocumentPath dpath = DocumentPath.from(spath);
417 DataNode.Type type = null;
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700418 CompletableFuture<Versioned<DataNode.Type>> ret = keystore.get(dpath);
419 type = completeVersioned(ret);
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800420 if (type == null) {
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700421 throw new FailedException("Cannot delete, Requested node or some of the parents" +
Henry Yu5c54e772017-04-19 14:13:56 -0400422 "are not present in the requested path");
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800423 }
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700424 DataNode retVal = null;
425 if (type == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
426 removeLeaf(spath);
427 } else if (type == DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE) {
428 removeLeaf(spath);
429 } else if (type == DataNode.Type.SINGLE_INSTANCE_NODE) {
430 deleteInner(spath);
431 } else if (type == DataNode.Type.MULTI_INSTANCE_NODE) {
432 deleteInner(spath);
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800433 } else {
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700434 throw new FailedException("Invalid node type");
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800435 }
Sithara Punnasserye4ab4f22017-03-27 19:11:00 -0700436 return CompletableFuture.completedFuture(true);
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800437 }
438
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800439 public class InternalDocTreeListener implements DocumentTreeListener<DataNode.Type> {
440 @Override
441 public void event(DocumentTreeEvent<DataNode.Type> event) {
442 DynamicConfigEvent.Type type;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800443 ResourceId path;
444 switch (event.type()) {
445 case CREATED:
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800446 type = NODE_ADDED;
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700447 //log.info("NODE added in store");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800448 break;
449 case UPDATED:
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700450 //log.info("NODE updated in store");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800451 type = NODE_UPDATED;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800452 break;
453 case DELETED:
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700454 //log.info("NODE deleted in store");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800455 type = NODE_DELETED;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800456 break;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800457 default:
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700458 //log.info("UNKNOWN operation in store");
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800459 type = UNKNOWN_OPRN;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800460 }
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800461 path = ResourceIdParser.getResId(event.path().pathElements());
462 notifyDelegate(new DynamicConfigEvent(type, path));
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800463 }
464 }
465
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800466 public class InternalMapListener implements MapEventListener<String, LeafNode> {
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800467 @Override
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800468 public void event(MapEvent<String, LeafNode> event) {
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800469 switch (event.type()) {
470 case INSERT:
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800471 //log.info("NODE created in store");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800472 break;
473 case UPDATE:
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800474 //log.info("NODE updated in store");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800475 break;
476 case REMOVE:
477 default:
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800478 //log.info("NODE removed in store");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800479 break;
480 }
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800481 }
482 }
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800483
484 private <T> T complete(CompletableFuture<T> future) {
485 try {
486 return future.get();
487 } catch (InterruptedException e) {
488 Thread.currentThread().interrupt();
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700489 if (e == null) {
490 throw new FailedException("Unknown Exception");
491 } else {
492 throw new FailedException(e.getCause().getMessage());
493 }
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800494 } catch (ExecutionException e) {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700495 if (e == null) {
496 throw new FailedException("Unknown Exception");
497 } else if (e.getCause() instanceof IllegalDocumentModificationException) {
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800498 throw new FailedException("Node or parent doesnot exist or is root or is not a Leaf Node");
499 } else if (e.getCause() instanceof NoSuchDocumentPathException) {
500 throw new FailedException("Resource id does not exist");
501 } else {
502 throw new FailedException("Datastore operation failed");
503 }
504 }
505 }
506
507 private <T> T completeVersioned(CompletableFuture<Versioned<T>> future) {
508 try {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700509 if (future.get() != null) {
510 return future.get().value();
511 } else {
512 return null;
513 }
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800514 } catch (InterruptedException e) {
515 Thread.currentThread().interrupt();
516 throw new FailedException(e.getCause().getMessage());
517 } catch (ExecutionException e) {
Sithara Punnassery4cd2ced2017-03-17 17:36:43 -0700518 if (e == null) {
519 throw new FailedException("Unknown Exception");
520 } else if (e.getCause() instanceof IllegalDocumentModificationException) {
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800521 throw new FailedException("Node or parent does not exist or is root or is not a Leaf Node");
522 } else if (e.getCause() instanceof NoSuchDocumentPathException) {
523 throw new FailedException("Resource id does not exist");
524 } else {
525 throw new FailedException("Datastore operation failed");
526 }
527 }
528 }
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800529}