aboutsummaryrefslogtreecommitdiffstats
path: root/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock
diff options
context:
space:
mode:
Diffstat (limited to 'resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock')
-rw-r--r--resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/comp/LockHelper.java35
-rw-r--r--resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/comp/LockHelperImpl.java166
-rw-r--r--resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/comp/ResourceLockedException.java41
-rw-r--r--resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/comp/SynchronizedFunction.java56
-rw-r--r--resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/dao/ResourceLockDao.java43
-rw-r--r--resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/dao/ResourceLockDaoImpl.java109
-rw-r--r--resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/data/ResourceLock.java34
7 files changed, 484 insertions, 0 deletions
diff --git a/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/comp/LockHelper.java b/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/comp/LockHelper.java
new file mode 100644
index 0000000..c7b5466
--- /dev/null
+++ b/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/comp/LockHelper.java
@@ -0,0 +1,35 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdnc.lock.comp;
+
+import java.util.Collection;
+
+public interface LockHelper {
+
+ void lock(String resourceName, String lockRequester, int lockTimeout /* Seconds */);
+
+ void unlock(String resourceName, boolean force);
+
+ void lock(Collection<String> resourceNameList, String lockRequester, int lockTimeout /* Seconds */);
+
+ void unlock(Collection<String> resourceNameList, boolean force);
+}
diff --git a/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/comp/LockHelperImpl.java b/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/comp/LockHelperImpl.java
new file mode 100644
index 0000000..139abfe
--- /dev/null
+++ b/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/comp/LockHelperImpl.java
@@ -0,0 +1,166 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdnc.lock.comp;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import org.openecomp.sdnc.lock.dao.ResourceLockDao;
+import org.openecomp.sdnc.lock.data.ResourceLock;
+
+public class LockHelperImpl implements LockHelper {
+
+ private ResourceLockDao resourceLockDao;
+ private int retryCount = 10;
+ private int lockWait = 5; // Seconds
+
+ @Override
+ public void lock(String resourceName, String lockRequester, int lockTimeout /* Seconds */) {
+ lock(Collections.singleton(resourceName), lockRequester, lockTimeout);
+ }
+
+ @Override
+ public void unlock(String resourceName, boolean force) {
+ unlock(Collections.singleton(resourceName), force);
+ }
+
+ @Override
+ public void lock(Collection<String> resourceNameList, String lockRequester, int lockTimeout /* Seconds */) {
+ for (int i = 0; true; i++) {
+ try {
+ tryLock(resourceNameList, lockRequester, lockTimeout);
+ return;
+ } catch (ResourceLockedException e) {
+ if (i > retryCount)
+ throw e;
+ try {
+ Thread.sleep(lockWait * 1000);
+ } catch (InterruptedException ex) {
+ }
+ }
+ }
+ }
+
+ @Override
+ public void unlock(Collection<String> lockNames, boolean force) {
+ if (lockNames == null || lockNames.size() == 0)
+ return;
+
+ resourceLockDao.lockTable();
+
+ try {
+ for (String name : lockNames) {
+ ResourceLock l = resourceLockDao.getByResourceName(name);
+ if (l != null)
+ if (force || l.lockCount == 1)
+ resourceLockDao.delete(l.id);
+ else
+ resourceLockDao.decrementLockCount(l.id);
+ }
+ } finally {
+ resourceLockDao.unlockTable();
+ }
+ }
+
+ public void tryLock(Collection<String> resourceNameList, String lockRequester, int lockTimeout /* Seconds */) {
+ if (resourceNameList == null || resourceNameList.size() == 0)
+ return;
+
+ lockRequester = generateLockRequester(lockRequester, 100);
+
+ resourceLockDao.lockTable();
+
+ try {
+ // First check if all requested records are available to lock
+
+ Date now = new Date();
+
+ List<ResourceLock> dbLockList = new ArrayList<ResourceLock>();
+ List<String> insertLockNameList = new ArrayList<String>();
+ for (String name : resourceNameList) {
+ ResourceLock l = resourceLockDao.getByResourceName(name);
+
+ boolean canLock =
+ l == null || now.getTime() > l.expirationTime.getTime() || lockRequester != null &&
+ lockRequester.equals(l.lockHolder) || l.lockCount <= 0;
+ if (!canLock)
+ throw new ResourceLockedException(l.resourceName, l.lockHolder, lockRequester);
+
+ if (l != null)
+ dbLockList.add(l);
+ else
+ insertLockNameList.add(name);
+ }
+
+ // Update the lock info in DB
+ for (ResourceLock l : dbLockList)
+ resourceLockDao.update(l.id, now, new Date(now.getTime() + lockTimeout * 1000), l.lockCount + 1);
+
+ // Insert records for those that are not yet there
+ for (String lockName : insertLockNameList) {
+ ResourceLock l = new ResourceLock();
+ l.resourceName = lockName;
+ l.lockHolder = lockRequester;
+ l.lockTime = now;
+ l.expirationTime = new Date(now.getTime() + lockTimeout * 1000);
+ l.lockCount = 1;
+ resourceLockDao.add(l);
+ }
+ } finally {
+ resourceLockDao.unlockTable();
+ }
+ }
+
+ private static String generateLockRequester(String name, int maxLength) {
+ if (name == null)
+ name = "";
+ int l1 = name.length();
+ String tname = Thread.currentThread().getName();
+ int l2 = tname.length();
+ if (l1 + l2 + 1 > maxLength) {
+ int maxl1 = maxLength / 2;
+ if (l1 > maxl1) {
+ name = name.substring(0, maxl1);
+ l1 = maxl1;
+ }
+ int maxl2 = maxLength - l1 - 1;
+ if (l2 > maxl2)
+ tname = tname.substring(0, 6) + "..." + tname.substring(l2 - maxl2 + 9);
+ }
+ return tname + '-' + name;
+ }
+
+ public void setResourceLockDao(ResourceLockDao resourceLockDao) {
+ this.resourceLockDao = resourceLockDao;
+ }
+
+ public void setRetryCount(int retryCount) {
+ this.retryCount = retryCount;
+ }
+
+ public void setLockWait(int lockWait /* Seconds */) {
+ this.lockWait = lockWait;
+ }
+}
diff --git a/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/comp/ResourceLockedException.java b/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/comp/ResourceLockedException.java
new file mode 100644
index 0000000..b2fa942
--- /dev/null
+++ b/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/comp/ResourceLockedException.java
@@ -0,0 +1,41 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdnc.lock.comp;
+
+public class ResourceLockedException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ private String lockName, lockHolder, lockRequester;
+
+ public ResourceLockedException(String lockName, String lockHolder, String lockRequester) {
+ this.lockName = lockName;
+ this.lockHolder = lockHolder;
+ this.lockRequester = lockRequester;
+ }
+
+ @Override
+ public String getMessage() {
+ return "Failed to lock [" + lockName + "] for [" + lockRequester + "]. Currently locked by [" + lockHolder +
+ "].";
+ }
+}
diff --git a/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/comp/SynchronizedFunction.java b/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/comp/SynchronizedFunction.java
new file mode 100644
index 0000000..0bbb053
--- /dev/null
+++ b/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/comp/SynchronizedFunction.java
@@ -0,0 +1,56 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdnc.lock.comp;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+public abstract class SynchronizedFunction {
+
+ private Set<String> synchset;
+ private String lockRequester;
+ private int lockTimeout; // Seconds
+ private LockHelper lockHelper;
+
+ protected SynchronizedFunction(LockHelper lockHelper, Collection<String> synchset, int lockTimeout) {
+ this.lockHelper = lockHelper;
+ this.synchset = new HashSet<String>(synchset);
+ this.lockRequester = generateLockRequester();
+ this.lockTimeout = lockTimeout;
+ }
+
+ protected abstract void _exec();
+
+ public void exec() {
+ lockHelper.lock(synchset, lockRequester, lockTimeout);
+ try {
+ _exec();
+ } finally {
+ lockHelper.unlock(synchset, true);
+ }
+ }
+
+ private static String generateLockRequester() {
+ return "SynchronizedFunction-" + (int) (Math.random() * 1000000);
+ }
+}
diff --git a/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/dao/ResourceLockDao.java b/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/dao/ResourceLockDao.java
new file mode 100644
index 0000000..3dcc511
--- /dev/null
+++ b/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/dao/ResourceLockDao.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdnc.lock.dao;
+
+import java.util.Date;
+
+import org.openecomp.sdnc.lock.data.ResourceLock;
+
+public interface ResourceLockDao {
+
+ void lockTable();
+
+ void unlockTable();
+
+ void add(ResourceLock l);
+
+ void update(long id, Date lockTime, Date expirationTime, int lockCount);
+
+ ResourceLock getByResourceName(String resourceName);
+
+ void delete(long id);
+
+ void decrementLockCount(long id);
+}
diff --git a/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/dao/ResourceLockDaoImpl.java b/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/dao/ResourceLockDaoImpl.java
new file mode 100644
index 0000000..7edd156
--- /dev/null
+++ b/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/dao/ResourceLockDaoImpl.java
@@ -0,0 +1,109 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdnc.lock.dao;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Date;
+import java.util.List;
+
+import org.openecomp.sdnc.lock.data.ResourceLock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+
+public class ResourceLockDaoImpl implements ResourceLockDao {
+
+ private static final Logger log = LoggerFactory.getLogger(ResourceLockDaoImpl.class);
+
+ private JdbcTemplate jdbcTemplate;
+ private boolean testing = false;
+
+ @Override
+ public void lockTable() {
+ if (!testing)
+ jdbcTemplate.update("LOCK TABLE RESOURCE_LOCK WRITE");
+ log.info("Table RESOURCE_LOCK locked.");
+ }
+
+ @Override
+ public void unlockTable() {
+ if (!testing)
+ jdbcTemplate.update("UNLOCK TABLES");
+ log.info("Table RESOURCE_LOCK unlocked.");
+ }
+
+ @Override
+ public void add(ResourceLock l) {
+ jdbcTemplate.update(
+ "INSERT INTO RESOURCE_LOCK (resource_name, lock_holder, lock_count, lock_time, expiration_time)\n" +
+ "VALUES (?, ?, ?, ?, ?)",
+ new Object[] { l.resourceName, l.lockHolder, l.lockCount, l.lockTime, l.expirationTime });
+ }
+
+ @Override
+ public void update(long id, Date lockTime, Date expirationTime, int lockCount) {
+ jdbcTemplate.update(
+ "UPDATE RESOURCE_LOCK SET lock_time = ?, expiration_time = ?, lock_count = ? WHERE resource_lock_id = ?",
+ new Object[] { lockTime, expirationTime, lockCount, id });
+ }
+
+ @Override
+ public ResourceLock getByResourceName(String resourceName) {
+ List<ResourceLock> ll = jdbcTemplate.query("SELECT * FROM RESOURCE_LOCK WHERE resource_name = ?",
+ new Object[] { resourceName }, new RowMapper<ResourceLock>() {
+
+ @Override
+ public ResourceLock mapRow(ResultSet rs, int rowNum) throws SQLException {
+ ResourceLock rl = new ResourceLock();
+ rl.id = rs.getLong("resource_lock_id");
+ rl.resourceName = rs.getString("resource_name");
+ rl.lockHolder = rs.getString("lock_holder");
+ rl.lockCount = rs.getInt("lock_count");
+ rl.lockTime = rs.getTimestamp("lock_time");
+ rl.expirationTime = rs.getTimestamp("expiration_time");
+ return rl;
+ }
+ });
+ return ll != null && !ll.isEmpty() ? ll.get(0) : null;
+ }
+
+ @Override
+ public void delete(long id) {
+ jdbcTemplate.update("DELETE FROM RESOURCE_LOCK WHERE resource_lock_id = ?", new Object[] { id });
+ }
+
+ @Override
+ public void decrementLockCount(long id) {
+ jdbcTemplate.update("UPDATE RESOURCE_LOCK SET lock_count = lock_count - 1 WHERE resource_lock_id = ?",
+ new Object[] { id });
+ }
+
+ public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+
+ public void setTesting(boolean testing) {
+ this.testing = testing;
+ }
+}
diff --git a/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/data/ResourceLock.java b/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/data/ResourceLock.java
new file mode 100644
index 0000000..052e38f
--- /dev/null
+++ b/resource-assignment/provider/src/main/java/org/openecomp/sdnc/lock/data/ResourceLock.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdnc.lock.data;
+
+import java.util.Date;
+
+public class ResourceLock {
+
+ public long id;
+ public String resourceName;
+ public String lockHolder;
+ public int lockCount;
+ public Date lockTime;
+ public Date expirationTime;
+}