Bump versions by 0.1.0 for next dev cycle
[vpnservice.git] / idmanager / idmanager-impl / src / main / java / org / opendaylight / idmanager / IdUtils.java
1 /*
2  * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  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
9 package org.opendaylight.idmanager;
10
11 import java.net.InetAddress;
12 import java.util.LinkedList;
13 import java.util.List;
14 import java.util.concurrent.ExecutionException;
15 import java.util.concurrent.Future;
16
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.DelayedIdEntry;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolBuilder;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolderBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPools;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPoolsBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPoolsKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntries;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntriesBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntriesKey;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolderBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntries;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntriesBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockInput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockInputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInputBuilder;
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
40 import org.opendaylight.yangtools.yang.common.RpcResult;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 import com.google.common.net.InetAddresses;
45
46 class IdUtils {
47
48     private static final Logger LOGGER = LoggerFactory.getLogger(IdUtils.class);
49     private static final long DEFAULT_DELAY_TIME = 30;
50     private static final long DEFAULT_AVAILABLE_ID_COUNT = 0;
51     private static final int DEFAULT_BLOCK_SIZE_DIFF = 50;
52
53     private static int BLADE_ID;
54     static {
55         try {
56             BLADE_ID = InetAddresses.coerceToInteger(InetAddress.getLocalHost());
57         } catch (Exception e) {
58             LOGGER.error("IdManager - Exception - {}", e.getMessage());
59         }
60     }
61
62     protected static InstanceIdentifier<IdEntries> getIdEntry(InstanceIdentifier<IdPool> poolName, String idKey) {
63         InstanceIdentifier.InstanceIdentifierBuilder<IdEntries> idEntriesBuilder = poolName
64                 .builder().child(IdEntries.class, new IdEntriesKey(idKey));
65         InstanceIdentifier<IdEntries> idEntry = idEntriesBuilder.build();
66         return idEntry;
67     }
68
69     protected static IdEntries createIdEntries(String idKey, long newIdVal) {
70         return new IdEntriesBuilder().setKey(new IdEntriesKey(idKey))
71                 .setIdKey(idKey).setIdValue(newIdVal).build();
72     }
73
74     protected static DelayedIdEntries createDelayedIdEntry(long idValue, long delayTime) {
75         return new DelayedIdEntriesBuilder()
76                 .setId(idValue)
77                 .setReadyTimeSec(delayTime).build();
78     }
79
80     protected static IdPool createGlobalPool(String poolName, long low, long high, long blockSize) {
81         AvailableIdsHolder availableIdsHolder = createAvailableIdsHolder(low, high, low - 1);
82         ReleasedIdsHolder releasedIdsHolder = createReleasedIdsHolder(DEFAULT_AVAILABLE_ID_COUNT, 0);
83         int size = (int) blockSize;
84         return new IdPoolBuilder().setKey(new IdPoolKey(poolName))
85                 .setBlockSize(size).setPoolName(poolName)
86                 .setAvailableIdsHolder(availableIdsHolder)
87                 .setReleasedIdsHolder(releasedIdsHolder).build();
88     }
89
90     protected static AvailableIdsHolder createAvailableIdsHolder(long low, long high, long cursor) {
91         AvailableIdsHolder availableIdsHolder = new AvailableIdsHolderBuilder()
92                 .setStart(low).setEnd(high).setCursor(cursor).build();
93         return availableIdsHolder;
94     }
95
96     protected static ReleasedIdsHolder createReleasedIdsHolder(long availableIdCount, long delayTime) {
97         ReleasedIdsHolder releasedIdsHolder = new ReleasedIdsHolderBuilder()
98                 .setAvailableIdCount(availableIdCount)
99                 .setDelayedTimeSec(delayTime).build();
100         return releasedIdsHolder;
101     }
102
103     protected static InstanceIdentifier<IdPool> getIdPoolInstance(String poolName) {
104         InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idPoolBuilder = InstanceIdentifier
105                 .builder(IdPools.class).child(IdPool.class,
106                         new IdPoolKey(poolName));
107         InstanceIdentifier<IdPool> id = idPoolBuilder.build();
108         return id;
109     }
110
111     protected static InstanceIdentifier<ReleasedIdsHolder> getReleasedIdsHolderInstance(String poolName) {
112         InstanceIdentifier.InstanceIdentifierBuilder<ReleasedIdsHolder> releasedIdsHolder = InstanceIdentifier
113                 .builder(IdPools.class).child(IdPool.class,
114                         new IdPoolKey(poolName)).child(ReleasedIdsHolder.class);
115         InstanceIdentifier<ReleasedIdsHolder> releasedIds = releasedIdsHolder.build();
116         return releasedIds;
117     }
118
119     /**
120      * Changes made to releasedIds are not persisted in the datastore.
121      * @param releasedIds
122      * @return
123      */
124     protected static long getIdFromReleaseIdsIfAvailable(ReleasedIdsHolderBuilder releasedIds) {
125         List<DelayedIdEntries> delayedIdEntries = releasedIds.getDelayedIdEntries();
126         long newIdValue = -1;
127         if (delayedIdEntries != null && !delayedIdEntries.isEmpty()) {
128             processDelayList(releasedIds);
129             if (releasedIds.getAvailableIdCount() > 0) {
130                 DelayedIdEntries delayedIdEntry= delayedIdEntries.get(0);
131                 newIdValue = delayedIdEntry.getId();
132                 delayedIdEntries.remove(delayedIdEntry);
133                 releasedIds.setDelayedIdEntries(delayedIdEntries);
134                 releasedIds.setAvailableIdCount(releasedIds.getAvailableIdCount() - 1);
135             }
136         }
137         return newIdValue;
138     }
139
140     /**
141      * Changes made to availableIds are not persisted to datastore.
142      * @param availableIds
143      * @return
144      */
145     protected static long getIdFromAvailableIds(AvailableIdsHolderBuilder availableIds) {
146         long newIdValue = -1;
147         if (availableIds != null && isIdAvailable(availableIds)) {
148             newIdValue = availableIds.getCursor() + 1;
149             availableIds.setCursor(newIdValue);
150         }
151         return newIdValue;
152     }
153
154     protected static boolean isIdAvailable(AvailableIdsHolderBuilder availableIds) {
155         if (availableIds.getCursor() != null && availableIds.getEnd() != null)
156             return availableIds.getCursor() < availableIds.getEnd();
157         return false;
158     }
159
160     protected static String getLocalPoolName(String poolName) {
161         return (poolName + "." + BLADE_ID);
162     }
163
164     protected static IdPool createLocalIdPool(String localPoolName, IdPool parentIdPool) {
165         ReleasedIdsHolder releasedIdsHolder = createReleasedIdsHolder(DEFAULT_AVAILABLE_ID_COUNT, DEFAULT_DELAY_TIME);
166         return new IdPoolBuilder().setKey(new IdPoolKey(localPoolName))
167                 .setPoolName(localPoolName)
168                 .setParentPoolName(parentIdPool.getPoolName())
169                 .setBlockSize(parentIdPool.getBlockSize())
170                 .setReleasedIdsHolder(releasedIdsHolder).build();
171     }
172
173     protected static ChildPools createChildPool(String childPoolName) {
174         return new ChildPoolsBuilder().setKey(new ChildPoolsKey(childPoolName)).setChildPoolName(childPoolName).setLastAccessTime(System.currentTimeMillis() / 1000).build();
175     }
176
177     protected static AvailableIdsHolderBuilder getAvailableIdsHolderBuilder(IdPool pool) {
178         AvailableIdsHolder availableIds = pool.getAvailableIdsHolder();
179         if (availableIds != null )
180             return new AvailableIdsHolderBuilder(availableIds);
181         return new AvailableIdsHolderBuilder();
182     }
183
184     protected static ReleasedIdsHolderBuilder getReleaseIdsHolderBuilder(IdPool pool) {
185         ReleasedIdsHolder releasedIds = pool.getReleasedIdsHolder();
186         if (releasedIds != null)
187             return new ReleasedIdsHolderBuilder(releasedIds);
188         return new ReleasedIdsHolderBuilder();
189     }
190
191     /**
192      * Changes made to releaseIds are not persisted to the Datastore. Method invoking should ensure that releaseIds gets persisted.
193      * @param releasedIds
194      */
195     protected static void processDelayList(ReleasedIdsHolderBuilder releasedIds) {
196         List<DelayedIdEntries> delayedIdEntries = releasedIds.getDelayedIdEntries();
197         if (delayedIdEntries ==  null)
198             return;
199         long availableIdCount = releasedIds.getAvailableIdCount() == null ? 0 : releasedIds.getAvailableIdCount();
200         int index = (int) availableIdCount;
201         long currentTimeSec = System.currentTimeMillis() / 1000;
202         DelayedIdEntry delayedIdEntry;
203         while (index < delayedIdEntries.size()) {
204             delayedIdEntry = delayedIdEntries.get(index);
205             if (delayedIdEntry.getReadyTimeSec() > currentTimeSec) {
206                 break;
207             }
208             availableIdCount++;
209             index++;
210         }
211         releasedIds.setAvailableIdCount(availableIdCount);
212     }
213
214     /**
215      * Changes made to the parameters passed are not persisted to the Datastore. Method invoking should ensure that these gets persisted.
216      * @param releasedIdsChild
217      * @param releasedIdsParent
218      * @param idCountToBeFreed
219      */
220     protected static void freeExcessAvailableIds(ReleasedIdsHolderBuilder releasedIdsChild, ReleasedIdsHolderBuilder releasedIdsParent, int idCountToBeFreed) {
221         List<DelayedIdEntries> existingDelayedIdEntriesInParent = releasedIdsParent.getDelayedIdEntries();
222         List<DelayedIdEntries> delayedIdEntriesChild = releasedIdsChild.getDelayedIdEntries();
223         long availableIdCountParent = releasedIdsParent.getAvailableIdCount();
224         long availableIdCountChild = releasedIdsChild.getAvailableIdCount();
225         if (existingDelayedIdEntriesInParent == null) {
226             existingDelayedIdEntriesInParent = new LinkedList<>();
227         }
228         idCountToBeFreed = Math.min(idCountToBeFreed, delayedIdEntriesChild.size());
229         for (int index = 0; index < idCountToBeFreed; index++) {
230             existingDelayedIdEntriesInParent.add(delayedIdEntriesChild.get(0));
231             delayedIdEntriesChild.remove(0);
232         }
233         releasedIdsChild.setDelayedIdEntries(delayedIdEntriesChild).setAvailableIdCount(availableIdCountChild - idCountToBeFreed);
234         releasedIdsParent.setDelayedIdEntries(existingDelayedIdEntriesInParent).setAvailableIdCount(availableIdCountParent + idCountToBeFreed);
235     }
236
237     protected static InstanceIdentifier<IdEntries> getIdEntriesInstanceIdentifier(String poolName, String idKey) {
238         InstanceIdentifier<IdEntries> idEntries = InstanceIdentifier
239                 .builder(IdPools.class).child(IdPool.class,
240                         new IdPoolKey(poolName)).child(IdEntries.class, new IdEntriesKey(idKey)).build();
241         return idEntries;
242     }
243
244     protected static InstanceIdentifier<ChildPools> getChildPoolsInstanceIdentifier(String poolName, String localPoolName) {
245         InstanceIdentifier<ChildPools> childPools = InstanceIdentifier
246                 .builder(IdPools.class)
247                 .child(IdPool.class, new IdPoolKey(poolName))
248                 .child(ChildPools.class, new ChildPoolsKey(localPoolName)).build();
249         return childPools;
250     }
251
252     protected static long computeBlockSize(long low, long high) {
253         long blockSize;
254
255         long diff = high - low;
256         if (diff > DEFAULT_BLOCK_SIZE_DIFF) {
257             blockSize = diff / DEFAULT_BLOCK_SIZE_DIFF;
258         } else {
259             blockSize = 1;
260         }
261         return blockSize;
262     }
263
264     public static long getAvailableIdsCount(AvailableIdsHolderBuilder availableIds) {
265         if(availableIds != null && isIdAvailable(availableIds)) {
266             return availableIds.getEnd() - availableIds.getCursor();
267         }
268         return 0;
269     }
270
271     public static void lockPool(LockManagerService lockManager, String poolName) {
272          LockInput input = new LockInputBuilder().setLockName(poolName).build();
273          Future<RpcResult<Void>> result = lockManager.lock(input);
274          try {
275              if ((result != null) && (result.get().isSuccessful())) {
276                  LOGGER.debug("Acquired lock {}", poolName);
277              } else {
278                  throw new RuntimeException(String.format("Unable to getLock for pool %s", poolName));
279              }
280          } catch (InterruptedException | ExecutionException e) {
281              LOGGER.error("Unable to getLock for pool {}", poolName);
282              throw new RuntimeException(String.format("Unable to getLock for pool %s", poolName), e.getCause());
283          }
284     }
285
286     public static void unlockPool(LockManagerService lockManager, String poolName) {
287         UnlockInput input = new UnlockInputBuilder().setLockName(poolName).build();
288         Future<RpcResult<Void>> result = lockManager.unlock(input);
289         try {
290             if ((result != null) && (result.get().isSuccessful())) {
291                 LOGGER.debug("Unlocked {}", poolName);
292             } else {
293                 LOGGER.debug("Unable to unlock pool {}", poolName);
294             }
295         } catch (InterruptedException | ExecutionException e) {
296             LOGGER.error("Unable to unlock for pool {}", poolName);
297             throw new RuntimeException(String.format("Unable to unlock pool %s", poolName), e.getCause());
298         }
299    }
300 }