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