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;
 
  33 import org.onap.ccsdk.sli.adaptors.lock.comp.LockHelper;
 
  34 import org.onap.ccsdk.sli.adaptors.lock.comp.ResourceLockedException;
 
  35 import org.onap.ccsdk.sli.adaptors.lock.comp.SynchronizedFunction;
 
  36 import org.onap.ccsdk.sli.adaptors.rm.dao.ResourceDao;
 
  37 import org.onap.ccsdk.sli.adaptors.rm.data.AllocationOutcome;
 
  38 import org.onap.ccsdk.sli.adaptors.rm.data.AllocationRequest;
 
  39 import org.onap.ccsdk.sli.adaptors.rm.data.AllocationStatus;
 
  40 import org.onap.ccsdk.sli.adaptors.rm.data.LabelAllocationOutcome;
 
  41 import org.onap.ccsdk.sli.adaptors.rm.data.LabelAllocationRequest;
 
  42 import org.onap.ccsdk.sli.adaptors.rm.data.LabelResource;
 
  43 import org.onap.ccsdk.sli.adaptors.rm.data.LimitAllocationOutcome;
 
  44 import org.onap.ccsdk.sli.adaptors.rm.data.LimitAllocationRequest;
 
  45 import org.onap.ccsdk.sli.adaptors.rm.data.LimitResource;
 
  46 import org.onap.ccsdk.sli.adaptors.rm.data.MultiAssetAllocationOutcome;
 
  47 import org.onap.ccsdk.sli.adaptors.rm.data.MultiAssetAllocationRequest;
 
  48 import org.onap.ccsdk.sli.adaptors.rm.data.MultiResourceAllocationOutcome;
 
  49 import org.onap.ccsdk.sli.adaptors.rm.data.MultiResourceAllocationRequest;
 
  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 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() {