2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.ccsdk.sli.adaptors.rm.comp;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.List;
30 import java.util.SortedSet;
31 import java.util.TreeSet;
32 import org.onap.ccsdk.sli.adaptors.lock.comp.LockHelper;
33 import org.onap.ccsdk.sli.adaptors.lock.comp.ResourceLockedException;
34 import org.onap.ccsdk.sli.adaptors.lock.comp.SynchronizedFunction;
35 import org.onap.ccsdk.sli.adaptors.rm.dao.ResourceDao;
36 import org.onap.ccsdk.sli.adaptors.rm.data.AllocationOutcome;
37 import org.onap.ccsdk.sli.adaptors.rm.data.AllocationRequest;
38 import org.onap.ccsdk.sli.adaptors.rm.data.AllocationStatus;
39 import org.onap.ccsdk.sli.adaptors.rm.data.LabelAllocationOutcome;
40 import org.onap.ccsdk.sli.adaptors.rm.data.LabelAllocationRequest;
41 import org.onap.ccsdk.sli.adaptors.rm.data.LabelResource;
42 import org.onap.ccsdk.sli.adaptors.rm.data.LimitAllocationOutcome;
43 import org.onap.ccsdk.sli.adaptors.rm.data.LimitAllocationRequest;
44 import org.onap.ccsdk.sli.adaptors.rm.data.LimitResource;
45 import org.onap.ccsdk.sli.adaptors.rm.data.MultiAssetAllocationOutcome;
46 import org.onap.ccsdk.sli.adaptors.rm.data.MultiAssetAllocationRequest;
47 import org.onap.ccsdk.sli.adaptors.rm.data.MultiResourceAllocationOutcome;
48 import org.onap.ccsdk.sli.adaptors.rm.data.MultiResourceAllocationRequest;
49 import org.onap.ccsdk.sli.adaptors.rm.data.Range;
50 import org.onap.ccsdk.sli.adaptors.rm.data.RangeAllocationOutcome;
51 import org.onap.ccsdk.sli.adaptors.rm.data.RangeAllocationRequest;
52 import org.onap.ccsdk.sli.adaptors.rm.data.RangeResource;
53 import org.onap.ccsdk.sli.adaptors.rm.data.Resource;
54 import org.onap.ccsdk.sli.adaptors.rm.data.ResourceKey;
55 import org.onap.ccsdk.sli.adaptors.rm.data.ResourceType;
56 import org.onap.ccsdk.sli.adaptors.rm.util.LabelUtil;
57 import org.onap.ccsdk.sli.adaptors.rm.util.LimitUtil;
58 import org.onap.ccsdk.sli.adaptors.rm.util.RangeUtil;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
62 class AllocationFunction extends SynchronizedFunction {
64 @SuppressWarnings("unused")
65 private static final Logger log = LoggerFactory.getLogger(AllocationFunction.class);
67 private ResourceDao resourceDao;
69 private AllocationRequest request;
70 private AllocationOutcome outcome;
72 private List<Resource> updateList = new ArrayList<>();
74 public AllocationFunction(LockHelper lockHelper, ResourceDao resourceDao, AllocationRequest request,
76 super(lockHelper, getLockNames(request), lockTimeout);
77 this.resourceDao = resourceDao;
78 this.request = request;
81 private static Collection<String> getLockNames(AllocationRequest request) {
82 Set<String> lockResourceNames = new HashSet<>();
83 addLockNames(lockResourceNames, request);
84 return lockResourceNames;
87 private static void addLockNames(Set<String> lockResourceNames, AllocationRequest request) {
88 if (request instanceof MultiAssetAllocationRequest) {
89 MultiAssetAllocationRequest req = (MultiAssetAllocationRequest) request;
90 if (req.assetIdList != null) {
91 lockResourceNames.addAll(req.assetIdList);
93 } else if (request instanceof MultiResourceAllocationRequest) {
94 MultiResourceAllocationRequest req = (MultiResourceAllocationRequest) request;
95 if (req.allocationRequestList != null) {
96 for (AllocationRequest request1 : req.allocationRequestList) {
97 addLockNames(lockResourceNames, request1);
100 } else if (request.assetId != null) {
101 lockResourceNames.add(request.assetId);
106 public void _exec() throws ResourceLockedException {
107 outcome = allocate(request);
108 if (outcome.status == AllocationStatus.Success) {
109 for (Resource r : updateList) {
110 resourceDao.saveResource(r);
115 private AllocationOutcome allocate(AllocationRequest allocationRequest) throws ResourceLockedException {
116 if (allocationRequest instanceof MultiAssetAllocationRequest) {
117 return allocateMultiAsset((MultiAssetAllocationRequest) allocationRequest);
119 if (allocationRequest instanceof MultiResourceAllocationRequest) {
120 return allocateMultiResource((MultiResourceAllocationRequest) allocationRequest);
122 if (allocationRequest instanceof LimitAllocationRequest) {
123 return allocateLimit((LimitAllocationRequest) allocationRequest);
125 if (allocationRequest instanceof LabelAllocationRequest) {
126 return allocateLabel((LabelAllocationRequest) allocationRequest);
128 if (allocationRequest instanceof RangeAllocationRequest) {
129 return allocateRange((RangeAllocationRequest) allocationRequest);
134 private MultiAssetAllocationOutcome allocateMultiAsset(MultiAssetAllocationRequest req) {
135 // TODO Auto-generated method stub
139 private MultiResourceAllocationOutcome allocateMultiResource(MultiResourceAllocationRequest req) {
140 MultiResourceAllocationOutcome out = new MultiResourceAllocationOutcome();
142 out.allocationOutcomeList = new ArrayList<>();
143 out.status = AllocationStatus.Success;
145 if (req.allocationRequestList != null) {
146 for (AllocationRequest req1 : req.allocationRequestList) {
147 AllocationOutcome out1 = allocate(req1);
148 out.allocationOutcomeList.add(out1);
149 if (out1.status != AllocationStatus.Success) {
150 out.status = AllocationStatus.Failure;
158 private LimitAllocationOutcome allocateLimit(LimitAllocationRequest req) {
159 LimitAllocationOutcome out = new LimitAllocationOutcome();
162 Resource r = resourceDao.getResource(req.assetId, req.resourceName);
164 r = new LimitResource();
165 r.resourceKey = new ResourceKey();
166 r.resourceKey.assetId = req.assetId;
167 r.resourceKey.resourceName = req.resourceName;
168 r.resourceType = ResourceType.Limit;
170 if (r.resourceType != ResourceType.Limit) {
171 out.status = AllocationStatus.ResourceNotFound;
174 LimitUtil.recalculate((LimitResource) r);
177 LimitResource l = (LimitResource) r;
178 if (LimitUtil.checkLimit(l, req)) {
179 out.status = AllocationStatus.Success;
180 if (req.allocateCount > 0) {
181 out.allocatedCount = LimitUtil.allocateLimit(l, req);
185 out.status = AllocationStatus.Failure;
189 out.limit = req.checkLimit;
194 private LabelAllocationOutcome allocateLabel(LabelAllocationRequest req) {
195 LabelAllocationOutcome out = new LabelAllocationOutcome();
199 Resource r = resourceDao.getResource(req.assetId, req.resourceName);
201 r = new LabelResource();
202 r.resourceKey = new ResourceKey();
203 r.resourceKey.assetId = req.assetId;
204 r.resourceKey.resourceName = req.resourceName;
205 r.resourceType = ResourceType.Label;
207 if (r.resourceType != ResourceType.Label) {
208 out.status = AllocationStatus.ResourceNotFound;
211 LabelUtil.recalculate((LabelResource) r);
214 LabelResource l = (LabelResource) r;
215 if (LabelUtil.checkLabel(l, req)) {
216 out.status = AllocationStatus.Success;
217 out.currentLabel = l.label;
219 out.allocatedLabel = LabelUtil.allocateLabel(l, req);
223 out.status = AllocationStatus.Failure;
229 private RangeAllocationOutcome allocateRange(RangeAllocationRequest req) {
230 RangeAllocationOutcome out = new RangeAllocationOutcome();
234 Resource r = resourceDao.getResource(req.assetId, req.resourceName);
236 r = new RangeResource();
237 r.resourceKey = new ResourceKey();
238 r.resourceKey.assetId = req.assetId;
239 r.resourceKey.resourceName = req.resourceName;
240 r.resourceType = ResourceType.Range;
242 if (r.resourceType != ResourceType.Range) {
243 out.status = AllocationStatus.ResourceNotFound;
246 RangeUtil.recalculate((RangeResource) r);
249 RangeResource rr = (RangeResource) r;
250 SortedSet<Integer> foundNumbers = null;
252 out.status = AllocationStatus.Success;
253 foundNumbers = req.requestedNumbers;
255 if (req.requestedNumbers != null && req.requestedNumbers.size() > 0) {
256 foundNumbers = req.requestedNumbers;
257 out.status = AllocationStatus.Success;
258 for (int n : foundNumbers) {
259 if (!RangeUtil.checkRange(rr, req, n)) {
260 out.status = AllocationStatus.Failure;
265 foundNumbers = new TreeSet<>();
268 // First try to reuse the numbers already taken by the same resource union
269 SortedSet<Integer> uu = RangeUtil.getUsed(rr, req.resourceUnionId);
270 if (uu != null && !uu.isEmpty() && req.replace && !req.forceNewNumbers) {
271 if (uu.size() >= req.requestedCount) {
272 // Just take the first req.requestedCount numbers from uu
273 Iterator<Integer> i = uu.iterator();
274 while (foundCount < req.requestedCount) {
275 foundNumbers.add(i.next());
279 // Additional numbers are requested. Try to find them starting from
280 // the minimum we have in uu (the first element) towards the min
281 // parameter, and then starting from the maximum in uu (the last
282 // element) towards the max parameter.
283 // NOTE: In case of request for sequential numbers, the parameters
284 // alignBlockSize and alignModulus are ignored. It would be harder
285 // to take them into account, and currently it is not needed.
287 // Request may contain multiple ranges. We will find the range from the request
288 // that contains the currently used numbers (the first one). We will only look
289 // for additional numbers in that range.
292 if (req.rangeList != null) {
293 for (Range range1 : req.rangeList) {
294 if (uu.first() >= range1.min && uu.first() <= range1.max) {
302 int uumin = uu.first() - 1;
303 int uumax = uu.last() + 1;
304 foundNumbers.addAll(uu);
305 foundCount = uu.size();
306 for (int n = uumin; foundCount < req.requestedCount && n >= range.min; n--) {
307 if (RangeUtil.checkRange(rr, req, n)) {
310 } else if (req.sequential) {
314 for (int n = uumax; foundCount < req.requestedCount && n <= range.max; n++) {
315 if (RangeUtil.checkRange(rr, req, n)) {
318 } else if (req.sequential) {
324 // If we could not find enough numbers trying to reuse currently
325 // allocated, reset foundNumbers and foundCount, continue with
326 // the normal allocation of new numbers.
327 if (foundCount < req.requestedCount) {
328 foundNumbers = new TreeSet<>();
334 if (req.rangeList != null) {
335 if (req.reverseOrder) {
336 for (int i = req.rangeList.size() - 1; i >= 0; i--) {
337 Range range = req.rangeList.get(i);
338 for (int n = range.max; foundCount < req.requestedCount && n >= range.min; n--) {
339 if (RangeUtil.checkRange(rr, req, n)) {
342 } else if (req.sequential) {
348 for (Range range : req.rangeList) {
349 for (int n = range.min; foundCount < req.requestedCount && n <= range.max; n++) {
350 if (RangeUtil.checkRange(rr, req, n)) {
353 } else if (req.sequential) {
361 out.status = foundCount == req.requestedCount ? AllocationStatus.Success : AllocationStatus.Failure;
365 if (out.status == AllocationStatus.Success) {
366 out.allocated = foundNumbers;
368 RangeUtil.allocateRange(rr, out.allocated, req);
372 out.allocated = new TreeSet<>();
380 public AllocationOutcome getAllocationOutcome() {