Checkstyle: fix issues and enforce on implementation
[lispflowmapping.git] / mappingservice / implementation / src / main / java / org / opendaylight / lispflowmapping / implementation / MappingService.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;
9
10 import com.google.common.base.Preconditions;
11 import com.google.common.util.concurrent.Futures;
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.concurrent.Future;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
17 import org.opendaylight.lispflowmapping.dsbackend.DataStoreBackEnd;
18 import org.opendaylight.lispflowmapping.implementation.config.ConfigIni;
19 import org.opendaylight.lispflowmapping.implementation.mdsal.AuthenticationKeyDataListener;
20 import org.opendaylight.lispflowmapping.implementation.mdsal.MappingDataListener;
21 import org.opendaylight.lispflowmapping.implementation.util.DSBEInputUtil;
22 import org.opendaylight.lispflowmapping.implementation.util.RPCInputConvertorUtil;
23 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
24 import org.opendaylight.lispflowmapping.interfaces.mappingservice.IMappingService;
25 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.SiteId;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecord;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecordBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.authkey.container.MappingAuthkey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeyInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeysInput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingInput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingsInput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetAllKeysOutput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetAllMappingsOutput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyInput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyOutput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyOutputBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeysInput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeysOutput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingInput;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingOutput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingOutputBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingsInput;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingsOutput;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.OdlMappingserviceService;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKeyInput;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKeysInput;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMappingInput;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMappingsInput;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKeyInput;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKeysInput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMappingInput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMappingsInput;
59 import org.opendaylight.yangtools.yang.common.RpcError;
60 import org.opendaylight.yangtools.yang.common.RpcResult;
61 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 /**
66  * Dispatcher of API calls that implements the RPC and Java APIs in mappingservice.yang and IMappingService
67  * respectively. It also coordinates and acts as container for all objects in charge of
68  *  - saving and updating md-sal datastore stored mappings
69  *  - monitoring md-sal datastore mapping updates and pushing them to the in memory mapping-system
70  *  - in memory mapping-system
71  *
72  * @author Lorand Jakab
73  * @author Florin Coras
74  *
75  */
76 public class MappingService implements OdlMappingserviceService, IMappingService, AutoCloseable {
77     protected static final Logger LOG = LoggerFactory.getLogger(MappingService.class);
78     private static final String NOT_FOUND_TAG = "data-missing";
79     private static final String DATA_EXISTS_TAG = "data-exists";
80
81     private MappingSystem mappingSystem;
82     private DataStoreBackEnd dsbe;
83     private AuthenticationKeyDataListener keyListener;
84     private MappingDataListener mappingListener;
85     private final ILispDAO dao;
86
87     private final DataBroker dataBroker;
88     private final NotificationPublishService notificationPublishService;
89
90     private boolean overwritePolicy = ConfigIni.getInstance().mappingOverwriteIsSet();
91     private boolean notificationPolicy = ConfigIni.getInstance().smrIsSet();
92     private boolean iterateMask = true;
93
94     public MappingService(final DataBroker broker,
95             final NotificationPublishService notificationPublishService,
96             final ILispDAO lispDAO) {
97         this.dataBroker = broker;
98         this.notificationPublishService = notificationPublishService;
99         this.dao = lispDAO;
100
101         LOG.debug("MappingService created!");
102     }
103
104
105     @Override
106     public void setMappingOverwrite(boolean overwrite) {
107         this.overwritePolicy = overwrite;
108         if (mappingSystem != null) {
109             mappingSystem.setOverwritePolicy(overwrite);
110             ConfigIni.getInstance().setMappingOverwrite(overwrite);
111         }
112     }
113
114     @Override
115     public void setLookupPolicy(IMappingService.LookupPolicy policy) {
116         ConfigIni.getInstance().setLookupPolicy(policy);
117     }
118
119     public void initialize() {
120         LOG.info("Mapping Service initializing...");
121         dsbe = new DataStoreBackEnd(dataBroker);
122
123         mappingSystem = new MappingSystem(dao, iterateMask, notificationPolicy, overwritePolicy);
124         mappingSystem.setDataStoreBackEnd(dsbe);
125         mappingSystem.initialize();
126
127         keyListener = new AuthenticationKeyDataListener(dataBroker, mappingSystem);
128         mappingListener = new MappingDataListener(dataBroker, mappingSystem, notificationPublishService);
129         LOG.info("Mapping Service loaded.");
130     }
131
132     @Override
133     public Future<RpcResult<Void>> addKey(AddKeyInput input) {
134         Preconditions.checkNotNull(input, "add-key RPC input must be not null!");
135         LOG.trace("RPC received to add the following key: " + input.toString());
136
137         RpcResultBuilder<Void> rpcResultBuilder;
138
139         MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
140
141         if (key != null) {
142             String message = "Key already exists! Please use update-key if you want to change it.";
143             rpcResultBuilder = RpcResultBuilder.<Void>failed()
144                     .withError(RpcError.ErrorType.PROTOCOL, DATA_EXISTS_TAG, message);
145             return Futures.immediateFuture(rpcResultBuilder.build());
146         }
147
148         dsbe.addAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
149         rpcResultBuilder = RpcResultBuilder.success();
150
151         return Futures.immediateFuture(rpcResultBuilder.build());
152     }
153
154     @Override
155     public Future<RpcResult<Void>> addMapping(AddMappingInput input) {
156         Preconditions.checkNotNull(input, "add-mapping RPC input must be not null!");
157         LOG.trace("RPC received to add the following mapping: " + input.toString());
158
159         dsbe.addMapping(RPCInputConvertorUtil.toMapping(input));
160
161         RpcResultBuilder<Void> rpcResultBuilder;
162
163         rpcResultBuilder = RpcResultBuilder.success();
164
165         return Futures.immediateFuture(rpcResultBuilder.build());
166     }
167
168     @Override
169     public void addMapping(MappingOrigin origin, Eid key, SiteId siteId, Object data, boolean merge) {
170         // SB registrations are first written to the MappingSystem and only afterwards are persisted to the datastore
171         if (origin.equals(MappingOrigin.Southbound)) {
172             // Store data first in MapCache and only afterwards persist to datastore. This should be used only for SB
173             // registrations
174             mappingSystem.addMapping(origin, key, data, merge);
175             dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, (MappingRecord) data));
176             if (((MappingRecord) data).getXtrId() != null) {
177                 dsbe.addXtrIdMapping(DSBEInputUtil.toXtrIdMapping((MappingRecord) data));
178             }
179         } else {
180             dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, (MappingRecord) data));
181         }
182     }
183
184     @Override
185     public void updateMappingRegistration(MappingOrigin origin, Eid key, Long timestamp) {
186         mappingSystem.updateMappingRegistration(origin, key, timestamp);
187     }
188
189     @Override
190     public Future<RpcResult<GetKeyOutput>> getKey(GetKeyInput input) {
191         Preconditions.checkNotNull(input, "get-key RPC input must be not null!");
192         LOG.trace("RPC received to get the following key: " + input.toString());
193
194         RpcResultBuilder<GetKeyOutput> rpcResultBuilder;
195
196         MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
197
198         if (key == null) {
199             String message = "Key was not found in the mapping database";
200             rpcResultBuilder = RpcResultBuilder.<GetKeyOutput>failed()
201                     .withError(RpcError.ErrorType.APPLICATION, NOT_FOUND_TAG, message);
202         } else {
203             rpcResultBuilder = RpcResultBuilder.success(new GetKeyOutputBuilder().setMappingAuthkey(key));
204         }
205
206         return Futures.immediateFuture(rpcResultBuilder.build());
207     }
208
209     @Override
210     public Future<RpcResult<GetMappingOutput>> getMapping(GetMappingInput input) {
211         Preconditions.checkNotNull(input, "get-mapping RPC input must be not null!");
212         LOG.trace("RPC received to get the following mapping: " + input.toString());
213
214         RpcResultBuilder<GetMappingOutput> rpcResultBuilder;
215
216         MappingRecord reply = (MappingRecord) mappingSystem.getMapping(convertToBinaryIfNecessary(input.getEid()));
217
218         if (reply == null) {
219             String message = "No mapping was found in the mapping database";
220             rpcResultBuilder = RpcResultBuilder.<GetMappingOutput>failed()
221                     .withError(RpcError.ErrorType.APPLICATION, NOT_FOUND_TAG, message);
222         } else {
223             final MappingRecord convertedReply = convertFromBinaryIfNecessary(reply);
224             rpcResultBuilder = RpcResultBuilder.success(new GetMappingOutputBuilder().setMappingRecord(convertedReply));
225         }
226
227         return Futures.immediateFuture(rpcResultBuilder.build());
228     }
229
230     @Override
231     public Object getMapping(MappingOrigin origin, Eid key) {
232         return mappingSystem.getMapping(origin, key);
233     }
234
235     @Override
236     public Object getMapping(Eid key) {
237         return mappingSystem.getMapping(key);
238     }
239
240     @Override
241     public Object getMapping(Eid srcKey, Eid dstKey) {
242         return mappingSystem.getMapping(srcKey, dstKey);
243     }
244
245     @Override
246     public Future<RpcResult<Void>> removeKey(RemoveKeyInput input) {
247         Preconditions.checkNotNull(input, "remove-key RPC input must be not null!");
248         LOG.trace("RPC received to remove the following key: " + input.toString());
249
250         RpcResultBuilder<Void> rpcResultBuilder;
251
252         dsbe.removeAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
253
254         rpcResultBuilder = RpcResultBuilder.success();
255
256         return Futures.immediateFuture(rpcResultBuilder.build());
257     }
258
259     @Override
260     public Future<RpcResult<Void>> removeMapping(RemoveMappingInput input) {
261         Preconditions.checkNotNull(input, "remove-mapping RPC input must be not null!");
262         LOG.trace("RPC received to remove the following mapping: " + input.toString());
263
264         RpcResultBuilder<Void> rpcResultBuilder;
265
266         dsbe.removeMapping(RPCInputConvertorUtil.toMapping(input));
267
268         rpcResultBuilder = RpcResultBuilder.success();
269
270         return Futures.immediateFuture(rpcResultBuilder.build());
271     }
272
273     @Override
274     public void removeMapping(MappingOrigin origin, Eid key) {
275         dsbe.removeMapping(DSBEInputUtil.toMapping(origin, key));
276     }
277
278     @Override
279     public Future<RpcResult<Void>> updateKey(UpdateKeyInput input) {
280         Preconditions.checkNotNull(input, "update-key RPC input must be not null!");
281         LOG.trace("RPC received to update the following key: " + input.toString());
282
283         RpcResultBuilder<Void> rpcResultBuilder;
284
285         MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
286
287         if (key == null) {
288             String message = "Key doesn't exist! Please use add-key if you want to create a new authentication key.";
289             rpcResultBuilder = RpcResultBuilder.<Void>failed()
290                     .withError(RpcError.ErrorType.PROTOCOL, NOT_FOUND_TAG, message);
291             return Futures.immediateFuture(rpcResultBuilder.build());
292         }
293
294         dsbe.updateAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
295         rpcResultBuilder = RpcResultBuilder.success();
296
297         return Futures.immediateFuture(rpcResultBuilder.build());
298     }
299
300     @Override
301     public Future<RpcResult<Void>> updateMapping(UpdateMappingInput input) {
302         LOG.trace("RPC received to update the following mapping: " + input.toString());
303         Preconditions.checkNotNull(input, "update-mapping RPC input must be not null!");
304
305         RpcResultBuilder<Void> rpcResultBuilder;
306
307         dsbe.updateMapping(RPCInputConvertorUtil.toMapping(input));
308
309         rpcResultBuilder = RpcResultBuilder.success();
310
311         return Futures.immediateFuture(rpcResultBuilder.build());
312     }
313
314     @Override
315     public Future<RpcResult<Void>> removeKeys(RemoveKeysInput input) {
316         // TODO Auto-generated method stub
317         return null;
318     }
319
320     @Override
321     public Future<RpcResult<Void>> removeMappings(RemoveMappingsInput input) {
322         // TODO Auto-generated method stub
323         return null;
324     }
325
326     @Override
327     public Future<RpcResult<GetKeysOutput>> getKeys(GetKeysInput input) {
328         // TODO Auto-generated method stub
329         return null;
330     }
331
332     @Override
333     public Future<RpcResult<Void>> addMappings(AddMappingsInput input) {
334         // TODO Auto-generated method stub
335         return null;
336     }
337
338     @Override
339     public Future<RpcResult<Void>> updateKeys(UpdateKeysInput input) {
340         // TODO Auto-generated method stub
341         return null;
342     }
343
344     @Override
345     public Future<RpcResult<Void>> removeAllMappings() {
346         // TODO Auto-generated method stub
347         return null;
348     }
349
350     @Override
351     public Future<RpcResult<Void>> removeAllKeys() {
352         // TODO Auto-generated method stub
353         return null;
354     }
355
356     @Override
357     public Future<RpcResult<GetAllKeysOutput>> getAllKeys() {
358         // TODO Auto-generated method stub
359         return null;
360     }
361
362     @Override
363     public Future<RpcResult<Void>> updateMappings(UpdateMappingsInput input) {
364         // TODO Auto-generated method stub
365         return null;
366     }
367
368     @Override
369     public Future<RpcResult<Void>> addKeys(AddKeysInput input) {
370         // TODO Auto-generated method stub
371         return null;
372     }
373
374     @Override
375     public Future<RpcResult<GetAllMappingsOutput>> getAllMappings() {
376         // TODO Auto-generated method stub
377         return null;
378     }
379
380     @Override
381     public Future<RpcResult<GetMappingsOutput>> getMappings(
382             GetMappingsInput input) {
383         // TODO Auto-generated method stub
384         return null;
385     }
386
387     @Override
388     public Eid getWidestNegativePrefix(Eid key) {
389         return mappingSystem.getWidestNegativePrefix(key);
390     }
391
392     @Override
393     public void addAuthenticationKey(Eid key, MappingAuthkey authKey) {
394         dsbe.addAuthenticationKey(DSBEInputUtil.toAuthenticationKey(key, authKey));
395     }
396
397     @Override
398     public MappingAuthkey getAuthenticationKey(Eid key) {
399         return mappingSystem.getAuthenticationKey(key);
400     }
401
402     @Override
403     public void removeAuthenticationKey(Eid key) {
404         dsbe.removeAuthenticationKey(DSBEInputUtil.toAuthenticationKey(key, null));
405     }
406
407     @Override
408     public void addData(MappingOrigin origin, Eid key, String subKey, Object data) {
409         mappingSystem.addData(origin, key, subKey, data);
410     }
411
412     @Override
413     public Object getData(MappingOrigin origin, Eid key, String subKey) {
414         return mappingSystem.getData(origin, key, subKey);
415     }
416
417     @Override
418     public void removeData(MappingOrigin origin, Eid key, String subKey) {
419         mappingSystem.removeData(origin, key, subKey);
420     }
421
422     @Override
423     public String printMappings() {
424         return mappingSystem.printMappings();
425     }
426
427     @Override
428     public void close() throws Exception {
429         LOG.info("Mapping Service is being destroyed!");
430         keyListener.closeDataChangeListener();
431         mappingListener.closeDataChangeListener();
432     }
433
434     @Override
435     public void cleanCachedMappings() {
436         mappingSystem.cleanCaches();
437         dsbe.removeAllDatastoreContent();
438     }
439
440     private static Eid convertToBinaryIfNecessary(Eid eid) {
441         if (LispAddressUtil.addressNeedsConversionToBinary(eid.getAddress())) {
442             return LispAddressUtil.convertToBinary(eid);
443         }
444         return eid;
445     }
446
447     private static MappingRecord convertFromBinaryIfNecessary(MappingRecord originalRecord) {
448         List<LocatorRecord> originalLocators = originalRecord.getLocatorRecord();
449
450         List<LocatorRecord> convertedLocators = null;
451         if (originalLocators != null) {
452             // If convertedLocators is non-null, while originalLocators is also non-null, conversion has been made
453             convertedLocators = convertFromBinaryIfNecessary(originalLocators);
454         }
455
456         if (LispAddressUtil.addressNeedsConversionFromBinary(originalRecord.getEid().getAddress())
457                 || (originalLocators != null && convertedLocators != null)) {
458             MappingRecordBuilder mrb = new MappingRecordBuilder(originalRecord);
459             mrb.setEid(LispAddressUtil.convertFromBinary(originalRecord.getEid()));
460             if (convertedLocators != null) {
461                 mrb.setLocatorRecord(convertedLocators);
462             }
463             return mrb.build();
464         }
465         return originalRecord;
466     }
467
468     private static List<LocatorRecord> convertFromBinaryIfNecessary(List<LocatorRecord> originalLocators) {
469         List<LocatorRecord> convertedLocators = null;
470         for (LocatorRecord record : originalLocators) {
471             if (LispAddressUtil.addressNeedsConversionFromBinary(record.getRloc().getAddress())) {
472                 LocatorRecordBuilder lrb = new LocatorRecordBuilder(record);
473                 lrb.setRloc(LispAddressUtil.convertFromBinary(record.getRloc()));
474                 if (convertedLocators == null) {
475                     convertedLocators = new ArrayList<LocatorRecord>();
476                 }
477                 convertedLocators.add(lrb.build());
478             }
479         }
480         if (convertedLocators != null) {
481             return convertedLocators;
482         }
483         return originalLocators;
484     }
485 }