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.RangeAllocationOutcome;
 
  50 import org.onap.ccsdk.sli.adaptors.rm.data.RangeAllocationRequest;
 
  51 import org.onap.ccsdk.sli.adaptors.rm.data.RangeResource;
 
  52 import org.onap.ccsdk.sli.adaptors.rm.data.Resource;
 
  53 import org.onap.ccsdk.sli.adaptors.rm.data.ResourceKey;
 
  54 import org.onap.ccsdk.sli.adaptors.rm.data.ResourceType;
 
  55 import org.onap.ccsdk.sli.adaptors.rm.util.LabelUtil;
 
  56 import org.onap.ccsdk.sli.adaptors.rm.util.LimitUtil;
 
  57 import org.onap.ccsdk.sli.adaptors.rm.util.RangeUtil;
 
  58 import org.slf4j.Logger;
 
  59 import org.slf4j.LoggerFactory;
 
  61 class AllocationFunction extends SynchronizedFunction {
 
  63     @SuppressWarnings("unused")
 
  64     private static final Logger log = LoggerFactory.getLogger(AllocationFunction.class);
 
  66     private ResourceDao resourceDao;
 
  68     private AllocationRequest request;
 
  69     private AllocationOutcome outcome;
 
  71     private List<Resource> updateList = new ArrayList<>();
 
  73     public AllocationFunction(LockHelper lockHelper, ResourceDao resourceDao, AllocationRequest request,
 
  75         super(lockHelper, getLockNames(request), lockTimeout);
 
  76         this.resourceDao = resourceDao;
 
  77         this.request = request;
 
  80     private static Collection<String> getLockNames(AllocationRequest request) {
 
  81         Set<String> lockResourceNames = new HashSet<>();
 
  82         addLockNames(lockResourceNames, request);
 
  83         return lockResourceNames;
 
  86     private static void addLockNames(Set<String> lockResourceNames, AllocationRequest request) {
 
  87         if (request instanceof MultiAssetAllocationRequest) {
 
  88             MultiAssetAllocationRequest req = (MultiAssetAllocationRequest) request;
 
  89             if (req.assetIdList != null) {
 
  90                 lockResourceNames.addAll(req.assetIdList);
 
  92         } else if (request instanceof MultiResourceAllocationRequest) {
 
  93             MultiResourceAllocationRequest req = (MultiResourceAllocationRequest) request;
 
  94             if (req.allocationRequestList != null) {
 
  95                 for (AllocationRequest request1 : req.allocationRequestList) {
 
  96                     addLockNames(lockResourceNames, request1);
 
  99         } else if (request.assetId != null) {
 
 100             lockResourceNames.add(request.assetId);
 
 105     public void _exec() throws ResourceLockedException {
 
 106         outcome = allocate(request);
 
 107         if (outcome.status == AllocationStatus.Success) {
 
 108             for (Resource r : updateList) {
 
 109                 resourceDao.saveResource(r);
 
 114     private AllocationOutcome allocate(AllocationRequest allocationRequest) throws ResourceLockedException {
 
 115         if (allocationRequest instanceof MultiAssetAllocationRequest) {
 
 116             return allocateMultiAsset((MultiAssetAllocationRequest) allocationRequest);
 
 118         if (allocationRequest instanceof MultiResourceAllocationRequest) {
 
 119             return allocateMultiResource((MultiResourceAllocationRequest) allocationRequest);
 
 121         if (allocationRequest instanceof LimitAllocationRequest) {
 
 122             return allocateLimit((LimitAllocationRequest) allocationRequest);
 
 124         if (allocationRequest instanceof LabelAllocationRequest) {
 
 125             return allocateLabel((LabelAllocationRequest) allocationRequest);
 
 127         if (allocationRequest instanceof RangeAllocationRequest) {
 
 128             return allocateRange((RangeAllocationRequest) allocationRequest);
 
 133     private MultiAssetAllocationOutcome allocateMultiAsset(MultiAssetAllocationRequest req) {
 
 134         // TODO Auto-generated method stub
 
 138     private MultiResourceAllocationOutcome allocateMultiResource(MultiResourceAllocationRequest req) {
 
 139         MultiResourceAllocationOutcome out = new MultiResourceAllocationOutcome();
 
 141         out.allocationOutcomeList = new ArrayList<>();
 
 142         out.status = AllocationStatus.Success;
 
 144         if (req.allocationRequestList != null) {
 
 145             for (AllocationRequest req1 : req.allocationRequestList) {
 
 146                 AllocationOutcome out1 = allocate(req1);
 
 147                 out.allocationOutcomeList.add(out1);
 
 148                 if (out1.status != AllocationStatus.Success) {
 
 149                     out.status = AllocationStatus.Failure;
 
 157     private LimitAllocationOutcome allocateLimit(LimitAllocationRequest req) {
 
 158         LimitAllocationOutcome out = new LimitAllocationOutcome();
 
 161         Resource r = resourceDao.getResource(req.assetId, req.resourceName);
 
 163             r = new LimitResource();
 
 164             r.resourceKey = new ResourceKey();
 
 165             r.resourceKey.assetId = req.assetId;
 
 166             r.resourceKey.resourceName = req.resourceName;
 
 167             r.resourceType = ResourceType.Limit;
 
 169             if (r.resourceType != ResourceType.Limit) {
 
 170                 out.status = AllocationStatus.ResourceNotFound;
 
 173             LimitUtil.recalculate((LimitResource) r);
 
 176         LimitResource l = (LimitResource) r;
 
 177         if (LimitUtil.checkLimit(l, req)) {
 
 178             out.status = AllocationStatus.Success;
 
 179             if (req.allocateCount > 0) {
 
 180                 out.allocatedCount = LimitUtil.allocateLimit(l, req);
 
 184             out.status = AllocationStatus.Failure;
 
 188         out.limit = req.checkLimit;
 
 193     private LabelAllocationOutcome allocateLabel(LabelAllocationRequest req) {
 
 194         LabelAllocationOutcome out = new LabelAllocationOutcome();
 
 198         Resource r = resourceDao.getResource(req.assetId, req.resourceName);
 
 200             r = new LabelResource();
 
 201             r.resourceKey = new ResourceKey();
 
 202             r.resourceKey.assetId = req.assetId;
 
 203             r.resourceKey.resourceName = req.resourceName;
 
 204             r.resourceType = ResourceType.Label;
 
 206             if (r.resourceType != ResourceType.Label) {
 
 207                 out.status = AllocationStatus.ResourceNotFound;
 
 210             LabelUtil.recalculate((LabelResource) r);
 
 213         LabelResource l = (LabelResource) r;
 
 214         if (LabelUtil.checkLabel(l, req)) {
 
 215             out.status = AllocationStatus.Success;
 
 216             out.currentLabel = l.label;
 
 218                 out.allocatedLabel = LabelUtil.allocateLabel(l, req);
 
 222             out.status = AllocationStatus.Failure;
 
 228     private RangeAllocationOutcome allocateRange(RangeAllocationRequest req) {
 
 229         RangeAllocationOutcome out = new RangeAllocationOutcome();
 
 233         Resource r = resourceDao.getResource(req.assetId, req.resourceName);
 
 235             r = new RangeResource();
 
 236             r.resourceKey = new ResourceKey();
 
 237             r.resourceKey.assetId = req.assetId;
 
 238             r.resourceKey.resourceName = req.resourceName;
 
 239             r.resourceType = ResourceType.Range;
 
 241             if (r.resourceType != ResourceType.Range) {
 
 242                 out.status = AllocationStatus.ResourceNotFound;
 
 245             RangeUtil.recalculate((RangeResource) r);
 
 248         RangeResource rr = (RangeResource) r;
 
 249         SortedSet<Integer> foundNumbers = null;
 
 251             out.status = AllocationStatus.Success;
 
 252             foundNumbers = req.requestedNumbers;
 
 254             if (req.requestedNumbers != null && req.requestedNumbers.size() > 0) {
 
 255                 foundNumbers = req.requestedNumbers;
 
 256                 out.status = AllocationStatus.Success;
 
 257                 for (int n : foundNumbers) {
 
 258                     if (!RangeUtil.checkRange(rr, req, n)) {
 
 259                         out.status = AllocationStatus.Failure;
 
 264                 foundNumbers = new TreeSet<>();
 
 267                 // First try to reuse the numbers already taken by the same resource union
 
 268                 SortedSet<Integer> uu = RangeUtil.getUsed(rr, req.resourceUnionId);
 
 269                 if (uu != null && !uu.isEmpty() && req.replace) {
 
 270                     if (uu.size() >= req.requestedCount) {
 
 271                         // Just take the first req.requestedCount numbers from uu
 
 272                         Iterator<Integer> i = uu.iterator();
 
 273                         while (foundCount < req.requestedCount) {
 
 274                             foundNumbers.add(i.next());
 
 278                         // Additional numbers are requested. Try to find them starting from
 
 279                         // the minimum we have in uu (the first element) towards the min
 
 280                         // parameter, and then starting from the maximum in uu (the last
 
 281                         // element) towards the max parameter.
 
 282                         // NOTE: In case of request for sequential numbers, the parameters
 
 283                         // alignBlockSize and alignModulus are ignored. It would be harder
 
 284                         // to take them into account, and currently it is not needed.
 
 286                         int uumin = uu.first() - 1;
 
 287                         int uumax = uu.last() + 1;
 
 288                         foundNumbers.addAll(uu);
 
 289                         foundCount = uu.size();
 
 290                         for (int n = uumin; foundCount < req.requestedCount && n >= req.checkMin; n--) {
 
 291                             if (RangeUtil.checkRange(rr, req, n)) {
 
 294                             } else if (req.sequential) {
 
 298                         for (int n = uumax; foundCount < req.requestedCount && n <= req.checkMax; n++) {
 
 299                             if (RangeUtil.checkRange(rr, req, n)) {
 
 302                             } else if (req.sequential) {
 
 307                         // If we could not find enough numbers trying to reuse currently
 
 308                         // allocated, reset foundNumbers and foundCount, continue with
 
 309                         // the normal allocation of new numbers.
 
 310                         if (foundCount < req.requestedCount) {
 
 311                             foundNumbers = new TreeSet<>();
 
 317                 if (req.reverseOrder) {
 
 318                     for (int n = req.checkMax; foundCount < req.requestedCount && n >= req.checkMin; n--) {
 
 319                         if (RangeUtil.checkRange(rr, req, n)) {
 
 322                         } else if (req.sequential) {
 
 327                     for (int n = req.checkMin; foundCount < req.requestedCount && n <= req.checkMax; n++) {
 
 328                         if (RangeUtil.checkRange(rr, req, n)) {
 
 331                         } else if (req.sequential) {
 
 337                 out.status = foundCount == req.requestedCount ? AllocationStatus.Success : AllocationStatus.Failure;
 
 341         if (out.status == AllocationStatus.Success) {
 
 342             out.allocated = foundNumbers;
 
 344                 RangeUtil.allocateRange(rr, out.allocated, req);
 
 348             out.allocated = new TreeSet<>();
 
 356     public AllocationOutcome getAllocationOutcome() {