83063a05a837ddbd430f7e68421c3852967d6fcc
[ccsdk/features.git] /
1 /*******************************************************************************
2  * ============LICENSE_START========================================================================
3  * ONAP : ccsdk feature sdnr wt
4  * =================================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6  * =================================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License
13  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14  * or implied. See the License for the specific language governing permissions and limitations under
15  * the License.
16  * ============LICENSE_END==========================================================================
17  ******************************************************************************/
18 package org.onap.ccsdk.features.sdnr.wt.devicemanager.base.netconf.util;
19
20 import java.util.NoSuchElementException;
21 import java.util.concurrent.CancellationException;
22 import java.util.concurrent.ExecutionException;
23 import java.util.concurrent.atomic.AtomicBoolean;
24 import java.util.concurrent.atomic.AtomicReference;
25 import javax.annotation.Nullable;
26 import org.apache.commons.lang3.exception.ExceptionUtils;
27 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
28 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
29 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
30 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
31 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
32 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
33 import org.opendaylight.yangtools.yang.binding.DataObject;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37 import com.google.common.base.Optional;
38 import com.google.common.base.Preconditions;
39 import com.google.common.util.concurrent.CheckedFuture;
40
41 @SuppressWarnings("deprecation")
42 public final class GenericTransactionUtils {
43     static final Logger LOG = LoggerFactory.getLogger(GenericTransactionUtils.class);
44
45     public static <T extends DataObject> boolean writeData(DataBroker dataBroker,
46             LogicalDatastoreType logicalDatastoreType, InstanceIdentifier<T> iid, T dataObject, boolean isAdd) {
47         Preconditions.checkNotNull(dataBroker);
48         WriteTransaction modification = dataBroker.newWriteOnlyTransaction();
49         if (isAdd) {
50             if (dataObject == null) {
51                 LOG.warn("Invalid attempt to add a non-existent object to path {}", iid);
52                 return false;
53             }
54             modification.merge(logicalDatastoreType, iid, dataObject, true /* createMissingParents */);
55         } else {
56             modification.delete(LogicalDatastoreType.CONFIGURATION, iid);
57         }
58         CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
59         try {
60             commitFuture.checkedGet();
61             LOG.debug("Transaction success for {} of object {}", isAdd ? "add" : "delete", dataObject);
62             return true;
63         } catch (Exception e) {
64             LOG.warn("Transaction failed with error {} for {} of object {}", e.getMessage(), isAdd ? "add" : "delete",
65                     dataObject);
66             modification.cancel();
67             return false;
68         }
69     }
70
71     /**
72      * Deliver the data back or null. Warning
73      *
74      * @param <T> SubType of the DataObject to be handled
75      * @param dataBroker for accessing data
76      * @param dataStoreType to address datastore
77      * @param iid id to access data
78      * @return null or object
79      */
80     @Nullable
81     public static <T extends DataObject> T readData(DataBroker dataBroker, LogicalDatastoreType dataStoreType,
82             InstanceIdentifier<T> iid) {
83
84         AtomicBoolean noErrorIndication = new AtomicBoolean();
85         AtomicReference<String> statusText = new AtomicReference<>();
86
87         T obj = readDataOptionalWithStatus(dataBroker, dataStoreType, iid, noErrorIndication, statusText);
88
89         if (!noErrorIndication.get()) {
90             LOG.warn("Read transaction for identifier " + iid + " failed with status " + statusText.get());
91         }
92
93         return obj;
94     }
95
96     /**
97      * Deliver the data back or null
98      *
99      * @param <T> SubType of the DataObject to be handled
100      * @param dataBroker for accessing data
101      * @param dataStoreType to address datastore
102      * @param iid id to access data
103      * @param noErrorIndication (Output) true if data could be read and are available and is not null
104      * @param statusIndicator (Output) String with status indications during the read.
105      * @return null or object
106      */
107     @Nullable
108     public static <T extends DataObject> T readDataOptionalWithStatus(DataBroker dataBroker,
109             LogicalDatastoreType dataStoreType, InstanceIdentifier<T> iid, AtomicBoolean noErrorIndication,
110             AtomicReference<String> statusIndicator) {
111
112         T data = null;
113         noErrorIndication.set(false);
114
115         statusIndicator.set("Preconditions");
116         Preconditions.checkNotNull(dataBroker);
117
118         int retry = 0;
119         int retryDelayMilliseconds = 2000;
120         int maxRetries = 5; // 0 no Retry
121
122         do {
123             if (retry > 0) {
124                 try {
125                     LOG.debug("Sleep {}ms", retryDelayMilliseconds);
126                     Thread.sleep(retryDelayMilliseconds);
127                 } catch (InterruptedException e) {
128                     LOG.debug("Sleep interrupted", e);
129                     Thread.currentThread().interrupt();
130                 }
131             }
132
133             LOG.debug("Sending message with retry {} ", retry);
134             statusIndicator.set("Create Read Transaction");
135
136             try (ReadOnlyTransaction readTransaction = dataBroker.newReadOnlyTransaction();) {
137                 CheckedFuture<Optional<T>, ReadFailedException> od = readTransaction.read(dataStoreType, iid);
138                 statusIndicator.set("Read done");
139                 if (od != null) {
140                     statusIndicator.set("Unwrap checkFuture done");
141                     Optional<T> optionalData = od.get();
142                     if (optionalData != null) {
143                         statusIndicator.set("Unwrap optional done");
144                         data = optionalData.orNull();
145                         statusIndicator.set("Read transaction done");
146                         noErrorIndication.set(true);
147                     }
148                 }
149
150                 readTransaction.close();
151             } catch (CancellationException | ExecutionException | InterruptedException | NoSuchElementException e) {
152                 statusIndicator.set(ExceptionUtils.getStackTrace(e));
153                 if (e instanceof InterruptedException) {
154                     Thread.currentThread().interrupt();
155                 }
156             }
157
158         } while (noErrorIndication.get() == false && retry++ < maxRetries);
159
160         return data;
161     }
162
163
164 }