Checkstyle: fix issues and enforce on dsbackend
[lispflowmapping.git] / mappingservice / dsbackend / src / main / java / org / opendaylight / lispflowmapping / dsbackend / DataStoreBackEnd.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc.  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.lispflowmapping.dsbackend;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.util.concurrent.CheckedFuture;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import java.util.ArrayList;
16 import java.util.List;
17 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
20 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
21 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
22 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
23 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
24 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
25 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
26 import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingDatabase;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.AuthenticationKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.Mapping;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.mapping.XtrIdMapping;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.mapping.database.VirtualNetworkIdentifier;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * Stores data coming from the mapping database RPCs into the MD-SAL datastore.
40  *
41  * @author Lorand Jakab
42  *
43  */
44 public class DataStoreBackEnd implements TransactionChainListener {
45     protected static final Logger LOG = LoggerFactory.getLogger(DataStoreBackEnd.class);
46     private static final InstanceIdentifier<MappingDatabase> DATABASE_ROOT =
47             InstanceIdentifier.create(MappingDatabase.class);
48     private BindingTransactionChain txChain;
49
50     public DataStoreBackEnd(DataBroker broker) {
51         this.txChain = broker.createTransactionChain(this);
52     }
53
54
55     public void addAuthenticationKey(AuthenticationKey authenticationKey) {
56         if (LOG.isDebugEnabled()) {
57             LOG.debug("MD-SAL: Adding authentication key '{}' for {}",
58                     authenticationKey.getMappingAuthkey().getKeyString(),
59                     LispAddressStringifier.getString(authenticationKey.getEid()));
60         }
61
62         InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
63                 .createAuthenticationKeyIid(authenticationKey.getEid());
64         writePutTransaction(path, authenticationKey, LogicalDatastoreType.CONFIGURATION,
65                 "Adding authentication key to MD-SAL datastore failed");
66     }
67
68     public void addMapping(Mapping mapping) {
69         if (LOG.isDebugEnabled()) {
70             LOG.debug("MD-SAL: Adding mapping for {}",
71                     LispAddressStringifier.getString(mapping.getMappingRecord().getEid()));
72         }
73
74         InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
75                 .createMappingIid(mapping.getMappingRecord().getEid(), mapping.getOrigin());
76         writePutTransaction(path, mapping, getDestinationDatastore(mapping),
77                 "Adding mapping to MD-SAL datastore failed");
78     }
79
80     // This method assumes that it is only called for southbound originated Map-Registers
81     public void addXtrIdMapping(XtrIdMapping mapping) {
82         XtrId xtrId = mapping.getMappingRecord().getXtrId();
83         Preconditions.checkNotNull(xtrId, "Make sure you only call addXtrIdMapping when the MappingRecord "
84                 + "contains an xTR-ID");
85         if (LOG.isDebugEnabled()) {
86             LOG.debug("MD-SAL: Adding mapping for {}, xTR-ID {}",
87                     LispAddressStringifier.getString(mapping.getMappingRecord().getEid()), xtrId);
88         }
89
90         InstanceIdentifier<XtrIdMapping> path = InstanceIdentifierUtil
91                 .createXtrIdMappingIid(mapping.getMappingRecord().getEid(), MappingOrigin.Southbound, xtrId);
92         writePutTransaction(path, mapping, LogicalDatastoreType.OPERATIONAL,
93                 "Adding xTR-ID mapping to MD-SAL datastore failed");
94     }
95
96     public void removeAuthenticationKey(AuthenticationKey authenticationKey) {
97         if (LOG.isDebugEnabled()) {
98             LOG.debug("MD-SAL: Removing authentication key for {}",
99                     LispAddressStringifier.getString(authenticationKey.getEid()));
100         }
101
102         InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
103                 .createAuthenticationKeyIid(authenticationKey.getEid());
104         deleteTransaction(path, LogicalDatastoreType.CONFIGURATION,
105                 "Deleting authentication key from MD-SAL datastore failed");
106     }
107
108     public void removeMapping(Mapping mapping) {
109         if (LOG.isDebugEnabled()) {
110             LOG.debug("MD-SAL: Removing mapping for {}",
111                     LispAddressStringifier.getString(mapping.getMappingRecord().getEid()));
112         }
113
114         InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
115                 .createMappingIid(mapping.getMappingRecord().getEid(), mapping.getOrigin());
116         deleteTransaction(path, getDestinationDatastore(mapping), "Deleting mapping from MD-SAL datastore failed");
117     }
118
119     public void removeXtrIdMapping(XtrIdMapping mapping) {
120         XtrId xtrId = mapping.getMappingRecord().getXtrId();
121         Preconditions.checkNotNull(xtrId, "Make sure you only call addXtrIdMapping when the MappingRecord "
122                 + "contains an xTR-ID");
123         if (LOG.isDebugEnabled()) {
124             LOG.debug("MD-SAL: Removing mapping for {}, xTR-ID {}",
125                     LispAddressStringifier.getString(mapping.getMappingRecord().getEid()), xtrId);
126         }
127
128         InstanceIdentifier<XtrIdMapping> path = InstanceIdentifierUtil
129                 .createXtrIdMappingIid(mapping.getMappingRecord().getEid(), MappingOrigin.Southbound, xtrId);
130         deleteTransaction(path, LogicalDatastoreType.OPERATIONAL,
131                 "Deleting xTR-ID mapping from MD-SAL datastore failed");
132     }
133
134     public void removeAllDatastoreContent() {
135         LOG.debug("MD-SAL: Removing all mapping database datastore content (mappings and keys)");
136         removeAllConfigDatastoreContent();
137         removeAllOperationalDatastoreContent();
138     }
139
140     public void removeAllConfigDatastoreContent() {
141         deleteTransaction(DATABASE_ROOT, LogicalDatastoreType.CONFIGURATION,
142                 "Removal of all database content in config datastore failed");
143     }
144
145     public void removeAllOperationalDatastoreContent() {
146         deleteTransaction(DATABASE_ROOT, LogicalDatastoreType.OPERATIONAL,
147                 "Removal of all database content in operational datastore failed");
148     }
149
150     public void updateAuthenticationKey(AuthenticationKey authenticationKey) {
151         if (LOG.isDebugEnabled()) {
152             LOG.debug("MD-SAL: Updating authentication key for {} with '{}'",
153                     LispAddressStringifier.getString(authenticationKey.getEid()),
154                     authenticationKey.getMappingAuthkey().getKeyString());
155         }
156
157         InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
158                 .createAuthenticationKeyIid(authenticationKey.getEid());
159         writePutTransaction(path, authenticationKey, LogicalDatastoreType.CONFIGURATION,
160                 "Updating authentication key in MD-SAL datastore failed");
161     }
162
163     public void updateMapping(Mapping mapping) {
164         if (LOG.isDebugEnabled()) {
165             LOG.debug("MD-SAL: Updating mapping for {}",
166                     LispAddressStringifier.getString(mapping.getMappingRecord().getEid()));
167         }
168
169         InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
170                 .createMappingIid(mapping.getMappingRecord().getEid(), mapping.getOrigin());
171         writePutTransaction(path, mapping, getDestinationDatastore(mapping),
172                 "Updating mapping in MD-SAL datastore failed");
173     }
174
175     public List<Mapping> getAllMappings() {
176         List<Mapping> mappings = getAllMappings(LogicalDatastoreType.CONFIGURATION);
177         mappings.addAll(getAllMappings(LogicalDatastoreType.OPERATIONAL));
178         return mappings;
179     }
180
181     public List<Mapping> getAllMappings(LogicalDatastoreType logicalDataStore) {
182         LOG.debug("MD-SAL: Get all mappings from datastore");
183         List<Mapping> mappings = new ArrayList<Mapping>();
184         MappingDatabase mdb = readTransaction(DATABASE_ROOT, logicalDataStore);
185
186         if (mdb != null) {
187             for (VirtualNetworkIdentifier id : mdb.getVirtualNetworkIdentifier()) {
188                 List<Mapping> ms = id.getMapping();
189                 if (ms != null) {
190                     mappings.addAll(ms);
191                 }
192             }
193         }
194
195         return mappings;
196     }
197
198     public List<AuthenticationKey> getAllAuthenticationKeys() {
199         LOG.debug("MD-SAL: Get all authentication keys from datastore");
200         List<AuthenticationKey> authKeys = new ArrayList<AuthenticationKey>();
201         MappingDatabase mdb = readTransaction(DATABASE_ROOT, LogicalDatastoreType.CONFIGURATION);
202
203         if (mdb != null) {
204             for (VirtualNetworkIdentifier id : mdb.getVirtualNetworkIdentifier()) {
205                 List<AuthenticationKey> keys = id.getAuthenticationKey();
206                 if (keys != null) {
207                     authKeys.addAll(keys);
208                 }
209             }
210         }
211
212         return authKeys;
213     }
214
215     private static LogicalDatastoreType getDestinationDatastore(Mapping mapping) {
216         return mapping.getOrigin().equals(MappingOrigin.Southbound) ? LogicalDatastoreType.OPERATIONAL
217                 : LogicalDatastoreType.CONFIGURATION;
218     }
219
220     private <U extends org.opendaylight.yangtools.yang.binding.DataObject> void writePutTransaction(
221             InstanceIdentifier<U> addIID, U data, LogicalDatastoreType logicalDatastoreType, String errMsg) {
222         WriteTransaction writeTx = txChain.newWriteOnlyTransaction();
223         writeTx.put(logicalDatastoreType, addIID, data, true);
224         Futures.addCallback(writeTx.submit(), new FutureCallback<Void>() {
225
226             public void onSuccess(Void result) {
227             }
228
229             public void onFailure(Throwable throwable) {
230                 LOG.error("Transaction failed:", throwable);
231             }
232         });
233     }
234
235     private <U extends org.opendaylight.yangtools.yang.binding.DataObject> U readTransaction(
236             InstanceIdentifier<U> readIID, LogicalDatastoreType logicalDatastoreType) {
237         ReadOnlyTransaction readTx = txChain.newReadOnlyTransaction();
238         CheckedFuture<Optional<U>, ReadFailedException> readFuture = readTx.read(logicalDatastoreType, readIID);
239         readTx.close();
240         try {
241             Optional<U> optionalDataObject = readFuture.checkedGet();
242             if (optionalDataObject != null && optionalDataObject.isPresent()) {
243                 return optionalDataObject.get();
244             } else {
245                 LOG.debug("{}: Failed to read", Thread.currentThread().getStackTrace()[1]);
246             }
247         } catch (ReadFailedException e) {
248             LOG.warn("Failed to ....", e);
249         }
250         return null;
251     }
252
253     private <U extends org.opendaylight.yangtools.yang.binding.DataObject> void deleteTransaction(
254             InstanceIdentifier<U> deleteIID, LogicalDatastoreType logicalDatastoreType, String errMsg) {
255
256         WriteTransaction writeTx = txChain.newWriteOnlyTransaction();
257         writeTx.delete(logicalDatastoreType, deleteIID);
258         Futures.addCallback(writeTx.submit(), new FutureCallback<Void>() {
259
260             public void onSuccess(Void result) {
261             }
262
263             public void onFailure(Throwable throwable) {
264                 LOG.error("Transaction failed:", throwable);
265             }
266         });
267     }
268
269     public void onTransactionChainFailed(TransactionChain<?, ?> chain, AsyncTransaction<?, ?> transaction,
270             Throwable cause) {
271         LOG.error("Broken chain {} in DataStoreBackEnd, transaction {}, cause {}", chain, transaction.getIdentifier(),
272                 cause);
273     }
274
275     public void onTransactionChainSuccessful(TransactionChain<?, ?> chain) {
276         LOG.info("DataStoreBackEnd closed successfully, chain {}", chain);
277     }
278 }