2 * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
9 package org.opendaylight.idmanager;
11 import java.util.Collections;
12 import java.util.Comparator;
13 import java.util.LinkedList;
14 import java.util.List;
15 import java.util.NoSuchElementException;
16 import java.util.concurrent.Future;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutputBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.DeleteIdPoolInput;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolderBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPools;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntries;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolderBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntries;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntriesBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
42 import org.opendaylight.yangtools.concepts.ListenerRegistration;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
44 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
45 import org.opendaylight.yangtools.yang.common.RpcResult;
46 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
50 import com.google.common.base.Optional;
51 import com.google.common.util.concurrent.Futures;
53 public class IdManager implements IdManagerService, AutoCloseable{
54 private static final Logger LOG = LoggerFactory.getLogger(IdManager.class);
56 private static final long DEFAULT_IDLE_TIME = 24 * 60 * 60;
58 private ListenerRegistration<DataChangeListener> listenerRegistration;
59 private final DataBroker broker;
60 private LockManagerService lockManager;
63 public void close() throws Exception {
64 if (listenerRegistration != null) {
66 listenerRegistration.close();
67 } catch (final Exception e) {
68 LOG.error("Error when cleaning up DataChangeListener.", e);
70 listenerRegistration = null;
72 LOG.info("IDManager Closed");
75 public IdManager(final DataBroker db) {
79 public void setLockManager(LockManagerService lockManager) {
80 this.lockManager = lockManager;
84 public Future<RpcResult<Void>> createIdPool(CreateIdPoolInput input) {
85 LOG.debug("createIdPool called with input {}", input);
86 String poolName = input.getPoolName();
87 long low = input.getLow();
88 long high = input.getHigh();
89 long blockSize = IdUtils.computeBlockSize(low, high);
90 RpcResultBuilder<Void> createIdPoolRpcBuilder;
91 IdUtils.lockPool(lockManager, poolName);
93 InstanceIdentifier<IdPool> idPoolInstanceIdentifier = IdUtils.getIdPoolInstance(poolName);
94 poolName = poolName.intern();
96 idPool = createGlobalPool(poolName, low, high, blockSize, idPoolInstanceIdentifier);
97 String localPoolName = IdUtils.getLocalPoolName(poolName);
98 if (createLocalPool(localPoolName, idPool)) {
99 LOG.debug("Updating global id pool {} with childPool {}", poolName, localPoolName);
100 updateChildPool(poolName, localPoolName);
102 createIdPoolRpcBuilder = RpcResultBuilder.success();
103 } catch (Exception ex) {
104 LOG.error("Creation of Id Pool {} failed due to {}", poolName, ex);
105 createIdPoolRpcBuilder = RpcResultBuilder.failed();
106 createIdPoolRpcBuilder.withError(ErrorType.APPLICATION, ex.getMessage());
108 IdUtils.unlockPool(lockManager, poolName);
110 return Futures.immediateFuture(createIdPoolRpcBuilder.build());
114 public Future<RpcResult<AllocateIdOutput>> allocateId(AllocateIdInput input) {
115 LOG.debug("AllocateId called with input {}", input);
116 String idKey = input.getIdKey();
117 String poolName = input.getPoolName();
118 String localPoolName = IdUtils.getLocalPoolName(poolName);
119 RpcResultBuilder<AllocateIdOutput> allocateIdRpcBuilder;
120 long newIdValue = -1;
121 AllocateIdOutputBuilder output = new AllocateIdOutputBuilder();
123 newIdValue = allocateIdFromLocalPool(poolName, localPoolName, idKey);
124 output.setIdValue(newIdValue);
125 allocateIdRpcBuilder = RpcResultBuilder.success();
126 allocateIdRpcBuilder.withResult(output.build());
127 } catch (Exception ex) {
128 LOG.error("Allocate id in pool {} failed due to {}", poolName, ex);
129 allocateIdRpcBuilder = RpcResultBuilder.failed();
130 allocateIdRpcBuilder.withError(ErrorType.APPLICATION, ex.getMessage());
132 return Futures.immediateFuture(allocateIdRpcBuilder.build());
136 public Future<RpcResult<Void>> deleteIdPool(DeleteIdPoolInput input) {
137 LOG.debug("DeleteIdPool called with input {}", input);
138 String poolName = input.getPoolName();
139 RpcResultBuilder<Void> deleteIdPoolRpcBuilder;
141 InstanceIdentifier<IdPool> idPoolToBeDeleted = IdUtils.getIdPoolInstance(poolName);
142 poolName = poolName.intern();
143 synchronized(poolName) {
144 IdPool idPool = getIdPool(idPoolToBeDeleted);
145 List<ChildPools> childPoolList = idPool.getChildPools();
146 if (childPoolList != null) {
147 for (ChildPools childPoolName : childPoolList) {
148 deletePool(childPoolName.getChildPoolName());
151 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, idPoolToBeDeleted);
152 LOG.debug("Deleted id pool {}", poolName);
154 deleteIdPoolRpcBuilder = RpcResultBuilder.success();
156 catch (Exception ex) {
157 LOG.error("Delete id in pool {} failed due to {}", poolName, ex);
158 deleteIdPoolRpcBuilder = RpcResultBuilder.failed();
159 deleteIdPoolRpcBuilder.withError(ErrorType.APPLICATION, ex.getMessage());
161 return Futures.immediateFuture(deleteIdPoolRpcBuilder.build());
165 public Future<RpcResult<Void>> releaseId(ReleaseIdInput input) {
166 String poolName = input.getPoolName();
167 String idKey = input.getIdKey();
168 RpcResultBuilder<Void> releaseIdRpcBuilder;
170 releaseIdFromLocalPool(IdUtils.getLocalPoolName(poolName), idKey);
171 releaseIdRpcBuilder = RpcResultBuilder.success();
172 } catch (Exception ex) {
173 LOG.error("Release id {} from pool {} failed due to {}", idKey, poolName, ex);
174 releaseIdRpcBuilder = RpcResultBuilder.failed();
175 releaseIdRpcBuilder.withError(ErrorType.APPLICATION, ex.getMessage());
177 return Futures.immediateFuture(releaseIdRpcBuilder.build());
180 private long allocateIdFromLocalPool(String parentPoolName, String localPoolName, String idKey) {
181 LOG.trace("Allocating id from local pool {}. Parent pool {}. Idkey {}", localPoolName, parentPoolName, idKey);
182 long newIdValue = -1;
183 InstanceIdentifier<IdPool> localIdPoolInstanceIdentifier = IdUtils.getIdPoolInstance(localPoolName);
184 localPoolName = localPoolName.intern();
185 synchronized (localPoolName) {
186 InstanceIdentifier<IdPool> parentIdPoolInstanceIdentifier = IdUtils.getIdPoolInstance(parentPoolName);
187 IdPool parentIdPool = getIdPool(parentIdPoolInstanceIdentifier);
188 IdPool localPool = null;
190 localPool = getIdPool(localIdPoolInstanceIdentifier);
191 } catch (NoSuchElementException e){
192 LOG.trace("Creating local pool {} since it was not present", localPoolName);
193 localPool = IdUtils.createLocalIdPool(localPoolName, parentIdPool);
194 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, localIdPoolInstanceIdentifier, localPool);
195 IdUtils.lockPool(lockManager, parentPoolName);
197 updateChildPool(parentPoolName, localPoolName);
199 IdUtils.unlockPool(lockManager, parentPoolName);
201 LOG.debug("Updating global id pool {} with childPool {}", parentPoolName, localPoolName);
203 IdEntries newIdEntry;
204 List<IdEntries> idEntries = parentIdPool.getIdEntries();
205 AvailableIdsHolderBuilder availableIds = IdUtils.getAvailableIdsHolderBuilder(localPool);
206 ReleasedIdsHolderBuilder releasedIds = IdUtils.getReleaseIdsHolderBuilder(localPool);
207 //Calling cleanupExcessIds since there could be excessive ids.
208 cleanupExcessIds(availableIds, releasedIds, parentPoolName, localPool.getBlockSize());
209 if (idEntries == null) {
210 idEntries = new LinkedList<IdEntries>();
212 InstanceIdentifier<IdEntries> existingId = IdUtils.getIdEntry(parentIdPoolInstanceIdentifier, idKey);
213 Optional<IdEntries> existingIdEntry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, existingId);
214 if (existingIdEntry.isPresent()) {
215 newIdValue = existingIdEntry.get().getIdValue();
216 LOG.debug("Existing id {} for the key {} ", idKey, newIdValue);
217 InstanceIdentifier<ReleasedIdsHolder> releasedIdsHolderInstanceIdentifier = InstanceIdentifier
218 .builder(IdPools.class).child(IdPool.class, new IdPoolKey(localPoolName)).child(ReleasedIdsHolder.class).build();
219 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, releasedIdsHolderInstanceIdentifier, releasedIds.build());
223 newIdValue = getIdFromPool(localPool, availableIds, releasedIds);
224 LOG.debug("The newIdValue {} for the idKey {}", newIdValue, idKey);
225 newIdEntry = IdUtils.createIdEntries(idKey, newIdValue);
226 idEntries.add(newIdEntry);
227 LOG.debug("The availablelIds are {}", availableIds.build());
228 localPool = new IdPoolBuilder(localPool).setAvailableIdsHolder(availableIds.build())
229 .setReleasedIdsHolder(releasedIds.build()).build();
230 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, localIdPoolInstanceIdentifier, localPool);
231 updateChildPool(localPool.getParentPoolName(), localPoolName);
232 //Updating id entries in the parent pool. This will be used for restart scenario
233 IdUtils.lockPool(lockManager, parentPoolName);
235 parentIdPool = getIdPool(parentIdPoolInstanceIdentifier);
236 IdPool parentPool = new IdPoolBuilder(parentIdPool).setIdEntries(idEntries).build();
237 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, parentIdPoolInstanceIdentifier, parentPool);
238 } catch (Exception ex) {
239 LOG.error("Saving of Id entries to parent pool {} failed due to {}", parentPoolName, ex);
241 IdUtils.unlockPool(lockManager, parentPoolName);
247 private long getIdFromPool(IdPool pool, AvailableIdsHolderBuilder availableIds, ReleasedIdsHolderBuilder releasedIds) {
248 long newIdValue = -1;
250 newIdValue = IdUtils.getIdFromReleaseIdsIfAvailable(releasedIds);
251 if (newIdValue != -1) {
252 LOG.debug("Retrieved id value {} from released id holder", newIdValue);
255 newIdValue = IdUtils.getIdFromAvailableIds(availableIds);
256 if (newIdValue != -1) {
257 LOG.debug("Creating a new id {} for the pool: {} ", newIdValue, pool.getPoolName());
260 long idCount = allocateIdBlockFromParentPool(pool.getParentPoolName(), availableIds, releasedIds);
262 LOG.debug("Unable to allocate Id block from global pool");
263 throw new RuntimeException(String.format("Ids exhausted for pool : %s", pool.getPoolName()));
269 * Changes made to releaseIds and AvailableIds are not persisted.
270 * @param availableIds
272 * @param parentPoolName
275 private void cleanupExcessIds(AvailableIdsHolderBuilder availableIds, ReleasedIdsHolderBuilder releasedIds, String parentPoolName, int blockSize) {
276 IdUtils.processDelayList(releasedIds);
277 long totalAvailableIdCount = releasedIds.getAvailableIdCount() + IdUtils.getAvailableIdsCount(availableIds);
278 if (totalAvailableIdCount > blockSize * 2) {
279 parentPoolName = parentPoolName.intern();
280 InstanceIdentifier<ReleasedIdsHolder> releasedIdInstanceIdentifier = IdUtils.getReleasedIdsHolderInstance(parentPoolName);
281 IdUtils.lockPool(lockManager, parentPoolName);
283 Optional<ReleasedIdsHolder> releasedIdsHolder = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, releasedIdInstanceIdentifier);
284 ReleasedIdsHolderBuilder releasedIdsParent;
285 if (!releasedIdsHolder.isPresent()) {
286 LOG.error("ReleasedIds not present in parent pool. Unable to cleanup excess ids");
289 releasedIdsParent = new ReleasedIdsHolderBuilder(releasedIdsHolder.get());
290 LOG.debug("Releasing excesss Ids from local pool");
291 IdUtils.freeExcessAvailableIds(releasedIds, releasedIdsParent, blockSize);
292 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, releasedIdInstanceIdentifier, releasedIdsParent.build());
294 IdUtils.unlockPool(lockManager, parentPoolName);
300 * Changes made to availableIds and releasedIds will not be persisted to the datastore
301 * @param parentPoolName
302 * @param availableIdsBuilder
303 * @param releasedIdsBuilder
306 private long allocateIdBlockFromParentPool(String parentPoolName,
307 AvailableIdsHolderBuilder availableIdsBuilder, ReleasedIdsHolderBuilder releasedIdsBuilder) {
308 LOG.debug("Allocating block of id from parent pool {}", parentPoolName);
309 InstanceIdentifier<IdPool> idPoolInstanceIdentifier = IdUtils.getIdPoolInstance(parentPoolName);
310 parentPoolName = parentPoolName.intern();
312 IdUtils.lockPool(lockManager, parentPoolName);
314 IdPool parentIdPool = getIdPool(idPoolInstanceIdentifier);
315 ReleasedIdsHolderBuilder releasedIdsBuilderParent = IdUtils.getReleaseIdsHolderBuilder(parentIdPool);
317 idCount = allocateIdBlockFromReleasedIdsHolder(releasedIdsBuilder, releasedIdsBuilderParent, parentIdPool);
321 idCount = allocateIdBlockFromAvailableIdsHolder(availableIdsBuilder, parentIdPool);
325 idCount = getIdsFromOtherChildPools(releasedIdsBuilderParent, parentIdPool);
327 LOG.debug("Unable to allocate Id block from global pool");
328 throw new RuntimeException(String.format("Ids exhausted for pool : %s", parentPoolName));
333 IdUtils.unlockPool(lockManager, parentPoolName);
337 private long getIdsFromOtherChildPools(ReleasedIdsHolderBuilder releasedIdsBuilderParent, IdPool parentIdPool) {
338 List<ChildPools> childPoolsList = parentIdPool.getChildPools();
339 // Sorting the child pools on last accessed time so that the pool that was not accessed for a long time comes first.
340 Collections.sort(childPoolsList, new Comparator<ChildPools>() {
342 public int compare(ChildPools childPool1, ChildPools childPool2) {
343 return childPool1.getLastAccessTime().compareTo(childPool2.getLastAccessTime());
346 long currentTime = System.currentTimeMillis() / 1000;
347 for (ChildPools childPools : childPoolsList) {
348 if (childPools.getLastAccessTime() + DEFAULT_IDLE_TIME < currentTime) {
351 if (!childPools.getChildPoolName().equals(IdUtils.getLocalPoolName(parentIdPool.getPoolName()))) {
352 InstanceIdentifier<IdPool> idPoolInstanceIdentifier = IdUtils.getIdPoolInstance(childPools.getChildPoolName());
353 IdPool otherChildPool = getIdPool(idPoolInstanceIdentifier);
354 ReleasedIdsHolderBuilder releasedIds = IdUtils.getReleaseIdsHolderBuilder(otherChildPool);
355 AvailableIdsHolderBuilder availableIds = IdUtils.getAvailableIdsHolderBuilder(otherChildPool);
356 long totalAvailableIdCount = releasedIds.getDelayedIdEntries().size() + IdUtils.getAvailableIdsCount(availableIds);
357 List<DelayedIdEntries> delayedIdEntriesChild = releasedIds.getDelayedIdEntries();
358 List<DelayedIdEntries> delayedIdEntriesParent = releasedIdsBuilderParent.getDelayedIdEntries();
359 if (delayedIdEntriesParent == null) {
360 delayedIdEntriesParent = new LinkedList<>();
362 delayedIdEntriesParent.addAll(delayedIdEntriesChild);
363 delayedIdEntriesChild.removeAll(delayedIdEntriesChild);
364 while (IdUtils.isIdAvailable(availableIds)) {
365 long cursor = availableIds.getCursor() + 1;
366 delayedIdEntriesParent.add(new DelayedIdEntriesBuilder().setId(cursor).setReadyTimeSec(System.currentTimeMillis()).build());
367 availableIds.setCursor(cursor);
369 long count = releasedIdsBuilderParent.getAvailableIdCount() + totalAvailableIdCount;
370 releasedIdsBuilderParent.setDelayedIdEntries(delayedIdEntriesParent).setAvailableIdCount(count);
371 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier,
372 new IdPoolBuilder(otherChildPool).setAvailableIdsHolder(availableIds.build()).setReleasedIdsHolder(releasedIds.build()).build());
373 return totalAvailableIdCount;
379 private long allocateIdBlockFromReleasedIdsHolder(ReleasedIdsHolderBuilder releasedIdsBuilderChild, ReleasedIdsHolderBuilder releasedIdsBuilderParent, IdPool parentIdPool) {
380 if (releasedIdsBuilderParent.getAvailableIdCount() == 0) {
381 LOG.debug("Ids unavailable in releasedIds of parent pool {}", parentIdPool);
384 List<DelayedIdEntries> delayedIdEntriesParent = releasedIdsBuilderParent.getDelayedIdEntries();
385 List<DelayedIdEntries> delayedIdEntriesChild = releasedIdsBuilderChild.getDelayedIdEntries();
386 if (delayedIdEntriesChild == null) {
387 delayedIdEntriesChild = new LinkedList<DelayedIdEntries>();
389 int idCount = Math.min(delayedIdEntriesParent.size(), parentIdPool.getBlockSize());
390 List<DelayedIdEntries> idEntriesToBeRemoved = delayedIdEntriesParent.subList(0, idCount);
391 delayedIdEntriesChild.addAll(0, idEntriesToBeRemoved);
392 delayedIdEntriesParent.removeAll(idEntriesToBeRemoved);
393 releasedIdsBuilderParent.setDelayedIdEntries(delayedIdEntriesParent);
394 releasedIdsBuilderChild.setDelayedIdEntries(delayedIdEntriesChild);
395 releasedIdsBuilderChild.setAvailableIdCount(releasedIdsBuilderChild.getAvailableIdCount() + idCount);
396 InstanceIdentifier<ReleasedIdsHolder> releasedIdsHolderInstanceIdentifier = InstanceIdentifier
397 .builder(IdPools.class).child(IdPool.class,
398 new IdPoolKey(parentIdPool.getPoolName())).child(ReleasedIdsHolder.class).build();
399 releasedIdsBuilderParent.setAvailableIdCount(releasedIdsBuilderParent.getAvailableIdCount() - idCount);
400 LOG.debug("Allocated {} ids from releasedIds of parent pool {}", idCount, parentIdPool);
401 MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, releasedIdsHolderInstanceIdentifier, releasedIdsBuilderParent.build());
405 private long allocateIdBlockFromAvailableIdsHolder(AvailableIdsHolderBuilder availableIdsBuilder, IdPool parentIdPool) {
407 AvailableIdsHolderBuilder availableIdsBuilderParent = IdUtils.getAvailableIdsHolderBuilder(parentIdPool);
408 long end = availableIdsBuilderParent.getEnd();
409 long cur = availableIdsBuilderParent.getCursor();
410 if (!IdUtils.isIdAvailable(availableIdsBuilderParent)) {
411 LOG.debug("Ids exhausted in parent pool {}", parentIdPool);
414 // Update availableIdsHolder of Local Pool
415 availableIdsBuilder.setStart(cur + 1);
416 idCount = Math.min(end - cur, parentIdPool.getBlockSize());
417 availableIdsBuilder.setEnd(cur + idCount);
418 availableIdsBuilder.setCursor(cur);
419 // Update availableIdsHolder of Global Pool
420 InstanceIdentifier<AvailableIdsHolder> availableIdsHolderInstanceIdentifier = InstanceIdentifier
421 .builder(IdPools.class).child(IdPool.class,
422 new IdPoolKey(parentIdPool.getPoolName())).child(AvailableIdsHolder.class).build();
423 availableIdsBuilderParent.setCursor(cur + idCount);
424 LOG.debug("Allocated {} ids from availableIds of global pool {}", idCount, parentIdPool);
425 MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, availableIdsHolderInstanceIdentifier, availableIdsBuilderParent.build());
429 private void releaseIdFromLocalPool(String poolName, String idKey) {
430 InstanceIdentifier<IdPool> localIdPoolInstanceIdentifier = IdUtils.getIdPoolInstance(poolName);
431 poolName = poolName.intern();
432 synchronized (poolName) {
433 IdPool localPool = getIdPool(localIdPoolInstanceIdentifier);
434 String parentPoolName = localPool.getParentPoolName();
435 InstanceIdentifier<IdPool> parentIdPoolInstanceIdentifier = IdUtils.getIdPoolInstance(parentPoolName);
436 IdPool parentIdPool = getIdPool(parentIdPoolInstanceIdentifier);
437 List<IdEntries> idEntries = parentIdPool.getIdEntries();
438 List<IdEntries> newIdEntries = idEntries;
439 if (idEntries == null) {
440 throw new RuntimeException("Id Entries does not exist");
442 InstanceIdentifier<IdEntries> existingId = IdUtils.getIdEntry(parentIdPoolInstanceIdentifier, idKey);
443 Optional<IdEntries> existingIdEntryObject = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, existingId);
444 if (!existingIdEntryObject.isPresent()) {
445 throw new RuntimeException(String.format("Specified Id key %s does not exist in id pool %s", idKey, poolName));
447 IdEntries existingIdEntry = existingIdEntryObject.get();
448 long idValue = existingIdEntry.getIdValue();
449 boolean isRemoved = newIdEntries.remove(existingIdEntry);
450 LOG.debug("The entry {} is removed {}", existingIdEntry, isRemoved);
451 ReleasedIdsHolderBuilder releasedIds = IdUtils.getReleaseIdsHolderBuilder(localPool);
452 AvailableIdsHolderBuilder availableIds = IdUtils.getAvailableIdsHolderBuilder(localPool);
453 long delayTime = System.currentTimeMillis() / 1000 + releasedIds.getDelayedTimeSec();
454 DelayedIdEntries delayedIdEntry = IdUtils.createDelayedIdEntry(idValue, delayTime);
455 List<DelayedIdEntries> delayedIdEntries = releasedIds.getDelayedIdEntries();
456 if (delayedIdEntries == null) {
457 delayedIdEntries = new LinkedList<DelayedIdEntries>();
459 delayedIdEntries.add(delayedIdEntry);
460 long availableIdCount = releasedIds
461 .getAvailableIdCount() == null ? 0
462 : releasedIds.getAvailableIdCount();
463 releasedIds.setDelayedIdEntries(delayedIdEntries);
464 releasedIds.setAvailableIdCount(availableIdCount);
465 //Calling cleanupExcessIds since there could be excessive ids.
466 cleanupExcessIds(availableIds, releasedIds, parentPoolName, localPool.getBlockSize());
467 localPool = new IdPoolBuilder(localPool)
468 .setAvailableIdsHolder(availableIds.build())
469 .setReleasedIdsHolder(releasedIds.build()).build();
470 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, localIdPoolInstanceIdentifier, localPool);
471 LOG.debug("Released id ({}, {}) from pool {}", idKey, idValue, poolName);
472 //Updating id entries in the parent pool. This will be used for restart scenario
473 IdUtils.lockPool(lockManager, parentPoolName);
475 parentIdPool = getIdPool(parentIdPoolInstanceIdentifier);
476 IdPool parentPool = new IdPoolBuilder(parentIdPool).setIdEntries(newIdEntries).build();
477 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, parentIdPoolInstanceIdentifier, parentPool);
478 } catch (Exception ex) {
479 LOG.error("Saving of Id entries to parent pool {} failed due to {}", parentPoolName, ex);
481 IdUtils.unlockPool(lockManager, parentPoolName);
486 private IdPool createGlobalPool(String poolName, long low, long high,
487 long blockSize, InstanceIdentifier<IdPool> idPoolInstanceIdentifier) {
489 Optional<IdPool> existingIdPool = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier);
490 if (!existingIdPool.isPresent()) {
491 LOG.debug("Creating new global pool {}", poolName);
492 idPool = IdUtils.createGlobalPool(poolName, low, high, blockSize);
493 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier, idPool);
496 idPool = existingIdPool.get();
497 LOG.debug("GlobalPool exists {}", idPool);
502 private boolean createLocalPool(String localPoolName, IdPool idPool) {
503 localPoolName = localPoolName.intern();
504 synchronized (localPoolName) {
505 InstanceIdentifier<IdPool> localIdPoolInstanceIdentifier = IdUtils.getIdPoolInstance(localPoolName);
506 Optional<IdPool> localIdPool = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, localIdPoolInstanceIdentifier);
507 if (!localIdPool.isPresent()) {
508 LOG.debug("Creating new local pool");
509 IdPool newLocalIdPool = IdUtils.createLocalIdPool(localPoolName, idPool);
510 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, localIdPoolInstanceIdentifier, newLocalIdPool);
511 LOG.debug("Local pool created {}", newLocalIdPool);
518 private void deletePool(String poolName) {
519 InstanceIdentifier<IdPool> idPoolToBeDeleted = IdUtils.getIdPoolInstance(poolName);
520 synchronized (poolName) {
521 Optional<IdPool> idPool = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, idPoolToBeDeleted);
522 if (idPool.isPresent()) {
523 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, idPoolToBeDeleted);
524 LOG.debug("Deleted local pool {}", poolName);
529 private IdPool getIdPool(InstanceIdentifier<IdPool> idPoolInstanceIdentifier) {
530 Optional<IdPool> idPool = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier);
531 if (!idPool.isPresent()) {
532 throw new NoSuchElementException(String.format("Specified pool %s does not exist" , idPool));
534 LOG.trace("GetIdPool : Read id pool {} ", idPool);
538 private void updateChildPool(String poolName, String localPoolName) {
539 ChildPools childPool = IdUtils.createChildPool(localPoolName);
540 InstanceIdentifier<ChildPools> childPoolInstanceIdentifier = IdUtils.getChildPoolsInstanceIdentifier(poolName, localPoolName);
541 MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, childPoolInstanceIdentifier, childPool);