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