Bug 5259: Fix NPE in serializer when merge is on
[lispflowmapping.git] / mappingservice / implementation / src / main / java / org / opendaylight / lispflowmapping / implementation / mdsal / 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.implementation.mdsal;
9
10 import java.util.ArrayList;
11 import java.util.List;
12
13 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
16 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
17 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
20 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
21 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
22 import org.opendaylight.lispflowmapping.implementation.util.InstanceIdentifierUtil;
23 import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingDatabase;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.AuthenticationKey;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.Mapping;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.mapping.database.VirtualNetworkIdentifier;
28 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 import com.google.common.base.Optional;
33 import com.google.common.util.concurrent.CheckedFuture;
34 import com.google.common.util.concurrent.FutureCallback;
35 import com.google.common.util.concurrent.Futures;
36
37 /**
38  * Stores data coming from the mapping database RPCs into the config datastore.
39  *
40  * @author Lorand Jakab
41  *
42  */
43 public class DataStoreBackEnd implements TransactionChainListener {
44     protected static final Logger LOG = LoggerFactory.getLogger(DataStoreBackEnd.class);
45     private BindingTransactionChain txChain;
46
47     public DataStoreBackEnd(DataBroker broker) {
48         this.txChain = broker.createTransactionChain(this);
49     }
50
51     public void addAuthenticationKey(AuthenticationKey authenticationKey) {
52         LOG.debug("MD-SAL: Adding authentication key '{}' for {}", authenticationKey.getMappingAuthkey().getKeyString(),
53                 LispAddressStringifier.getString(authenticationKey.getEid()));
54
55         InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
56                 .createAuthenticationKeyIid(authenticationKey.getEid());
57         writePutTransaction(path, authenticationKey, LogicalDatastoreType.CONFIGURATION,
58                 "Adding authentication key to config datastrore failed");
59     }
60
61     public void addMapping(Mapping mapping) {
62         LOG.debug("MD-SAL: Adding mapping for {}",
63                 LispAddressStringifier.getString(mapping.getMappingRecord().getEid()));
64
65         InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
66                 .createMappingIid(mapping.getMappingRecord().getEid(), mapping.getOrigin());
67         writePutTransaction(path, mapping, LogicalDatastoreType.CONFIGURATION,
68                 "Adding mapping to config datastrore failed");
69     }
70
71     public void removeAuthenticationKey(AuthenticationKey authenticationKey) {
72         LOG.debug("MD-SAL: Removing authentication key for {}",
73                 LispAddressStringifier.getString(authenticationKey.getEid()));
74
75         InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
76                 .createAuthenticationKeyIid(authenticationKey.getEid());
77         deleteTransaction(path, LogicalDatastoreType.CONFIGURATION,
78                 "Deleting authentication key from config datastrore failed");
79     }
80
81     public void removeMapping(Mapping mapping) {
82         LOG.debug("MD-SAL: Removing mapping for {}",
83                 LispAddressStringifier.getString(mapping.getMappingRecord().getEid()));
84
85         InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
86                 .createMappingIid(mapping.getMappingRecord().getEid(), mapping.getOrigin());
87         deleteTransaction(path, LogicalDatastoreType.CONFIGURATION, "Deleting mapping from config datastrore failed");
88     }
89
90     public void removeAllMappings() {
91         LOG.debug("MD-SAL: Removing all mappings");
92         InstanceIdentifier<MappingDatabase> path = InstanceIdentifier.create(MappingDatabase.class);
93         deleteTransaction(path, LogicalDatastoreType.CONFIGURATION,
94                 "Removing of all mappings in config datastore failed");
95     }
96
97     public void updateAuthenticationKey(AuthenticationKey authenticationKey) {
98         LOG.debug("MD-SAL: Updating authentication key for {} with '{}'",
99                 LispAddressStringifier.getString(authenticationKey.getEid()),
100                 authenticationKey.getMappingAuthkey().getKeyString());
101
102         InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
103                 .createAuthenticationKeyIid(authenticationKey.getEid());
104         writePutTransaction(path, authenticationKey, LogicalDatastoreType.CONFIGURATION,
105                 "Updating authentication key in config datastrore failed");
106     }
107
108     public void updateMapping(Mapping mapping) {
109         LOG.debug("MD-SAL: Updating mapping for {}",
110                 LispAddressStringifier.getString(mapping.getMappingRecord().getEid()));
111
112         InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
113                 .createMappingIid(mapping.getMappingRecord().getEid(), mapping.getOrigin());
114         writePutTransaction(path, mapping, LogicalDatastoreType.CONFIGURATION,
115                 "Updating mapping in config datastrore failed");
116     }
117
118     public List<Mapping> getAllMappings() {
119         LOG.debug("MD-SAL: Get all mappings from datastore");
120         List<Mapping> mappings = new ArrayList<Mapping>();
121         InstanceIdentifier<MappingDatabase> path = InstanceIdentifier.create(MappingDatabase.class);
122         MappingDatabase mdb = readTransaction(path, LogicalDatastoreType.CONFIGURATION);
123
124         if (mdb != null) {
125             for (VirtualNetworkIdentifier id : mdb.getVirtualNetworkIdentifier()) {
126                 List<Mapping> ms = id.getMapping();
127                 if (ms != null) {
128                     mappings.addAll(ms);
129                 }
130             }
131         }
132
133         return mappings;
134     }
135
136     public List<AuthenticationKey> getAllAuthenticationKeys() {
137         LOG.debug("MD-SAL: Get all authentication keys from datastore");
138         List<AuthenticationKey> authKeys = new ArrayList<AuthenticationKey>();
139         InstanceIdentifier<MappingDatabase> path = InstanceIdentifier.create(MappingDatabase.class);
140         MappingDatabase mdb = readTransaction(path, LogicalDatastoreType.CONFIGURATION);
141
142         if (mdb != null) {
143             for (VirtualNetworkIdentifier id : mdb.getVirtualNetworkIdentifier()) {
144                 List<AuthenticationKey> keys = id.getAuthenticationKey();
145                 if (keys != null) {
146                     authKeys.addAll(keys);
147                 }
148             }
149         }
150
151         return authKeys;
152     }
153
154     private <U extends org.opendaylight.yangtools.yang.binding.DataObject> void writePutTransaction(
155             InstanceIdentifier<U> addIID, U data, LogicalDatastoreType logicalDatastoreType, String errMsg) {
156         WriteTransaction writeTx = txChain.newWriteOnlyTransaction();
157         writeTx.put(logicalDatastoreType, addIID, data, true);
158         Futures.addCallback(writeTx.submit(), new FutureCallback<Void>() {
159             @Override
160             public void onSuccess(Void result) {
161             }
162             @Override
163             public void onFailure(Throwable t) {
164                 LOG.error("Transaction failed:", t);
165             }
166         });
167     }
168
169     private <U extends org.opendaylight.yangtools.yang.binding.DataObject> U readTransaction(
170             InstanceIdentifier<U> readIID, LogicalDatastoreType logicalDatastoreType) {
171         ReadOnlyTransaction readTx = txChain.newReadOnlyTransaction();
172         CheckedFuture<Optional<U>, ReadFailedException> readFuture = readTx.read(logicalDatastoreType, readIID);
173         readTx.close();
174         try {
175             Optional<U> optionalDataObject = readFuture.checkedGet();
176             if (optionalDataObject != null && optionalDataObject.isPresent()) {
177                 return optionalDataObject.get();
178             } else {
179                 LOG.debug("{}: Failed to read", Thread.currentThread().getStackTrace()[1]);
180             }
181         } catch (ReadFailedException e) {
182             LOG.warn("Failed to ....", e);
183         }
184         return null;
185     }
186
187     private <U extends org.opendaylight.yangtools.yang.binding.DataObject> void deleteTransaction(
188             InstanceIdentifier<U> deleteIID, LogicalDatastoreType logicalDatastoreType, String errMsg) {
189
190         WriteTransaction writeTx = txChain.newWriteOnlyTransaction();
191         writeTx.delete(logicalDatastoreType, deleteIID);
192         Futures.addCallback(writeTx.submit(), new FutureCallback<Void>() {
193             @Override
194             public void onSuccess(Void result) {
195             }
196             @Override
197             public void onFailure(Throwable t) {
198                 LOG.error("Transaction failed:", t);
199             }
200         });
201     }
202
203     @Override
204     public void onTransactionChainFailed(TransactionChain<?, ?> chain, AsyncTransaction<?, ?> transaction,
205             Throwable cause) {
206         LOG.error("Broken chain {} in DataStoreBackEnd, transaction {}, cause {}", chain, transaction.getIdentifier(),
207                 cause);
208     }
209
210     @Override
211     public void onTransactionChainSuccessful(TransactionChain<?, ?> chain) {
212         LOG.info("DataStoreBackEnd closed successfully, chain {}", chain);
213     }
214 }