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.openecomp.sdnc.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;
33 import org.openecomp.sdnc.lock.comp.LockHelper;
34 import org.openecomp.sdnc.lock.comp.ResourceLockedException;
35 import org.openecomp.sdnc.lock.comp.SynchronizedFunction;
36 import org.openecomp.sdnc.rm.dao.ResourceDao;
37 import org.openecomp.sdnc.rm.data.AllocationOutcome;
38 import org.openecomp.sdnc.rm.data.AllocationRequest;
39 import org.openecomp.sdnc.rm.data.AllocationStatus;
40 import org.openecomp.sdnc.rm.data.LabelAllocationOutcome;
41 import org.openecomp.sdnc.rm.data.LabelAllocationRequest;
42 import org.openecomp.sdnc.rm.data.LabelResource;
43 import org.openecomp.sdnc.rm.data.LimitAllocationOutcome;
44 import org.openecomp.sdnc.rm.data.LimitAllocationRequest;
45 import org.openecomp.sdnc.rm.data.LimitResource;
46 import org.openecomp.sdnc.rm.data.MultiAssetAllocationOutcome;
47 import org.openecomp.sdnc.rm.data.MultiAssetAllocationRequest;
48 import org.openecomp.sdnc.rm.data.MultiResourceAllocationOutcome;
49 import org.openecomp.sdnc.rm.data.MultiResourceAllocationRequest;
50 import org.openecomp.sdnc.rm.data.RangeAllocationOutcome;
51 import org.openecomp.sdnc.rm.data.RangeAllocationRequest;
52 import org.openecomp.sdnc.rm.data.RangeResource;
53 import org.openecomp.sdnc.rm.data.Resource;
54 import org.openecomp.sdnc.rm.data.ResourceKey;
55 import org.openecomp.sdnc.rm.data.ResourceType;
56 import org.openecomp.sdnc.rm.util.LabelUtil;
57 import org.openecomp.sdnc.rm.util.LimitUtil;
58 import org.openecomp.sdnc.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 String applicationId;
70 private AllocationRequest request;
71 private AllocationOutcome outcome;
73 private List<Resource> updateList = new ArrayList<Resource>();
75 public AllocationFunction(LockHelper lockHelper, ResourceDao resourceDao, String applicationId,
76 AllocationRequest request, int lockTimeout) {
77 super(lockHelper, getLockNames(request), lockTimeout);
78 this.applicationId = applicationId;
79 this.resourceDao = resourceDao;
80 this.request = request;
83 private static Collection<String> getLockNames(AllocationRequest request) {
84 Set<String> lockResourceNames = new HashSet<String>();
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);
94 } else if (request instanceof MultiResourceAllocationRequest) {
95 MultiResourceAllocationRequest req = (MultiResourceAllocationRequest) request;
96 if (req.allocationRequestList != null)
97 for (AllocationRequest request1 : req.allocationRequestList)
98 addLockNames(lockResourceNames, request1);
99 } else if (request.assetId != null)
100 lockResourceNames.add(request.assetId);
104 public void _exec() throws ResourceLockedException {
105 outcome = allocate(request);
106 if (outcome.status == AllocationStatus.Success)
107 for (Resource r : updateList)
108 resourceDao.saveResource(r);
111 private AllocationOutcome allocate(AllocationRequest allocationRequest) throws ResourceLockedException {
112 if (allocationRequest instanceof MultiAssetAllocationRequest)
113 return allocateMultiAsset((MultiAssetAllocationRequest) allocationRequest);
114 if (allocationRequest instanceof MultiResourceAllocationRequest)
115 return allocateMultiResource((MultiResourceAllocationRequest) allocationRequest);
116 if (allocationRequest instanceof LimitAllocationRequest)
117 return allocateLimit((LimitAllocationRequest) allocationRequest);
118 if (allocationRequest instanceof LabelAllocationRequest)
119 return allocateLabel((LabelAllocationRequest) allocationRequest);
120 if (allocationRequest instanceof RangeAllocationRequest)
121 return allocateRange((RangeAllocationRequest) allocationRequest);
125 private MultiAssetAllocationOutcome allocateMultiAsset(MultiAssetAllocationRequest req) {
126 // TODO Auto-generated method stub
130 private MultiResourceAllocationOutcome allocateMultiResource(MultiResourceAllocationRequest req) {
131 MultiResourceAllocationOutcome out = new MultiResourceAllocationOutcome();
133 out.allocationOutcomeList = new ArrayList<AllocationOutcome>();
134 out.status = AllocationStatus.Success;
136 if (req.allocationRequestList != null)
137 for (AllocationRequest req1 : req.allocationRequestList) {
138 AllocationOutcome out1 = allocate(req1);
139 out.allocationOutcomeList.add(out1);
140 if (out1.status != AllocationStatus.Success)
141 out.status = AllocationStatus.Failure;
147 private LimitAllocationOutcome allocateLimit(LimitAllocationRequest req) {
148 LimitAllocationOutcome out = new LimitAllocationOutcome();
151 Resource r = resourceDao.getResource(req.assetId, req.resourceName);
153 r = new LimitResource();
154 r.resourceKey = new ResourceKey();
155 r.resourceKey.assetId = req.assetId;
156 r.resourceKey.resourceName = req.resourceName;
157 r.resourceType = ResourceType.Limit;
159 if (r.resourceType != ResourceType.Limit) {
160 out.status = AllocationStatus.ResourceNotFound;
163 LimitUtil.recalculate((LimitResource) r);
166 LimitResource l = (LimitResource) r;
167 if (LimitUtil.checkLimit(l, req)) {
168 out.status = AllocationStatus.Success;
169 if (req.allocateCount > 0) {
170 out.allocatedCount = LimitUtil.allocateLimit(l, req, applicationId);
174 out.status = AllocationStatus.Failure;
177 out.limit = req.checkLimit;
182 private LabelAllocationOutcome allocateLabel(LabelAllocationRequest req) {
183 LabelAllocationOutcome out = new LabelAllocationOutcome();
187 Resource r = resourceDao.getResource(req.assetId, req.resourceName);
189 r = new LabelResource();
190 r.resourceKey = new ResourceKey();
191 r.resourceKey.assetId = req.assetId;
192 r.resourceKey.resourceName = req.resourceName;
193 r.resourceType = ResourceType.Label;
195 if (r.resourceType != ResourceType.Label) {
196 out.status = AllocationStatus.ResourceNotFound;
199 LabelUtil.recalculate((LabelResource) r);
202 LabelResource l = (LabelResource) r;
203 if (LabelUtil.checkLabel(l, req)) {
204 out.status = AllocationStatus.Success;
205 out.currentLabel = l.label;
207 out.allocatedLabel = LabelUtil.allocateLabel(l, req, applicationId);
211 out.status = AllocationStatus.Failure;
216 private RangeAllocationOutcome allocateRange(RangeAllocationRequest req) {
217 RangeAllocationOutcome out = new RangeAllocationOutcome();
221 Resource r = resourceDao.getResource(req.assetId, req.resourceName);
223 r = new RangeResource();
224 r.resourceKey = new ResourceKey();
225 r.resourceKey.assetId = req.assetId;
226 r.resourceKey.resourceName = req.resourceName;
227 r.resourceType = ResourceType.Range;
229 if (r.resourceType != ResourceType.Range) {
230 out.status = AllocationStatus.ResourceNotFound;
233 RangeUtil.recalculate((RangeResource) r);
236 RangeResource rr = (RangeResource) r;
237 SortedSet<Integer> foundNumbers = null;
239 out.status = AllocationStatus.Success;
240 foundNumbers = req.requestedNumbers;
242 if (req.requestedNumbers != null && req.requestedNumbers.size() > 0) {
243 foundNumbers = req.requestedNumbers;
244 out.status = AllocationStatus.Success;
245 for (int n : foundNumbers)
246 if (!RangeUtil.checkRange(rr, req, n)) {
247 out.status = AllocationStatus.Failure;
251 foundNumbers = new TreeSet<Integer>();
254 // First try to reuse the numbers already taken by the same resource union
255 SortedSet<Integer> uu = RangeUtil.getUsed(rr, req.resourceUnionId);
256 if (uu != null && !uu.isEmpty()) {
257 if (uu.size() >= req.requestedCount) {
258 // Just take the first req.requestedCount numbers from uu
259 Iterator<Integer> i = uu.iterator();
260 while (foundCount < req.requestedCount) {
261 foundNumbers.add(i.next());
265 // Additional numbers are requested. Try to find them starting from
266 // the minimum we have in uu (the first element) towards the min
267 // parameter, and then starting from the maximum in uu (the last
268 // element) towards the max parameter.
269 // NOTE: In case of request for sequential numbers, the parameters
270 // alignBlockSize and alignModulus are ignored. It would be harder
271 // to take them into account, and currently it is not needed.
273 int uumin = uu.first() - 1;
274 int uumax = uu.last() + 1;
275 foundNumbers.addAll(uu);
276 foundCount = uu.size();
277 for (int n = uumin; foundCount < req.requestedCount && n >= req.checkMin; n--) {
278 if (RangeUtil.checkRange(rr, req, n)) {
281 } else if (req.sequential)
284 for (int n = uumax; foundCount < req.requestedCount && n <= req.checkMax; n++) {
285 if (RangeUtil.checkRange(rr, req, n)) {
288 } else if (req.sequential)
292 // If we could not find enough numbers trying to reuse currently
293 // allocated, reset foundNumbers and foundCount, continue with
294 // the normal allocation of new numbers.
295 if (foundCount < req.requestedCount) {
296 foundNumbers = new TreeSet<Integer>();
302 for (int n = req.checkMin; foundCount < req.requestedCount && n <= req.checkMax; n++)
303 if (RangeUtil.checkRange(rr, req, n)) {
306 } else if (req.sequential)
309 out.status = foundCount == req.requestedCount ? AllocationStatus.Success : AllocationStatus.Failure;
313 if (out.status == AllocationStatus.Success) {
314 out.allocated = foundNumbers;
316 RangeUtil.allocateRange(rr, out.allocated, req, applicationId);
320 out.allocated = new TreeSet<Integer>();
327 public AllocationOutcome getAllocationOutcome() {