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.lock.comp;
 
  24 import java.util.ArrayList;
 
  25 import java.util.Collection;
 
  26 import java.util.Collections;
 
  27 import java.util.Date;
 
  28 import java.util.List;
 
  29 import org.onap.ccsdk.sli.adaptors.lock.dao.ResourceLockDao;
 
  30 import org.onap.ccsdk.sli.adaptors.lock.data.ResourceLock;
 
  31 import org.slf4j.Logger;
 
  32 import org.slf4j.LoggerFactory;
 
  34 public class LockHelperImpl implements LockHelper {
 
  36     private static final Logger log = LoggerFactory.getLogger(LockHelperImpl.class);
 
  38     private ResourceLockDao resourceLockDao;
 
  39     private int retryCount = 10;
 
  40     private int lockWait = 5; // Seconds
 
  43     public void lock(String resourceName, String lockRequester, int lockTimeout /* Seconds */) {
 
  44         lock(resourceName, lockRequester, lockTimeout, lockWait, retryCount);
 
  48     public void lock(String resourceName, String lockRequester, int lockTimeout /* Seconds */, int lockWait /* Seconds */, int retryCount) {
 
  49         lock(Collections.singleton(resourceName), lockRequester, lockTimeout, lockWait, retryCount);
 
  53     public void unlock(String resourceName, boolean force) {
 
  54         unlock(Collections.singleton(resourceName), force);
 
  58     public void lock(Collection<String> resourceNameList, String lockRequester, int lockTimeout /* Seconds */) {
 
  59         lock(resourceNameList, lockRequester, lockTimeout, lockWait, retryCount);
 
  63     public void lock(Collection<String> resourceNameList, String lockRequester, int lockTimeout /* Seconds */, int lockWait /* Seconds */, int retryCount) {
 
  64         for (int i = 0; true; i++) {
 
  66                 tryLock(resourceNameList, lockRequester, lockTimeout);
 
  67                 log.info("Resources locked: " + resourceNameList);
 
  69             } catch (ResourceLockedException e) {
 
  70                 if (i >= retryCount) {
 
  74                     Thread.sleep(lockWait * 1000);
 
  75                 } catch (InterruptedException ex) {
 
  82     public void unlock(Collection<String> lockNames, boolean force) {
 
  83         if (lockNames == null || lockNames.size() == 0) {
 
  88             for (String name : lockNames) {
 
  89                 ResourceLock l = resourceLockDao.getByResourceName(name);
 
  91                     if (force || l.lockCount == 1) {
 
  92                         resourceLockDao.delete(l.id);
 
  94                         resourceLockDao.decrementLockCount(l.id);
 
  99             resourceLockDao.commit();
 
 101             log.info("Resources unlocked: " + lockNames);
 
 103             resourceLockDao.rollback();
 
 107     public void tryLock(Collection<String> resourceNameList, String lockRequester, int lockTimeout /* Seconds */) {
 
 108         if (resourceNameList == null || resourceNameList.size() == 0) {
 
 112         lockRequester = generateLockRequester(lockRequester, 100);
 
 114         // First check if all requested records are available to lock
 
 116         Date now = new Date();
 
 119             List<ResourceLock> dbLockList = new ArrayList<>();
 
 120             List<String> insertLockNameList = new ArrayList<>();
 
 121             for (String name : resourceNameList) {
 
 122                 ResourceLock l = resourceLockDao.getByResourceName(name);
 
 124                 boolean canLock = l == null || now.getTime() > l.expirationTime.getTime() ||
 
 125                         lockRequester != null && lockRequester.equals(l.lockHolder) || l.lockCount <= 0;
 
 127                     throw new ResourceLockedException(l.resourceName, l.lockHolder, lockRequester);
 
 133                     insertLockNameList.add(name);
 
 137             // Update the lock info in DB
 
 138             for (ResourceLock l : dbLockList) {
 
 139                 resourceLockDao.update(l.id, now, new Date(now.getTime() + lockTimeout * 1000), l.lockCount + 1);
 
 142             // Insert records for those that are not yet there
 
 143             for (String lockName : insertLockNameList) {
 
 144                 ResourceLock l = new ResourceLock();
 
 145                 l.resourceName = lockName;
 
 146                 l.lockHolder = lockRequester;
 
 148                 l.expirationTime = new Date(now.getTime() + lockTimeout * 1000);
 
 152                     resourceLockDao.add(l);
 
 153                 } catch (Exception e) {
 
 154                     log.info("Failed to insert lock record: " + lockName);
 
 155                     throw new ResourceLockedException(l.resourceName, "unknown", lockRequester);
 
 159             resourceLockDao.commit();
 
 162             resourceLockDao.rollback();
 
 166     private static String generateLockRequester(String name, int maxLength) {
 
 170         int l1 = name.length();
 
 171         String tname = Thread.currentThread().getName();
 
 172         int l2 = tname.length();
 
 173         if (l1 + l2 + 1 > maxLength) {
 
 174             int maxl1 = maxLength / 2;
 
 176                 name = name.substring(0, maxl1);
 
 179             int maxl2 = maxLength - l1 - 1;
 
 181                 tname = tname.substring(0, 6) + "..." + tname.substring(l2 - maxl2 + 9);
 
 184         return tname + '-' + name;
 
 187     public void setResourceLockDao(ResourceLockDao resourceLockDao) {
 
 188         this.resourceLockDao = resourceLockDao;
 
 191     public void setRetryCount(int retryCount) {
 
 192         this.retryCount = retryCount;
 
 195     public void setLockWait(int lockWait /* Seconds */) {
 
 196         this.lockWait = lockWait;