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