[CCSDK-245] RA: Refactor RA to make it generic
[ccsdk/sli/adaptors.git] / resource-assignment / provider / src / main / java / org / onap / ccsdk / sli / adaptors / lock / comp / LockHelperImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openECOMP : SDN-C
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
6  *                         reserved.
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
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
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=========================================================
20  */
21
22 package org.onap.ccsdk.sli.adaptors.lock.comp;
23
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;
33
34 public class LockHelperImpl implements LockHelper {
35
36     private static final Logger log = LoggerFactory.getLogger(LockHelperImpl.class);
37
38     private ResourceLockDao resourceLockDao;
39     private int retryCount = 10;
40     private int lockWait = 5; // Seconds
41
42     @Override
43     public void lock(String resourceName, String lockRequester, int lockTimeout /* Seconds */) {
44         lock(Collections.singleton(resourceName), lockRequester, lockTimeout);
45     }
46
47     @Override
48     public void unlock(String resourceName, boolean force) {
49         unlock(Collections.singleton(resourceName), force);
50     }
51
52     @Override
53     public void lock(Collection<String> resourceNameList, String lockRequester, int lockTimeout /* Seconds */) {
54         for (int i = 0; true; i++) {
55             try {
56                 tryLock(resourceNameList, lockRequester, lockTimeout);
57                 log.info("Resources locked: " + resourceNameList);
58                 return;
59             } catch (ResourceLockedException e) {
60                 if (i > retryCount) {
61                     throw e;
62                 }
63                 try {
64                     Thread.sleep(lockWait * 1000);
65                 } catch (InterruptedException ex) {
66                 }
67             }
68         }
69     }
70
71     @Override
72     public void unlock(Collection<String> lockNames, boolean force) {
73         if (lockNames == null || lockNames.size() == 0) {
74             return;
75         }
76
77         try {
78             for (String name : lockNames) {
79                 ResourceLock l = resourceLockDao.getByResourceName(name);
80                 if (l != null) {
81                     if (force || l.lockCount == 1) {
82                         resourceLockDao.delete(l.id);
83                     } else {
84                         resourceLockDao.decrementLockCount(l.id);
85                     }
86                 }
87             }
88
89             resourceLockDao.commit();
90
91             log.info("Resources unlocked: " + lockNames);
92         } finally {
93             resourceLockDao.rollback();
94         }
95     }
96
97     public void tryLock(Collection<String> resourceNameList, String lockRequester, int lockTimeout /* Seconds */) {
98         if (resourceNameList == null || resourceNameList.size() == 0) {
99             return;
100         }
101
102         lockRequester = generateLockRequester(lockRequester, 100);
103
104         // First check if all requested records are available to lock
105
106         Date now = new Date();
107
108         try {
109             List<ResourceLock> dbLockList = new ArrayList<>();
110             List<String> insertLockNameList = new ArrayList<>();
111             for (String name : resourceNameList) {
112                 ResourceLock l = resourceLockDao.getByResourceName(name);
113
114                 boolean canLock = l == null || now.getTime() > l.expirationTime.getTime() ||
115                         lockRequester != null && lockRequester.equals(l.lockHolder) || l.lockCount <= 0;
116                 if (!canLock) {
117                     throw new ResourceLockedException(l.resourceName, l.lockHolder, lockRequester);
118                 }
119
120                 if (l != null) {
121                     dbLockList.add(l);
122                 } else {
123                     insertLockNameList.add(name);
124                 }
125             }
126
127             // Update the lock info in DB
128             for (ResourceLock l : dbLockList) {
129                 resourceLockDao.update(l.id, now, new Date(now.getTime() + lockTimeout * 1000), l.lockCount + 1);
130             }
131
132             // Insert records for those that are not yet there
133             for (String lockName : insertLockNameList) {
134                 ResourceLock l = new ResourceLock();
135                 l.resourceName = lockName;
136                 l.lockHolder = lockRequester;
137                 l.lockTime = now;
138                 l.expirationTime = new Date(now.getTime() + lockTimeout * 1000);
139                 l.lockCount = 1;
140
141                 try {
142                     resourceLockDao.add(l);
143                 } catch (Exception e) {
144                     log.info("Failed to insert lock record: " + lockName);
145                     throw new ResourceLockedException(l.resourceName, "unknown", lockRequester);
146                 }
147             }
148
149             resourceLockDao.commit();
150
151         } finally {
152             resourceLockDao.rollback();
153         }
154     }
155
156     private static String generateLockRequester(String name, int maxLength) {
157         if (name == null) {
158             name = "";
159         }
160         int l1 = name.length();
161         String tname = Thread.currentThread().getName();
162         int l2 = tname.length();
163         if (l1 + l2 + 1 > maxLength) {
164             int maxl1 = maxLength / 2;
165             if (l1 > maxl1) {
166                 name = name.substring(0, maxl1);
167                 l1 = maxl1;
168             }
169             int maxl2 = maxLength - l1 - 1;
170             if (l2 > maxl2) {
171                 tname = tname.substring(0, 6) + "..." + tname.substring(l2 - maxl2 + 9);
172             }
173         }
174         return tname + '-' + name;
175     }
176
177     public void setResourceLockDao(ResourceLockDao resourceLockDao) {
178         this.resourceLockDao = resourceLockDao;
179     }
180
181     public void setRetryCount(int retryCount) {
182         this.retryCount = retryCount;
183     }
184
185     public void setLockWait(int lockWait /* Seconds */) {
186         this.lockWait = lockWait;
187     }
188 }