492a48f0b07ca61d39bc47b401aec05b8f669998
[music.git] / music-core / src / main / java / org / onap / music / lockingservice / cassandra / LockCleanUpDaemon.java
1 /*
2  * ============LICENSE_START==========================================
3  * org.onap.music
4  * ===================================================================
5  *  Copyright (c) 2019 AT&T Intellectual Property
6  * ===================================================================
7  *  Licensed under the Apache License, Version 2.0 (the "License");
8  *  you may not use this file except in compliance with the License.
9  *  You may obtain a copy of the License at
10  * 
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS,
15  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  * 
19  * ============LICENSE_END=============================================
20  * ====================================================================
21  */
22
23 package org.onap.music.lockingservice.cassandra;
24
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Set;
28 import org.onap.music.datastore.MusicDataStoreHandle;
29 import org.onap.music.datastore.PreparedQueryObject;
30 import org.onap.music.eelf.logging.EELFLoggerDelegate;
31 import org.onap.music.exceptions.MusicQueryException;
32 import org.onap.music.exceptions.MusicServiceException;
33 import org.onap.music.main.MusicCore;
34 import org.onap.music.main.MusicUtil;
35 import com.datastax.driver.core.ResultSet;
36 import com.datastax.driver.core.Row;
37
38 public class LockCleanUpDaemon extends Thread {
39     
40     boolean terminated = false;
41     private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(LockCleanUpDaemon.class);
42
43     
44     public LockCleanUpDaemon() {
45     }
46     
47     @Override
48     public void run() {
49         if (MusicUtil.getLockDaemonSleepTimeMs()<0) {
50             terminate();
51         }
52         while (!terminated) {
53             try {
54                 cleanupStaleLocks();
55             } catch (MusicServiceException e) {
56                 logger.warn(EELFLoggerDelegate.applicationLogger, "Unable to clean up locks", e);
57             }
58             try {
59                 Thread.sleep(MusicUtil.getLockDaemonSleepTimeMs());
60             } catch (InterruptedException e) {
61                 e.printStackTrace();
62             }
63         }
64     }
65
66     private void cleanupStaleLocks() throws MusicServiceException {
67         Set<String> lockQTables = getLockQTables();
68         logger.info(EELFLoggerDelegate.applicationLogger, "Lock q tables found: " + lockQTables);
69         for(String lockTable: lockQTables) {
70             try {
71                 cleanUpLocksFromTable(lockTable);
72             } catch (MusicServiceException e) {
73                 logger.warn(EELFLoggerDelegate.applicationLogger, "Unable to clear locks on table " + lockTable, e);
74             }
75         }
76     }
77
78
79     private Set<String> getLockQTables() throws MusicServiceException {
80         Set<String> keyspacesToCleanUp = MusicUtil.getKeyspacesToCleanLocks();
81         Set<String> lockQTables = new HashSet<>();
82         
83         PreparedQueryObject query = new PreparedQueryObject();
84         query.appendQueryString("SELECT keyspace_name, table_name FROM system_schema.tables;");
85         ResultSet results = MusicCore.get(query);
86         
87         for (Row row: results) {
88             if (keyspacesToCleanUp.contains(row.getString("keyspace_name"))
89                     && row.getString("table_name").toLowerCase().startsWith(CassaLockStore.table_prepend_name.toLowerCase()) ) {
90                 lockQTables.add(row.getString("keyspace_name") + "." + row.getString("table_name"));
91             }
92         }
93         return lockQTables;
94     }
95
96     private void cleanUpLocksFromTable(String lockTable) throws MusicServiceException {
97         PreparedQueryObject query = new PreparedQueryObject();
98         query.appendQueryString("SELECT * from " + lockTable);
99         ResultSet results = MusicCore.get(query);
100         for (Row lock: results) {
101             if (!lock.isNull("lockreference")) {
102                 try {
103                     deleteLockIfStale(lockTable, lock);
104                 } catch (MusicServiceException e) {
105                     logger.warn(EELFLoggerDelegate.applicationLogger, "Unable to delete a potentially stale lock " + lock, e);
106                 }
107             }
108         }
109     }
110     
111     
112     private void deleteLockIfStale(String lockTable, Row lock) throws MusicServiceException {
113         if (lock.isNull("createtime") && lock.isNull("acquiretime")) {
114             return;
115         }
116
117         long createTime = lock.isNull("createtime") ? 0 : Long.parseLong(lock.getString("createtime"));
118         long acquireTime = lock.isNull("acquiretime") ? 0 : Long.parseLong(lock.getString("acquiretime"));
119         long row_access_time = Math.max(createTime, acquireTime);
120         if (System.currentTimeMillis() > row_access_time + MusicUtil.getDefaultLockLeasePeriod()) {
121             logger.info(EELFLoggerDelegate.applicationLogger, "Stale lock detected and being removed: " + lock);
122             PreparedQueryObject query = new PreparedQueryObject();
123             query.appendQueryString("DELETE FROM " + lockTable + " WHERE key='" + lock.getString("key") + "' AND " +
124                     "lockreference=" + lock.getLong("lockreference") + " IF EXISTS;");
125             MusicDataStoreHandle.getDSHandle().getSession().execute(query.getQuery());
126         }
127     }
128
129     public void terminate() {
130         terminated = true;
131     }
132 }