2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights
7 * ================================================================================
8 * Modifications Copyright (C) 2018 IBM.
9 * ================================================================================
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 * ============LICENSE_END=========================================================
24 package org.onap.ccsdk.sli.adaptors.rm.comp;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.List;
32 import java.util.SortedSet;
33 import java.util.TreeSet;
34 import org.onap.ccsdk.sli.adaptors.lock.comp.LockHelper;
35 import org.onap.ccsdk.sli.adaptors.lock.comp.ResourceLockedException;
36 import org.onap.ccsdk.sli.adaptors.lock.comp.SynchronizedFunction;
37 import org.onap.ccsdk.sli.adaptors.rm.dao.ResourceDao;
38 import org.onap.ccsdk.sli.adaptors.rm.data.AllocationOutcome;
39 import org.onap.ccsdk.sli.adaptors.rm.data.AllocationRequest;
40 import org.onap.ccsdk.sli.adaptors.rm.data.AllocationStatus;
41 import org.onap.ccsdk.sli.adaptors.rm.data.LabelAllocationOutcome;
42 import org.onap.ccsdk.sli.adaptors.rm.data.LabelAllocationRequest;
43 import org.onap.ccsdk.sli.adaptors.rm.data.LabelResource;
44 import org.onap.ccsdk.sli.adaptors.rm.data.LimitAllocationOutcome;
45 import org.onap.ccsdk.sli.adaptors.rm.data.LimitAllocationRequest;
46 import org.onap.ccsdk.sli.adaptors.rm.data.LimitResource;
47 import org.onap.ccsdk.sli.adaptors.rm.data.MultiAssetAllocationOutcome;
48 import org.onap.ccsdk.sli.adaptors.rm.data.MultiAssetAllocationRequest;
49 import org.onap.ccsdk.sli.adaptors.rm.data.MultiResourceAllocationOutcome;
50 import org.onap.ccsdk.sli.adaptors.rm.data.MultiResourceAllocationRequest;
51 import org.onap.ccsdk.sli.adaptors.rm.data.Range;
52 import org.onap.ccsdk.sli.adaptors.rm.data.RangeAllocationOutcome;
53 import org.onap.ccsdk.sli.adaptors.rm.data.RangeAllocationRequest;
54 import org.onap.ccsdk.sli.adaptors.rm.data.RangeResource;
55 import org.onap.ccsdk.sli.adaptors.rm.data.Resource;
56 import org.onap.ccsdk.sli.adaptors.rm.data.ResourceKey;
57 import org.onap.ccsdk.sli.adaptors.rm.data.ResourceType;
58 import org.onap.ccsdk.sli.adaptors.rm.util.LabelUtil;
59 import org.onap.ccsdk.sli.adaptors.rm.util.LimitUtil;
60 import org.onap.ccsdk.sli.adaptors.rm.util.RangeUtil;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
64 class AllocationFunction extends SynchronizedFunction {
66 @SuppressWarnings("unused")
67 private static final Logger log = LoggerFactory.getLogger(AllocationFunction.class);
69 private ResourceDao resourceDao;
71 private AllocationRequest request;
72 private AllocationOutcome outcome;
74 private List<Resource> updateList = new ArrayList<>();
76 public AllocationFunction(LockHelper lockHelper, ResourceDao resourceDao, AllocationRequest request,
78 super(lockHelper, getLockNames(request), lockTimeout);
79 this.resourceDao = resourceDao;
80 this.request = request;
83 private static Collection<String> getLockNames(AllocationRequest request) {
84 Set<String> lockResourceNames = new HashSet<>();
85 addLockNames(lockResourceNames, request);
86 return lockResourceNames;
89 private static void addLockNames(Set<String> lockResourceNames, AllocationRequest request) {
90 if (request instanceof MultiAssetAllocationRequest) {
91 MultiAssetAllocationRequest req = (MultiAssetAllocationRequest) request;
92 if (req.assetIdList != null) {
93 lockResourceNames.addAll(req.assetIdList);
95 } else if (request instanceof MultiResourceAllocationRequest) {
96 MultiResourceAllocationRequest req = (MultiResourceAllocationRequest) request;
97 if (req.allocationRequestList != null) {
98 for (AllocationRequest request1 : req.allocationRequestList) {
99 addLockNames(lockResourceNames, request1);
102 } else if (request.assetId != null) {
103 lockResourceNames.add(request.assetId);
108 public void _exec() throws ResourceLockedException {
109 outcome = allocate(request);
111 if ((outcome!=null) && (outcome.status == AllocationStatus.Success)) {
112 for (Resource r : updateList) {
113 resourceDao.saveResource(r);
118 private AllocationOutcome allocate(AllocationRequest allocationRequest) throws ResourceLockedException {
119 if (allocationRequest instanceof MultiAssetAllocationRequest) {
120 return allocateMultiAsset((MultiAssetAllocationRequest) allocationRequest);
122 if (allocationRequest instanceof MultiResourceAllocationRequest) {
123 return allocateMultiResource((MultiResourceAllocationRequest) allocationRequest);
125 if (allocationRequest instanceof LimitAllocationRequest) {
126 return allocateLimit((LimitAllocationRequest) allocationRequest);
128 if (allocationRequest instanceof LabelAllocationRequest) {
129 return allocateLabel((LabelAllocationRequest) allocationRequest);
131 if (allocationRequest instanceof RangeAllocationRequest) {
132 return allocateRange((RangeAllocationRequest) allocationRequest);
137 private MultiAssetAllocationOutcome allocateMultiAsset(MultiAssetAllocationRequest req) {
142 private MultiResourceAllocationOutcome allocateMultiResource(MultiResourceAllocationRequest req) {
143 MultiResourceAllocationOutcome out = new MultiResourceAllocationOutcome();
145 out.allocationOutcomeList = new ArrayList<>();
146 out.status = AllocationStatus.Success;
148 if (req.allocationRequestList != null) {
149 for (AllocationRequest req1 : req.allocationRequestList) {
150 AllocationOutcome out1 = allocate(req1);
151 out.allocationOutcomeList.add(out1);
152 if (out1.status != AllocationStatus.Success) {
153 out.status = AllocationStatus.Failure;
161 private LimitAllocationOutcome allocateLimit(LimitAllocationRequest req) {
162 LimitAllocationOutcome out = new LimitAllocationOutcome();
165 Resource r = resourceDao.getResource(req.assetId, req.resourceName);
167 r = new LimitResource();
168 r.resourceKey = new ResourceKey();
169 r.resourceKey.assetId = req.assetId;
170 r.resourceKey.resourceName = req.resourceName;
171 r.resourceType = ResourceType.Limit;
173 if (r.resourceType != ResourceType.Limit) {
174 out.status = AllocationStatus.ResourceNotFound;
177 LimitUtil.recalculate((LimitResource) r);
180 LimitResource l = (LimitResource) r;
181 if (LimitUtil.checkLimit(l, req)) {
182 out.status = AllocationStatus.Success;
183 if (req.allocateCount > 0) {
184 out.allocatedCount = LimitUtil.allocateLimit(l, req);
188 out.status = AllocationStatus.Failure;
192 out.limit = req.checkLimit;
197 private LabelAllocationOutcome allocateLabel(LabelAllocationRequest req) {
198 LabelAllocationOutcome out = new LabelAllocationOutcome();
202 Resource r = resourceDao.getResource(req.assetId, req.resourceName);
204 r = new LabelResource();
205 r.resourceKey = new ResourceKey();
206 r.resourceKey.assetId = req.assetId;
207 r.resourceKey.resourceName = req.resourceName;
208 r.resourceType = ResourceType.Label;
210 if (r.resourceType != ResourceType.Label) {
211 out.status = AllocationStatus.ResourceNotFound;
214 LabelUtil.recalculate((LabelResource) r);
217 LabelResource l = (LabelResource) r;
218 if (LabelUtil.checkLabel(l, req)) {
219 out.status = AllocationStatus.Success;
220 out.currentLabel = l.label;
222 out.allocatedLabel = LabelUtil.allocateLabel(l, req);
226 out.status = AllocationStatus.Failure;
232 private RangeAllocationOutcome allocateRange(RangeAllocationRequest req) {
233 RangeAllocationOutcome out = new RangeAllocationOutcome();
237 Resource r = resourceDao.getResource(req.assetId, req.resourceName);
239 r = new RangeResource();
240 r.resourceKey = new ResourceKey();
241 r.resourceKey.assetId = req.assetId;
242 r.resourceKey.resourceName = req.resourceName;
243 r.resourceType = ResourceType.Range;
245 if (r.resourceType != ResourceType.Range) {
246 out.status = AllocationStatus.ResourceNotFound;
249 RangeUtil.recalculate((RangeResource) r);
252 RangeResource rr = (RangeResource) r;
253 SortedSet<Integer> foundNumbers = null;
255 out.status = AllocationStatus.Success;
256 foundNumbers = req.requestedNumbers;
258 if (req.requestedNumbers != null && !req.requestedNumbers.isEmpty()) {
259 foundNumbers = req.requestedNumbers;
260 out.status = AllocationStatus.Success;
261 for (int n : foundNumbers) {
262 if (!RangeUtil.checkRange(rr, req, n)) {
263 out.status = AllocationStatus.Failure;
268 foundNumbers = new TreeSet<>();
271 // First try to reuse the numbers already taken by the same resource union
272 SortedSet<Integer> uu = RangeUtil.getUsed(rr, req.resourceUnionId);
273 if (uu != null && !uu.isEmpty() && req.replace && !req.forceNewNumbers) {
274 if (uu.size() >= req.requestedCount) {
275 // Just take the first req.requestedCount numbers from uu
276 Iterator<Integer> i = uu.iterator();
277 while (foundCount < req.requestedCount) {
278 foundNumbers.add(i.next());
282 // Additional numbers are requested. Try to find them starting from
283 // the minimum we have in uu (the first element) towards the min
284 // parameter, and then starting from the maximum in uu (the last
285 // element) towards the max parameter.
286 // NOTE: In case of request for sequential numbers, the parameters
287 // alignBlockSize and alignModulus are ignored. It would be harder
288 // to take them into account, and currently it is not needed.
290 // Request may contain multiple ranges. We will find the range from the request
291 // that contains the currently used numbers (the first one). We will only look
292 // for additional numbers in that range.
295 if (req.rangeList != null) {
296 for (Range range1 : req.rangeList) {
297 if (uu.first() >= range1.min && uu.first() <= range1.max) {
305 int uumin = uu.first() - 1;
306 int uumax = uu.last() + 1;
307 foundNumbers.addAll(uu);
308 foundCount = uu.size();
309 for (int n = uumin; foundCount < req.requestedCount && n >= range.min; n--) {
310 if (RangeUtil.checkRange(rr, req, n)) {
313 } else if (req.sequential) {
317 for (int n = uumax; foundCount < req.requestedCount && n <= range.max; n++) {
318 if (RangeUtil.checkRange(rr, req, n)) {
321 } else if (req.sequential) {
327 // If we could not find enough numbers trying to reuse currently
328 // allocated, reset foundNumbers and foundCount, continue with
329 // the normal allocation of new numbers.
330 if (foundCount < req.requestedCount) {
331 foundNumbers = new TreeSet<>();
337 if (req.rangeList != null) {
338 if (req.reverseOrder) {
339 for (int i = req.rangeList.size() - 1; i >= 0; i--) {
340 Range range = req.rangeList.get(i);
341 for (int n = range.max; foundCount < req.requestedCount && n >= range.min; n--) {
342 if (RangeUtil.checkRange(rr, req, n)) {
345 } else if (req.sequential) {
351 for (Range range : req.rangeList) {
352 for (int n = range.min; foundCount < req.requestedCount && n <= range.max; n++) {
353 if (RangeUtil.checkRange(rr, req, n)) {
356 } else if (req.sequential) {
364 out.status = foundCount == req.requestedCount ? AllocationStatus.Success : AllocationStatus.Failure;
368 if (out.status == AllocationStatus.Success) {
369 out.allocated = foundNumbers;
371 RangeUtil.allocateRange(rr, out.allocated, req);
375 out.allocated = new TreeSet<>();
383 public AllocationOutcome getAllocationOutcome() {