1460d8bbbac9262e012931bb30d49101169ee2ae
[ovsdb.git] / utils / mdsal-utils / src / main / java / org / opendaylight / ovsdb / utils / mdsal / utils / MdsalUtils.java
1 /*
2  * Copyright (c) 2015 Red Hat, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.ovsdb.utils.mdsal.utils;
9
10 import com.google.common.util.concurrent.FluentFuture;
11 import java.util.Optional;
12 import java.util.concurrent.ExecutionException;
13 import org.opendaylight.mdsal.binding.api.DataBroker;
14 import org.opendaylight.mdsal.binding.api.ReadTransaction;
15 import org.opendaylight.mdsal.binding.api.WriteTransaction;
16 import org.opendaylight.mdsal.common.api.CommitInfo;
17 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
18 import org.opendaylight.yangtools.yang.binding.DataObject;
19 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22
23 public class MdsalUtils {
24     private static final Logger LOG = LoggerFactory.getLogger(MdsalUtils.class);
25     private static int MDSAL_MAX_READ_TRIALS = Integer.getInteger("mdsalutil.max.tries", 30);
26     private static int MDSAL_READ_SLEEP_INTERVAL_MS = Integer.getInteger("mdsalutil.sleep.between.mdsal.reads", 1000);
27
28     private final DataBroker databroker;
29
30     /**
31      * Class constructor setting the data broker.
32      *
33      * @param dataBroker the {@link DataBroker}
34      */
35     public MdsalUtils(DataBroker dataBroker) {
36         this.databroker = dataBroker;
37     }
38
39     /**
40      * Executes delete as a blocking transaction.
41      *
42      * @param store {@link LogicalDatastoreType} which should be modified
43      * @param path {@link InstanceIdentifier} to read from
44      * @param <D> the data object type
45      * @return the result of the request
46      */
47     public <D extends DataObject> boolean delete(
48             final LogicalDatastoreType store, final InstanceIdentifier<D> path)  {
49         boolean result = false;
50         final WriteTransaction transaction = databroker.newWriteOnlyTransaction();
51         transaction.delete(store, path);
52         FluentFuture<? extends CommitInfo> future = transaction.commit();
53         try {
54             future.get();
55             result = true;
56         } catch (InterruptedException | ExecutionException e) {
57             LOG.warn("Failed to delete {} ", path, e);
58         }
59         return result;
60     }
61
62     /**
63      * Executes merge as a blocking transaction.
64      *
65      * @param logicalDatastoreType {@link LogicalDatastoreType} which should be modified
66      * @param path {@link InstanceIdentifier} for path to read
67      * @param <D> the data object type
68      * @return the result of the request
69      */
70     public <D extends DataObject> boolean merge(
71             final LogicalDatastoreType logicalDatastoreType, final InstanceIdentifier<D> path, D data)  {
72         boolean result = false;
73         final WriteTransaction transaction = databroker.newWriteOnlyTransaction();
74         transaction.mergeParentStructureMerge(logicalDatastoreType, path, data);
75         FluentFuture<? extends CommitInfo> future = transaction.commit();
76         try {
77             future.get();
78             result = true;
79         } catch (InterruptedException | ExecutionException e) {
80             LOG.warn("Failed to merge {} ", path, e);
81         }
82         return result;
83     }
84
85     /**
86      * Executes put as a blocking transaction.
87      *
88      * @param logicalDatastoreType {@link LogicalDatastoreType} which should be modified
89      * @param path {@link InstanceIdentifier} for path to read
90      * @param <D> the data object type
91      * @return the result of the request
92      */
93     public <D extends DataObject> boolean put(
94             final LogicalDatastoreType logicalDatastoreType, final InstanceIdentifier<D> path, D data)  {
95         boolean result = false;
96         final WriteTransaction transaction = databroker.newWriteOnlyTransaction();
97         transaction.mergeParentStructurePut(logicalDatastoreType, path, data);
98         FluentFuture<? extends CommitInfo> future = transaction.commit();
99         try {
100             future.get();
101             result = true;
102         } catch (InterruptedException | ExecutionException e) {
103             LOG.warn("Failed to put {} ", path, e);
104         }
105         return result;
106     }
107
108     /**
109      * Executes read as a blocking transaction.
110      *
111      * @param store {@link LogicalDatastoreType} to read
112      * @param path {@link InstanceIdentifier} for path to read
113      * @param <D> the data object type
114      * @return the result as the data object requested
115      */
116     public <D extends DataObject> D read(
117             final LogicalDatastoreType store, final InstanceIdentifier<? extends DataObject> path) {
118         Optional<D> optionalDataObject = readOptional(store, path);
119         if (optionalDataObject.isPresent()) {
120             return optionalDataObject.get();
121         }
122         LOG.debug("{}: Failed to read {}",
123                 Thread.currentThread().getStackTrace()[1], path);
124         return null;
125     }
126
127     public <D extends DataObject> Optional<D> readOptional(
128             final LogicalDatastoreType store, final InstanceIdentifier<? extends DataObject> path)  {
129         int trialNo = 0;
130         ReadTransaction transaction = databroker.newReadOnlyTransaction();
131         do {
132             try {
133                 Optional<D> result = transaction.read(store, (InstanceIdentifier<D>)path).get();
134                 transaction.close();
135                 return result;
136             } catch (InterruptedException | ExecutionException e) {
137                 if (trialNo == 0) {
138                     logReadFailureError(path, " mdsal Read failed exception retrying the read after sleep");
139                 }
140                 try {
141                     transaction.close();
142                     Thread.sleep(MDSAL_READ_SLEEP_INTERVAL_MS);
143                     transaction = databroker.newReadOnlyTransaction();
144                 } catch (InterruptedException e1) {
145                     logReadFailureError(path, " Sleep interrupted");
146                 }
147             }
148         } while (trialNo++ < MDSAL_MAX_READ_TRIALS);
149         logReadFailureError(path, " All read trials exceeded");
150         return Optional.empty();
151     }
152
153
154     public boolean exists(
155         final LogicalDatastoreType store, final InstanceIdentifier<? extends DataObject> path) {
156         int trialNo = 0;
157         ReadTransaction transaction = databroker.newReadOnlyTransaction();
158         do {
159             try {
160                 FluentFuture<Boolean> result = transaction.exists(store, path);
161                 transaction.close();
162                 return result.get().booleanValue();
163             } catch (InterruptedException | ExecutionException e) {
164                 if (trialNo == 0) {
165                     logReadFailureError(path, " mdsal Read failed exception retrying the read after sleep");
166                 }
167                 try {
168                     transaction.close();
169                     Thread.sleep(MDSAL_READ_SLEEP_INTERVAL_MS);
170                     transaction = databroker.newReadOnlyTransaction();
171                 } catch (InterruptedException e1) {
172                     logReadFailureError(path, " Sleep interrupted");
173                 }
174             }
175         } while (trialNo++ < MDSAL_MAX_READ_TRIALS);
176         logReadFailureError(path, " All read trials exceeded");
177         return false;
178     }
179
180     private <D extends DataObject> void logReadFailureError(
181             InstanceIdentifier<D> path, String cause) {
182         LOG.error("{}: Failed to read {} Cause : {}", Thread.currentThread().getStackTrace()[2], path, cause);
183
184     }
185 }