Bump versions by x.(y+1).z
[lispflowmapping.git] / mappingservice / implementation / src / main / java / org / opendaylight / lispflowmapping / implementation / MappingService.java
1 /*
2  * Copyright (c) 2015, 2017 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 static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.VisibleForTesting;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.Set;
17 import javax.annotation.PreDestroy;
18 import javax.inject.Singleton;
19 import org.opendaylight.lispflowmapping.config.ConfigIni;
20 import org.opendaylight.lispflowmapping.dsbackend.DataStoreBackEnd;
21 import org.opendaylight.lispflowmapping.implementation.mdsal.AuthenticationKeyDataListener;
22 import org.opendaylight.lispflowmapping.implementation.mdsal.MappingDataListener;
23 import org.opendaylight.lispflowmapping.implementation.util.DSBEInputUtil;
24 import org.opendaylight.lispflowmapping.implementation.util.RPCInputConvertorUtil;
25 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
26 import org.opendaylight.lispflowmapping.interfaces.dao.Subscriber;
27 import org.opendaylight.lispflowmapping.interfaces.mappingservice.IMappingService;
28 import org.opendaylight.lispflowmapping.lisp.type.MappingData;
29 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
30 import org.opendaylight.mdsal.binding.api.DataBroker;
31 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
32 import org.opendaylight.mdsal.binding.api.RpcProviderService;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.SiteId;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrId;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecord;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecordBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping._record.container.MappingRecord;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping._record.container.MappingRecordBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.authkey.container.MappingAuthkey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeyInput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeyOutput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeyOutputBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeys;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeysInput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeysOutput;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMapping;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingInput;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingOutput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingOutputBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappings;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingsInput;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingsOutput;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetAllKeys;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetAllKeysInput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetAllKeysOutput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetAllMappings;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetAllMappingsInput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetAllMappingsOutput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyOutput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyOutputBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeys;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeysInput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeysOutput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMapping;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingInput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingOutput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingOutputBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingWithXtrId;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingWithXtrIdInput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingWithXtrIdOutput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingWithXtrIdOutputBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappings;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingsInput;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingsOutput;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveAllKeys;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveAllKeysInput;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveAllKeysOutput;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveAllMappings;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveAllMappingsInput;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveAllMappingsOutput;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveAllOperationalContent;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveAllOperationalContentInput;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveAllOperationalContentOutput;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveAllOperationalContentOutputBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKey;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKeyInput;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKeyOutput;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKeyOutputBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKeys;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKeysInput;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKeysOutput;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMapping;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMappingInput;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMappingOutput;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMappingOutputBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMappings;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMappingsInput;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMappingsOutput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKey;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKeyInput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKeyOutput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKeyOutputBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKeys;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKeysInput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKeysOutput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMapping;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMappingInput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMappingOutput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMappingOutputBuilder;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMappings;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMappingsInput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMappingsOutput;
118 import org.opendaylight.yangtools.concepts.Registration;
119 import org.opendaylight.yangtools.yang.common.ErrorTag;
120 import org.opendaylight.yangtools.yang.common.ErrorType;
121 import org.opendaylight.yangtools.yang.common.RpcResult;
122 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
123 import org.osgi.service.component.annotations.Activate;
124 import org.osgi.service.component.annotations.Component;
125 import org.osgi.service.component.annotations.Deactivate;
126 import org.osgi.service.component.annotations.Reference;
127 import org.slf4j.Logger;
128 import org.slf4j.LoggerFactory;
129
130 /**
131  * Dispatcher of API calls that implements the RPC and Java APIs in mappingservice.yang and IMappingService
132  * respectively. It also coordinates and acts as container for all objects in charge of
133  *  - saving and updating md-sal datastore stored mappings
134  *  - monitoring md-sal datastore mapping updates and pushing them to the in memory mapping-system
135  *  - in memory mapping-system
136  *
137  * @author Lorand Jakab
138  * @author Florin Coras
139  *
140  */
141 @Component(service = IMappingService.class, immediate = true, property = "type=default")
142 @Singleton
143 public class MappingService implements IMappingService, AutoCloseable {
144     private static final Logger LOG = LoggerFactory.getLogger(MappingService.class);
145
146     private MappingSystem mappingSystem;
147     private DataStoreBackEnd dsbe;
148     private AuthenticationKeyDataListener keyListener;
149     private MappingDataListener mappingListener;
150
151     @Reference
152     private volatile ILispDAO dao;
153     @Reference
154     private volatile DataBroker dataBroker;
155     @Reference
156     private volatile RpcProviderService rpcProviderService;
157     @Reference
158     private volatile NotificationPublishService notificationPublishService;
159     private Registration rpcRegistration;
160
161     private boolean mappingMergePolicy = ConfigIni.getInstance().mappingMergeIsSet();
162     private final boolean notificationPolicy = ConfigIni.getInstance().smrIsSet();
163     private final boolean iterateMask = true;
164     private boolean isMaster = false;
165
166     @Override
167     public void setMappingMerge(boolean mergeMapping) {
168         this.mappingMergePolicy = mergeMapping;
169         if (mappingSystem != null) {
170             mappingSystem.setMappingMerge(mergeMapping);
171             ConfigIni.getInstance().setMappingMerge(mappingMergePolicy);
172         }
173     }
174
175     @Override
176     public void setLookupPolicy(IMappingService.LookupPolicy policy) {
177         ConfigIni.getInstance().setLookupPolicy(policy);
178     }
179
180     @Activate
181     public void initialize() {
182         LOG.info("Mapping Service initializing...");
183         dsbe = new DataStoreBackEnd(dataBroker);
184
185         rpcRegistration = rpcProviderService.registerRpcImplementations(
186             (AddKey) this::addKey,
187             (GetKey) this::getKey,
188             (UpdateKey) this::updateKey,
189             (RemoveKey) this::removeKey,
190             (AddMapping) this::addMapping,
191             (GetMapping) this::getMapping,
192             (GetMappingWithXtrId) this::getMappingWithXtrId,
193             (UpdateMapping) this::updateMapping,
194             (RemoveMapping) this::removeMapping,
195             (AddKeys) this::addKeys,
196             (GetKeys) this::getKeys,
197             (UpdateKeys) this::updateKeys,
198             (RemoveKeys) this::removeKeys,
199             (AddMappings) this::addMappings,
200             (GetMappings) this::getMappings,
201             (UpdateMappings) this::updateMappings,
202             (RemoveMappings) this::removeMappings,
203             (GetAllKeys) this::getAllKeys,
204             (GetAllMappings) this::getAllMappings,
205             (RemoveAllKeys) this::removeAllKeys,
206             (RemoveAllMappings) this::removeAllMappings,
207             (RemoveAllOperationalContent) this::removeAllOperationalContent);
208
209         mappingSystem = new MappingSystem(dao, iterateMask, notificationPublishService, mappingMergePolicy);
210         mappingSystem.setDataStoreBackEnd(dsbe);
211         mappingSystem.initialize();
212
213         keyListener = new AuthenticationKeyDataListener(dataBroker, mappingSystem);
214         mappingListener = new MappingDataListener(dataBroker, mappingSystem, notificationPublishService);
215         LOG.info("Mapping Service loaded.");
216     }
217
218     @VisibleForTesting
219     ListenableFuture<RpcResult<AddKeyOutput>> addKey(AddKeyInput input) {
220         requireNonNull(input, "add-key RPC input must be not null!");
221         LOG.trace("RPC received to add the following key: {}", input);
222
223         RpcResultBuilder<AddKeyOutput> rpcResultBuilder;
224
225         MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
226
227         if (key != null) {
228             String message = "Key already exists! Please use update-key if you want to change it.";
229             rpcResultBuilder = RpcResultBuilder.<AddKeyOutput>failed()
230                     .withError(ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS, message);
231             return rpcResultBuilder.buildFuture();
232         }
233
234         dsbe.addAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
235         rpcResultBuilder = RpcResultBuilder.success(new AddKeyOutputBuilder().build());
236
237         return rpcResultBuilder.buildFuture();
238     }
239
240     ListenableFuture<RpcResult<AddMappingOutput>> addMapping(AddMappingInput input) {
241         requireNonNull(input, "add-mapping RPC input must be not null!");
242         LOG.trace("RPC received to add the following mapping: {}", input);
243
244         dsbe.addMapping(RPCInputConvertorUtil.toMapping(input));
245
246         RpcResultBuilder<AddMappingOutput> rpcResultBuilder;
247
248         rpcResultBuilder = RpcResultBuilder.success(new AddMappingOutputBuilder().build());
249
250         return rpcResultBuilder.buildFuture();
251     }
252
253     @Override
254     public void addMapping(MappingOrigin origin, Eid key, SiteId siteId, MappingData mappingData) {
255         // SB registrations are first written to the MappingSystem and only afterwards are persisted to the datastore
256         if (origin.equals(MappingOrigin.Southbound)) {
257             // Store data first in MapCache and only afterwards persist to datastore. This should be used only for SB
258             // registrations
259             mappingSystem.addMapping(origin, key, mappingData);
260             dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, mappingData));
261             if (mappingData.getXtrId() != null) {
262                 dsbe.addXtrIdMapping(DSBEInputUtil.toXtrIdMapping(mappingData));
263             }
264         } else {
265             dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, mappingData));
266         }
267     }
268
269     @Override
270     public MappingData addNegativeMapping(Eid key) {
271         return mappingSystem.addNegativeMapping(key);
272     }
273
274     @Override
275     public void refreshMappingRegistration(Eid key, XtrId xtrId, Long timestamp) {
276         mappingSystem.refreshMappingRegistration(key, xtrId, timestamp);
277     }
278
279     ListenableFuture<RpcResult<GetKeyOutput>> getKey(GetKeyInput input) {
280         requireNonNull(input, "get-key RPC input must be not null!");
281         LOG.trace("RPC received to get the following key: {}", input);
282
283         RpcResultBuilder<GetKeyOutput> rpcResultBuilder;
284
285         MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
286
287         if (key == null) {
288             String message = "Key was not found in the mapping database";
289             rpcResultBuilder = RpcResultBuilder.<GetKeyOutput>failed()
290                     .withError(ErrorType.APPLICATION, ErrorTag.DATA_MISSING, message);
291         } else {
292             rpcResultBuilder = RpcResultBuilder.success(new GetKeyOutputBuilder().setMappingAuthkey(key).build());
293         }
294
295         return rpcResultBuilder.buildFuture();
296     }
297
298     ListenableFuture<RpcResult<GetMappingOutput>> getMapping(GetMappingInput input) {
299         requireNonNull(input, "get-mapping RPC input must be not null!");
300         LOG.trace("RPC received to get the following mapping: {}", input);
301
302         RpcResultBuilder<GetMappingOutput> rpcResultBuilder;
303
304         MappingData reply = mappingSystem.getMapping(convertToBinaryIfNecessary(input.getEid()));
305
306         if (reply == null) {
307             String message = "No mapping was found in the mapping database";
308             rpcResultBuilder = RpcResultBuilder.<GetMappingOutput>failed()
309                     .withError(ErrorType.APPLICATION, ErrorTag.DATA_MISSING, message);
310         } else {
311             final MappingRecord convertedReply = convertFromBinaryIfNecessary(reply.getRecord());
312             rpcResultBuilder = RpcResultBuilder.success(
313                 new GetMappingOutputBuilder().setMappingRecord(convertedReply).build());
314         }
315
316         return rpcResultBuilder.buildFuture();
317     }
318
319     @Override
320     public MappingData getMapping(MappingOrigin origin, Eid key) {
321         return mappingSystem.getMapping(origin, key);
322     }
323
324     @Override
325     public MappingData getMapping(Eid key) {
326         return mappingSystem.getMapping(key);
327     }
328
329     @Override
330     public MappingData getMapping(Eid srcKey, Eid dstKey) {
331         return mappingSystem.getMapping(srcKey, dstKey);
332     }
333
334     @Override
335     public void subscribe(Subscriber subscriber, Eid subscribedEid) {
336         mappingSystem.subscribe(subscriber, subscribedEid);
337     }
338
339     @Override
340     public Set<Subscriber> getSubscribers(Eid eid) {
341         return mappingSystem.getSubscribers(eid);
342     }
343
344     private ListenableFuture<RpcResult<GetMappingWithXtrIdOutput>> getMappingWithXtrId(GetMappingWithXtrIdInput input) {
345         requireNonNull(input, "get-mapping RPC input must be not null!");
346         LOG.trace("RPC received to get the following mapping: {}", input);
347
348         RpcResultBuilder<GetMappingWithXtrIdOutput> rpcResultBuilder;
349
350         MappingData reply = mappingSystem.getMapping(null, convertToBinaryIfNecessary(input.getEid()),
351                 input.getXtrId());
352
353         if (reply == null) {
354             String message = "No mapping was found in the mapping database";
355             rpcResultBuilder = RpcResultBuilder.<GetMappingWithXtrIdOutput>failed()
356                     .withError(ErrorType.APPLICATION, ErrorTag.DATA_MISSING, message);
357         } else {
358             final MappingRecord convertedReply = convertFromBinaryIfNecessary(reply.getRecord());
359             rpcResultBuilder = RpcResultBuilder.success(new GetMappingWithXtrIdOutputBuilder()
360                     .setMappingRecord(convertedReply).build());
361         }
362
363         return rpcResultBuilder.buildFuture();
364     }
365
366     ListenableFuture<RpcResult<RemoveKeyOutput>> removeKey(RemoveKeyInput input) {
367         requireNonNull(input, "remove-key RPC input must be not null!");
368         LOG.trace("RPC received to remove the following key: {}", input);
369
370         RpcResultBuilder<RemoveKeyOutput> rpcResultBuilder;
371
372         dsbe.removeAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
373
374         rpcResultBuilder = RpcResultBuilder.success(new RemoveKeyOutputBuilder().build());
375
376         return rpcResultBuilder.buildFuture();
377     }
378
379     ListenableFuture<RpcResult<RemoveMappingOutput>> removeMapping(RemoveMappingInput input) {
380         requireNonNull(input, "remove-mapping RPC input must be not null!");
381         LOG.trace("RPC received to remove the following mapping: {}", input);
382
383         RpcResultBuilder<RemoveMappingOutput> rpcResultBuilder;
384
385         dsbe.removeMapping(RPCInputConvertorUtil.toMapping(input));
386
387         rpcResultBuilder = RpcResultBuilder.success(new RemoveMappingOutputBuilder().build());
388
389         return rpcResultBuilder.buildFuture();
390     }
391
392     @Override
393     public void removeMapping(MappingOrigin origin, Eid key) {
394         if (origin.equals(MappingOrigin.Southbound)) {
395             mappingSystem.removeMapping(origin, key);
396         }
397         dsbe.removeMapping(DSBEInputUtil.toMapping(origin, key));
398     }
399
400     ListenableFuture<RpcResult<UpdateKeyOutput>> updateKey(UpdateKeyInput input) {
401         requireNonNull(input, "update-key RPC input must be not null!");
402         LOG.trace("RPC received to update the following key: {}", input);
403
404         RpcResultBuilder<UpdateKeyOutput> rpcResultBuilder;
405
406         MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
407
408         if (key == null) {
409             String message = "Key doesn't exist! Please use add-key if you want to create a new authentication key.";
410             rpcResultBuilder = RpcResultBuilder.<UpdateKeyOutput>failed()
411                     .withError(ErrorType.PROTOCOL, ErrorTag.DATA_MISSING, message);
412             return rpcResultBuilder.buildFuture();
413         }
414
415         dsbe.updateAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
416         rpcResultBuilder = RpcResultBuilder.success(new UpdateKeyOutputBuilder().build());
417
418         return rpcResultBuilder.buildFuture();
419     }
420
421     ListenableFuture<RpcResult<UpdateMappingOutput>> updateMapping(UpdateMappingInput input) {
422         LOG.trace("RPC received to update the following mapping: {}", input);
423         requireNonNull(input, "update-mapping RPC input must be not null!");
424
425         RpcResultBuilder<UpdateMappingOutput> rpcResultBuilder;
426
427         dsbe.updateMapping(RPCInputConvertorUtil.toMapping(input));
428
429         rpcResultBuilder = RpcResultBuilder.success(new UpdateMappingOutputBuilder().build());
430
431         return rpcResultBuilder.buildFuture();
432     }
433
434     ListenableFuture<RpcResult<RemoveKeysOutput>> removeKeys(RemoveKeysInput input) {
435         // TODO Auto-generated method stub
436         return null;
437     }
438
439     ListenableFuture<RpcResult<RemoveMappingsOutput>> removeMappings(RemoveMappingsInput input) {
440         // TODO Auto-generated method stub
441         return null;
442     }
443
444     ListenableFuture<RpcResult<GetKeysOutput>> getKeys(GetKeysInput input) {
445         // TODO Auto-generated method stub
446         return null;
447     }
448
449     ListenableFuture<RpcResult<AddMappingsOutput>> addMappings(AddMappingsInput input) {
450         // TODO Auto-generated method stub
451         return null;
452     }
453
454     ListenableFuture<RpcResult<UpdateKeysOutput>> updateKeys(UpdateKeysInput input) {
455         // TODO Auto-generated method stub
456         return null;
457     }
458
459     ListenableFuture<RpcResult<RemoveAllMappingsOutput>> removeAllMappings(RemoveAllMappingsInput input) {
460         // TODO Auto-generated method stub
461         return null;
462     }
463
464     private ListenableFuture<RpcResult<RemoveAllKeysOutput>> removeAllKeys(RemoveAllKeysInput input) {
465         // TODO Auto-generated method stub
466         return null;
467     }
468
469     ListenableFuture<RpcResult<GetAllKeysOutput>> getAllKeys(GetAllKeysInput input) {
470         // TODO Auto-generated method stub
471         return null;
472     }
473
474     ListenableFuture<RpcResult<UpdateMappingsOutput>> updateMappings(UpdateMappingsInput input) {
475         // TODO Auto-generated method stub
476         return null;
477     }
478
479     ListenableFuture<RpcResult<AddKeysOutput>> addKeys(AddKeysInput input) {
480         // TODO Auto-generated method stub
481         return null;
482     }
483
484     ListenableFuture<RpcResult<GetAllMappingsOutput>> getAllMappings(GetAllMappingsInput input) {
485         // TODO Auto-generated method stub
486         return null;
487     }
488
489     private ListenableFuture<RpcResult<GetMappingsOutput>> getMappings(
490             GetMappingsInput input) {
491         // TODO Auto-generated method stub
492         return null;
493     }
494
495     private ListenableFuture<RpcResult<RemoveAllOperationalContentOutput>> removeAllOperationalContent(
496             RemoveAllOperationalContentInput input) {
497         RpcResultBuilder<RemoveAllOperationalContentOutput> rpcResultBuilder;
498
499         /*
500          * Since master nodes ignore datastore changes for southbound originated mappings, they need to be removed
501          * explicitly.
502          */
503         if (isMaster) {
504             mappingSystem.cleanSBMappings();
505         }
506         dsbe.removeAllOperationalDatastoreContent();
507
508         rpcResultBuilder = RpcResultBuilder.success(new RemoveAllOperationalContentOutputBuilder().build());
509
510         return rpcResultBuilder.buildFuture();
511     }
512
513     @Override
514     public Eid getWidestNegativePrefix(Eid key) {
515         return mappingSystem.getWidestNegativePrefix(key);
516     }
517
518     @Override
519     public Set<Eid> getSubtree(MappingOrigin origin, Eid key) {
520         return mappingSystem.getSubtree(origin, key);
521     }
522
523     @Override
524     public void addAuthenticationKey(Eid key, MappingAuthkey authKey) {
525         dsbe.addAuthenticationKey(DSBEInputUtil.toAuthenticationKey(key, authKey));
526     }
527
528     @Override
529     public MappingAuthkey getAuthenticationKey(Eid key) {
530         return mappingSystem.getAuthenticationKey(key);
531     }
532
533     @Override
534     public void removeAuthenticationKey(Eid key) {
535         dsbe.removeAuthenticationKey(DSBEInputUtil.toAuthenticationKey(key, null));
536     }
537
538     @Override
539     public void addData(MappingOrigin origin, Eid key, String subKey, Object data) {
540         mappingSystem.addData(origin, key, subKey, data);
541     }
542
543     @Override
544     public Object getData(MappingOrigin origin, Eid key, String subKey) {
545         return mappingSystem.getData(origin, key, subKey);
546     }
547
548     @Override
549     public void removeData(MappingOrigin origin, Eid key, String subKey) {
550         mappingSystem.removeData(origin, key, subKey);
551     }
552
553     @Override
554     public Eid getParentPrefix(Eid key) {
555         return mappingSystem.getParentPrefix(key);
556     }
557
558     @Override
559     public String printMappings() {
560         return mappingSystem.printMappings();
561     }
562
563     @Override
564     public String prettyPrintMappings() {
565         return mappingSystem.prettyPrintMappings();
566     }
567
568     @Override
569     public String printKeys() {
570         return mappingSystem.printKeys();
571     }
572
573     @Override
574     public String prettyPrintKeys() {
575         return mappingSystem.prettyPrintKeys();
576     }
577
578     @PreDestroy
579     @Deactivate
580     @Override
581     public void close() throws Exception {
582         LOG.info("Mapping Service is being destroyed!");
583         rpcRegistration.close();
584         keyListener.closeDataChangeListener();
585         mappingListener.closeDataChangeListener();
586         mappingSystem.destroy();
587     }
588
589     @Override
590     public void cleanCachedMappings() {
591         mappingSystem.cleanCaches();
592         dsbe.removeAllDatastoreContent();
593     }
594
595     private static Eid convertToBinaryIfNecessary(Eid eid) {
596         if (LispAddressUtil.addressNeedsConversionToBinary(eid.getAddress())) {
597             return LispAddressUtil.convertToBinary(eid);
598         }
599         return eid;
600     }
601
602     private static MappingRecord convertFromBinaryIfNecessary(MappingRecord originalRecord) {
603         List<LocatorRecord> originalLocators = originalRecord.getLocatorRecord();
604
605         List<LocatorRecord> convertedLocators = null;
606         if (originalLocators != null) {
607             // If convertedLocators is non-null, while originalLocators is also non-null, conversion has been made
608             convertedLocators = convertFromBinaryIfNecessary(originalLocators);
609         }
610
611         if (LispAddressUtil.addressNeedsConversionFromBinary(originalRecord.getEid().getAddress())
612                 || originalLocators != null && convertedLocators != null) {
613             MappingRecordBuilder mrb = new MappingRecordBuilder(originalRecord);
614             mrb.setEid(LispAddressUtil.convertFromBinary(originalRecord.getEid()));
615             if (convertedLocators != null) {
616                 mrb.setLocatorRecord(convertedLocators);
617             }
618             return mrb.build();
619         }
620         return originalRecord;
621     }
622
623     private static List<LocatorRecord> convertFromBinaryIfNecessary(List<LocatorRecord> originalLocators) {
624         List<LocatorRecord> convertedLocators = null;
625         for (LocatorRecord record : originalLocators) {
626             if (LispAddressUtil.addressNeedsConversionFromBinary(record.getRloc().getAddress())) {
627                 LocatorRecordBuilder lrb = new LocatorRecordBuilder(record);
628                 lrb.setRloc(LispAddressUtil.convertFromBinary(record.getRloc()));
629                 if (convertedLocators == null) {
630                     convertedLocators = new ArrayList<>();
631                 }
632                 convertedLocators.add(lrb.build());
633             }
634         }
635         if (convertedLocators != null) {
636             return convertedLocators;
637         }
638         return originalLocators;
639     }
640
641     @Override
642     public void setIsMaster(boolean isMaster) {
643         this.isMaster = isMaster;
644         mappingSystem.setIsMaster(isMaster);
645     }
646
647     @Override
648     public boolean isMaster() {
649         return isMaster;
650     }
651 }