735d240c0b78cc4f94db85e2feda615f00c8ba47
[ccsdk/sli.git] /
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(resourceName, lockRequester, lockTimeout, lockWait, retryCount);
45     }
46
47     @Override
48     public void lock(String resourceName, String lockRequester, int lockTimeout /* Seconds */,
49             int lockWait /* Seconds */, int retryCount) {
50         lock(Collections.singleton(resourceName), lockRequester, lockTimeout, lockWait, retryCount);
51     }
52
53     @Override
54     public void unlock(String resourceName, boolean force) {
55         unlock(Collections.singleton(resourceName), force);
56     }
57
58     @Override
59     public void lock(Collection<String> resourceNameList, String lockRequester, int lockTimeout /* Seconds */) {
60         lock(resourceNameList, lockRequester, lockTimeout, lockWait, retryCount);
61     }
62
63     @Override
64     public void lock(Collection<String> resourceNameList, String lockRequester, int lockTimeout /* Seconds */,
65             int lockWait /* Seconds */, int retryCount) {
66         for (int i = 0; true; i++) {
67             try {
68                 tryLock(resourceNameList, lockRequester, lockTimeout);
69                 log.info("Resources locked: " + resourceNameList);
70                 return;
71             } catch (ResourceLockedException e) {
72                 if (i >= retryCount) {
73                     throw e;
74                 }
75                 try {
76                     Thread.sleep(lockWait * 1000);
77                 } catch (InterruptedException ex) {
78                     log.error("Interrupted Exception", ex);
79                 }
80             }
81         }
82     }
83
84     @Override
85     public void unlock(Collection<String> lockNames, boolean force) {
86         if (lockNames == null || lockNames.isEmpty()) {
87             return;
88         }
89
90         try {
91             for (String name : lockNames) {
92                 ResourceLock l = resourceLockDao.getByResourceName(name);
93                 if (l != null) {
94                     if (force || l.lockCount == 1) {
95                         resourceLockDao.delete(l.id);
96                     } else {
97                         resourceLockDao.decrementLockCount(l.id);
98                     }
99                 }
100             }
101
102             resourceLockDao.commit();
103
104             log.info("Resources unlocked: " + lockNames);
105         } finally {
106             resourceLockDao.rollback();
107         }
108     }
109
110     public void tryLock(Collection<String> resourceNameList, String lockRequester, int lockTimeout /* Seconds */) {
111         if (resourceNameList == null || resourceNameList.isEmpty()) {
112             return;
113         }
114
115         lockRequester = generateLockRequester(lockRequester, 100);
116
117         // First check if all requested records are available to lock
118
119         Date now = new Date();
120
121         try {
122             List<ResourceLock> dbLockList = new ArrayList<>();
123             List<String> insertLockNameList = new ArrayList<>();
124             for (String name : resourceNameList) {
125                 ResourceLock l = resourceLockDao.getByResourceName(name);
126
127                 boolean canLock = l == null || now.getTime() > l.expirationTime.getTime() ||
128                         lockRequester != null && lockRequester.equals(l.lockHolder) || l.lockCount <= 0;
129                 if (!canLock) {
130                     throw new ResourceLockedException(l.resourceName, l.lockHolder, lockRequester);
131                 }
132
133                 if (l != null) {
134                     if (now.getTime() > l.expirationTime.getTime() || l.lockCount <= 0) {
135                         l.lockCount = 0;
136                     }
137                     dbLockList.add(l);
138                 } else {
139                     insertLockNameList.add(name);
140                 }
141             }
142
143             // Update the lock info in DB
144             for (ResourceLock l : dbLockList) {
145                 resourceLockDao.update(l.id, lockRequester, now, new Date(now.getTime() + lockTimeout * 1000), l.lockCount + 1);
146             }
147
148             // Insert records for those that are not yet there
149             for (String lockName : insertLockNameList) {
150                 ResourceLock l = new ResourceLock();
151                 l.resourceName = lockName;
152                 l.lockHolder = lockRequester;
153                 l.lockTime = now;
154                 l.expirationTime = new Date(now.getTime() + lockTimeout * 1000);
155                 l.lockCount = 1;
156
157                 try {
158                     resourceLockDao.add(l);
159                 } catch (Exception e) {
160                     log.info("Failed to insert lock record: " + lockName);
161                     throw new ResourceLockedException(l.resourceName, "unknown", lockRequester);
162                 }
163             }
164
165             resourceLockDao.commit();
166
167         }finally
168
169         {
170             resourceLockDao.rollback();
171         }
172     }
173
174     private static String generateLockRequester(String name, int maxLength) {
175         if (name == null) {
176             name = "";
177         }
178         int l1 = name.length();
179         String tname = Thread.currentThread().getName();
180         int l2 = tname.length();
181         if (l1 + l2 + 1 > maxLength) {
182             int maxl1 = maxLength / 2;
183             if (l1 > maxl1) {
184                 name = name.substring(0, maxl1);
185                 l1 = maxl1;
186             }
187             int maxl2 = maxLength - l1 - 1;
188             if (l2 > maxl2) {
189                 tname = tname.substring(0, 6) + "..." + tname.substring(l2 - maxl2 + 9);
190             }
191         }
192         return tname + '-' + name;
193     }
194
195     public void setResourceLockDao(ResourceLockDao resourceLockDao) {
196         this.resourceLockDao = resourceLockDao;
197     }
198
199     public void setRetryCount(int retryCount) {
200         this.retryCount = retryCount;
201     }
202
203     public void setLockWait(int lockWait /* Seconds */) {
204         this.lockWait = lockWait;
205     }
206 }