2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (c) 2017 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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * ============LICENSE_END=============================================
20 * ====================================================================
22 package org.onap.music.main;
25 import java.io.StringWriter;
26 import java.util.HashMap;
28 import java.util.StringTokenizer;
30 import org.apache.zookeeper.KeeperException;
31 import org.apache.zookeeper.KeeperException.NoNodeException;
32 import org.onap.music.datastore.MusicDataStore;
33 import org.onap.music.datastore.PreparedQueryObject;
34 import org.onap.music.datastore.jsonobjects.JsonKeySpace;
35 import org.onap.music.eelf.logging.EELFLoggerDelegate;
36 import org.onap.music.eelf.logging.format.AppMessages;
37 import org.onap.music.eelf.logging.format.ErrorSeverity;
38 import org.onap.music.eelf.logging.format.ErrorTypes;
39 import org.onap.music.exceptions.MusicLockingException;
40 import org.onap.music.exceptions.MusicQueryException;
41 import org.onap.music.exceptions.MusicServiceException;
42 import org.onap.music.lockingservice.MusicLockState;
43 import org.onap.music.lockingservice.MusicLockState.LockStatus;
44 import org.onap.music.lockingservice.MusicLockingService;
46 import com.datastax.driver.core.ColumnDefinitions;
47 import com.datastax.driver.core.ColumnDefinitions.Definition;
48 import com.datastax.driver.core.DataType;
49 import com.datastax.driver.core.ResultSet;
50 import com.datastax.driver.core.Row;
51 import com.datastax.driver.core.TableMetadata;
58 public class MusicCore {
60 public static MusicLockingService mLockHandle = null;
61 public static MusicDataStore mDstoreHandle = null;
62 private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicCore.class);
64 public static class Condition {
65 Map<String, Object> conditions;
66 PreparedQueryObject selectQueryForTheRow;
68 public Condition(Map<String, Object> conditions, PreparedQueryObject selectQueryForTheRow) {
69 this.conditions = conditions;
70 this.selectQueryForTheRow = selectQueryForTheRow;
73 public boolean testCondition() throws Exception {
74 // first generate the row
75 ResultSet results = quorumGet(selectQueryForTheRow);
76 Row row = results.one();
77 return getDSHandle().doesRowSatisfyCondition(row, conditions);
82 public static MusicLockingService getLockingServiceHandle() throws MusicLockingException {
83 logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring lock store handle");
84 long start = System.currentTimeMillis();
86 if (mLockHandle == null) {
88 mLockHandle = new MusicLockingService();
89 } catch (Exception e) {
90 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKHANDLE,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
91 throw new MusicLockingException("Failed to aquire Locl store handle " + e);
94 long end = System.currentTimeMillis();
95 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire lock store handle:" + (end - start) + " ms");
104 public static MusicDataStore getDSHandle(String remoteIp) {
105 logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring data store handle");
106 long start = System.currentTimeMillis();
107 if (mDstoreHandle == null) {
109 MusicUtil.loadProperties();
110 } catch (Exception e) {
111 logger.error(EELFLoggerDelegate.errorLogger, "No properties file defined. Falling back to default.");
113 mDstoreHandle = new MusicDataStore(remoteIp);
115 long end = System.currentTimeMillis();
116 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms");
117 return mDstoreHandle;
123 * @throws MusicServiceException
125 public static MusicDataStore getDSHandle() throws MusicServiceException {
126 logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring data store handle");
127 long start = System.currentTimeMillis();
128 if (mDstoreHandle == null) {
130 MusicUtil.loadProperties();
131 } catch (Exception e) {
132 logger.error(EELFLoggerDelegate.errorLogger, "No properties file defined. Falling back to default.");
134 // Quick Fix - Best to put this into every call to getDSHandle?
135 if (! MusicUtil.getMyCassaHost().equals("localhost") ) {
136 mDstoreHandle = new MusicDataStore(MusicUtil.getMyCassaHost());
138 mDstoreHandle = new MusicDataStore();
141 if(mDstoreHandle.getSession() == null) {
142 String message = "Connection to Cassandra has not been enstablished."
143 + " Please check connection properites and reboot.";
144 logger.info(EELFLoggerDelegate.applicationLogger, message);
145 throw new MusicServiceException(message);
147 long end = System.currentTimeMillis();
148 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms");
149 return mDstoreHandle;
152 public static String createLockReference(String lockName) {
153 logger.info(EELFLoggerDelegate.applicationLogger,"Creating lock reference for lock name:" + lockName);
154 long start = System.currentTimeMillis();
155 String lockId = null;
157 lockId = getLockingServiceHandle().createLockId("/" + lockName);
158 } catch (MusicLockingException e) {
159 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.CREATELOCK+lockName,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
162 long end = System.currentTimeMillis();
163 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to create lock reference:" + (end - start) + " ms");
172 public static boolean isTableOrKeySpaceLock(String key) {
173 String[] splitString = key.split("\\.");
174 if (splitString.length > 2)
185 public static MusicLockState getMusicLockState(String key) {
186 long start = System.currentTimeMillis();
188 String[] splitString = key.split("\\.");
189 String keyspaceName = splitString[0];
190 String tableName = splitString[1];
191 String primaryKey = splitString[2];
193 String lockName = keyspaceName + "." + tableName + "." + primaryKey;
194 mls = getLockingServiceHandle().getLockState(lockName);
195 long end = System.currentTimeMillis();
196 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to get lock state:" + (end - start) + " ms");
198 } catch (NullPointerException | MusicLockingException e) {
199 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
204 public static ReturnType acquireLockWithLease(String key, String lockId, long leasePeriod) {
206 long start = System.currentTimeMillis();
207 /* check if the current lock has exceeded its lease and if yes, release that lock */
208 MusicLockState mls = getMusicLockState(key);
210 if (mls.getLockStatus().equals(LockStatus.LOCKED)) {
211 logger.info(EELFLoggerDelegate.applicationLogger,"The current lock holder for " + key + " is " + mls.getLockHolder()
212 + ". Checking if it has exceeded lease");
213 long currentLockPeriod = System.currentTimeMillis() - mls.getLeaseStartTime();
214 long currentLeasePeriod = mls.getLeasePeriod();
215 if (currentLockPeriod > currentLeasePeriod) {
216 logger.info(EELFLoggerDelegate.applicationLogger,"Lock period " + currentLockPeriod
217 + " has exceeded lease period " + currentLeasePeriod);
218 boolean voluntaryRelease = false;
219 String currentLockHolder = mls.getLockHolder();
220 mls = releaseLock(currentLockHolder, voluntaryRelease);
224 logger.error(EELFLoggerDelegate.errorLogger,key, AppMessages.INVALIDLOCK,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
227 * call the traditional acquire lock now and if the result returned is true, set the
228 * begin time-stamp and lease period
230 if (acquireLock(key, lockId).getResult() == ResultType.SUCCESS) {
231 mls = getMusicLockState(key);// get latest state
233 logger.info(EELFLoggerDelegate.applicationLogger,"Music Lock State is null");
234 return new ReturnType(ResultType.FAILURE, "Could not acquire lock, Lock State is null");
236 if (mls.getLeaseStartTime() == -1) {// set it again only if it is not set already
237 mls.setLeaseStartTime(System.currentTimeMillis());
238 mls.setLeasePeriod(leasePeriod);
239 getLockingServiceHandle().setLockState(key, mls);
241 long end = System.currentTimeMillis();
242 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire leased lock:" + (end - start) + " ms");
243 return new ReturnType(ResultType.SUCCESS, "Accquired lock");
245 long end = System.currentTimeMillis();
246 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to fail to acquire leased lock:" + (end - start) + " ms");
247 return new ReturnType(ResultType.FAILURE, "Could not acquire lock");
249 } catch (Exception e) {
250 StringWriter sw = new StringWriter();
251 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR506E] Failed to aquire lock ",ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
253 String exceptionAsString = sw.toString();
254 return new ReturnType(ResultType.FAILURE,
255 "Exception thrown in acquireLockWithLease:\n" + exceptionAsString);
259 public static ReturnType acquireLock(String key, String lockId) throws MusicLockingException {
261 * first check if I am on top. Since ids are not reusable there is no need to check
262 * lockStatus If the status is unlocked, then the above call will automatically return
265 Boolean result = false;
267 result = getLockingServiceHandle().isMyTurn(lockId);
268 } catch (MusicLockingException e2) {
269 logger.error(EELFLoggerDelegate.errorLogger,AppMessages.INVALIDLOCK + lockId + " " + e2);
270 throw new MusicLockingException();
273 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Not your turn, someone else has the lock");
275 if (!getLockingServiceHandle().lockIdExists(lockId)) {
276 logger.info(EELFLoggerDelegate.applicationLogger, "In acquire lock: this lockId doesn't exist");
277 return new ReturnType(ResultType.FAILURE, "Lockid doesn't exist");
279 } catch (MusicLockingException e) {
280 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
281 throw new MusicLockingException();
283 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: returning failure");
284 return new ReturnType(ResultType.FAILURE, "Not your turn, someone else has the lock");
288 // this is for backward compatibility where locks could also be acquired on just
289 // keyspaces or tables.
290 if (isTableOrKeySpaceLock(key)) {
291 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: A table or keyspace lock so no need to perform sync...so returning true");
292 return new ReturnType(ResultType.SUCCESS, "A table or keyspace lock so no need to perform sync...so returning true");
295 // read the lock name corresponding to the key and if the status is locked or being locked,
297 MusicLockState currentMls = null;
298 MusicLockState newMls = null;
300 currentMls = getMusicLockState(key);
301 String currentLockHolder = currentMls.getLockHolder();
302 if (lockId.equals(currentLockHolder)) {
303 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: You already have the lock!");
304 return new ReturnType(ResultType.SUCCESS, "You already have the lock!");
306 } catch (NullPointerException e) {
307 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
310 // change status to "being locked". This state transition is necessary to ensure syncing
311 // before granting the lock
312 String lockHolder = null;
313 boolean needToSyncQuorum = false;
314 if (currentMls != null)
315 needToSyncQuorum = currentMls.isNeedToSyncQuorum();
318 newMls = new MusicLockState(MusicLockState.LockStatus.BEING_LOCKED, lockHolder,
321 getLockingServiceHandle().setLockState(key, newMls);
322 } catch (MusicLockingException e1) {
323 logger.error(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
325 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to being_locked");
327 // do syncing if this was a forced lock release
328 if (needToSyncQuorum) {
329 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Since there was a forcible release, need to sync quorum!");
332 } catch (Exception e) {
333 logger.error(EELFLoggerDelegate.errorLogger,"Failed to set Lock state " + e);
337 // change status to locked
339 needToSyncQuorum = false;
340 newMls = new MusicLockState(MusicLockState.LockStatus.LOCKED, lockHolder, needToSyncQuorum);
342 getLockingServiceHandle().setLockState(key, newMls);
343 } catch (MusicLockingException e) {
344 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
346 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to locked and assigned current lock ref "
347 + lockId + " as holder");
349 return new ReturnType(result?ResultType.SUCCESS:ResultType.FAILURE, "Set lock state to locked and assigned a lock holder");
356 * @param keyspaceName
361 public boolean createKeyspace(String keyspaceName, JsonKeySpace kspObject) throws Exception {
366 private static void syncQuorum(String key) throws Exception {
367 logger.info(EELFLoggerDelegate.applicationLogger,"Performing sync operation---");
368 String[] splitString = key.split("\\.");
369 String keyspaceName = splitString[0];
370 String tableName = splitString[1];
371 String primaryKeyValue = splitString[2];
372 PreparedQueryObject selectQuery = new PreparedQueryObject();
373 PreparedQueryObject updateQuery = new PreparedQueryObject();
375 // get the primary key d
376 TableMetadata tableInfo = returnColumnMetadata(keyspaceName, tableName);
377 String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();// we only support single
379 DataType primaryKeyType = tableInfo.getPrimaryKey().get(0).getType();
380 Object cqlFormattedPrimaryKeyValue =
381 MusicUtil.convertToActualDataType(primaryKeyType, primaryKeyValue);
383 // get the row of data from a quorum
384 selectQuery.appendQueryString("SELECT * FROM " + keyspaceName + "." + tableName + " WHERE "
385 + primaryKeyName + "= ?" + ";");
386 selectQuery.addValue(cqlFormattedPrimaryKeyValue);
387 ResultSet results = null;
389 results = getDSHandle().executeCriticalGet(selectQuery);
390 // write it back to a quorum
391 Row row = results.one();
392 ColumnDefinitions colInfo = row.getColumnDefinitions();
393 int totalColumns = colInfo.size();
395 StringBuilder fieldValueString = new StringBuilder("");
396 for (Definition definition : colInfo) {
397 String colName = definition.getName();
398 if (colName.equals(primaryKeyName))
400 DataType colType = definition.getType();
401 Object valueObj = getDSHandle().getColValue(row, colName, colType);
402 Object valueString = MusicUtil.convertToActualDataType(colType, valueObj);
403 fieldValueString.append(colName + " = ?");
404 updateQuery.addValue(valueString);
405 if (counter != (totalColumns - 1))
406 fieldValueString.append(",");
407 counter = counter + 1;
409 updateQuery.appendQueryString("UPDATE " + keyspaceName + "." + tableName + " SET "
410 + fieldValueString + " WHERE " + primaryKeyName + "= ? " + ";");
411 updateQuery.addValue(cqlFormattedPrimaryKeyValue);
413 getDSHandle().executePut(updateQuery, "critical");
414 } catch (MusicServiceException | MusicQueryException e) {
415 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.QUERYERROR +""+updateQuery ,ErrorSeverity.MAJOR, ErrorTypes.QUERYERROR);
427 public static ResultSet quorumGet(PreparedQueryObject query) {
428 ResultSet results = null;
430 results = getDSHandle().executeCriticalGet(query);
431 } catch (MusicServiceException | MusicQueryException e) {
432 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.MAJOR, ErrorTypes.GENERALSERVICEERROR);
443 * @throws MusicServiceException
445 public static Map<String, HashMap<String, Object>> marshallResults(ResultSet results) throws MusicServiceException {
446 return getDSHandle().marshalData(results);
454 public static String whoseTurnIsIt(String lockName) {
457 return getLockingServiceHandle().whoseTurnIsIt("/" + lockName) + "";
458 } catch (MusicLockingException e) {
459 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKINGERROR+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
471 public static String getLockNameFromId(String lockId) {
472 StringTokenizer st = new StringTokenizer(lockId);
473 return st.nextToken("$");
476 public static void destroyLockRef(String lockId) {
477 long start = System.currentTimeMillis();
479 getLockingServiceHandle().unlockAndDeleteId(lockId);
480 } catch (MusicLockingException | NoNodeException e) {
481 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DESTROYLOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
483 long end = System.currentTimeMillis();
484 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to destroy lock reference:" + (end - start) + " ms");
487 public static MusicLockState releaseLock(String lockId, boolean voluntaryRelease) {
488 long start = System.currentTimeMillis();
490 getLockingServiceHandle().unlockAndDeleteId(lockId);
491 } catch (MusicLockingException e1) {
492 logger.error(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
493 } catch (KeeperException.NoNodeException nne) {
494 logger.error(EELFLoggerDelegate.errorLogger,"Failed to release Lock " + lockId + " " + nne);
495 MusicLockState mls = new MusicLockState("Lock doesn't exists. Release lock operation failed.");
498 String lockName = getLockNameFromId(lockId);
500 String lockHolder = null;
501 if (voluntaryRelease) {
502 mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder);
503 logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock voluntarily released for " + lockId);
505 boolean needToSyncQuorum = true;
506 mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder,
508 logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock forcibly released for " + lockId);
511 getLockingServiceHandle().setLockState(lockName, mls);
512 } catch (MusicLockingException e) {
513 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
515 long end = System.currentTimeMillis();
516 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to release lock:" + (end - start) + " ms");
520 public static void voluntaryReleaseLock(String lockId) throws MusicLockingException{
522 getLockingServiceHandle().unlockAndDeleteId(lockId);
523 } catch (KeeperException.NoNodeException e) {
531 * @throws MusicLockingException
533 public static void deleteLock(String lockName) throws MusicLockingException {
534 long start = System.currentTimeMillis();
535 logger.info(EELFLoggerDelegate.applicationLogger,"Deleting lock for " + lockName);
537 getLockingServiceHandle().deleteLock("/" + lockName);
538 } catch (MusicLockingException e) {
539 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DELTELOCK+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
540 throw new MusicLockingException(e.getMessage());
542 long end = System.currentTimeMillis();
543 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to delete lock:" + (end - start) + " ms");
553 * @throws MusicServiceException
555 public static TableMetadata returnColumnMetadata(String keyspace, String tablename) throws MusicServiceException {
556 return getDSHandle().returnColumnMetadata(keyspace, tablename);
564 public static void pureZkCreate(String nodeName) {
566 getLockingServiceHandle().getzkLockHandle().createNode(nodeName);
567 } catch (MusicLockingException e) {
568 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
577 public static void pureZkWrite(String nodeName, byte[] data) {
578 long start = System.currentTimeMillis();
579 logger.info(EELFLoggerDelegate.applicationLogger,"Performing zookeeper write to " + nodeName);
581 getLockingServiceHandle().getzkLockHandle().setNodeData(nodeName, data);
582 } catch (MusicLockingException e) {
583 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
585 logger.info(EELFLoggerDelegate.applicationLogger,"Performed zookeeper write to " + nodeName);
586 long end = System.currentTimeMillis();
587 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms");
595 public static byte[] pureZkRead(String nodeName) {
596 long start = System.currentTimeMillis();
599 data = getLockingServiceHandle().getzkLockHandle().getNodeData(nodeName);
600 } catch (MusicLockingException e) {
601 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
603 long end = System.currentTimeMillis();
604 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms");
610 // Prepared Query Additions.
614 * @param keyspaceName
619 * @throws MusicServiceException
621 public static ReturnType eventualPut(PreparedQueryObject queryObject) {
622 boolean result = false;
624 result = getDSHandle().executePut(queryObject, MusicUtil.EVENTUAL);
625 } catch (MusicServiceException | MusicQueryException ex) {
626 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
627 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() + " " + ex.getCause() + " " + ex);
628 return new ReturnType(ResultType.FAILURE, ex.getMessage());
631 return new ReturnType(ResultType.SUCCESS, "Success");
633 return new ReturnType(ResultType.FAILURE, "Failure");
639 * @param keyspaceName
646 public static ReturnType criticalPut(String keyspaceName, String tableName, String primaryKey,
647 PreparedQueryObject queryObject, String lockId, Condition conditionInfo) {
648 long start = System.currentTimeMillis();
651 MusicLockState mls = getLockingServiceHandle()
652 .getLockState(keyspaceName + "." + tableName + "." + primaryKey);
653 if (mls.getLockHolder().equals(lockId) == true) {
654 if (conditionInfo != null)
656 if (conditionInfo.testCondition() == false)
657 return new ReturnType(ResultType.FAILURE,
658 "Lock acquired but the condition is not true");
659 } catch (Exception e) {
660 return new ReturnType(ResultType.FAILURE,
661 "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
664 getDSHandle().executePut(queryObject, MusicUtil.CRITICAL);
665 long end = System.currentTimeMillis();
666 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the critical put:" + (end - start) + " ms");
667 return new ReturnType(ResultType.SUCCESS, "Update performed");
669 return new ReturnType(ResultType.FAILURE,
670 "Cannot perform operation since you are the not the lock holder");
671 } catch (MusicQueryException | MusicServiceException e) {
672 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
673 return new ReturnType(ResultType.FAILURE,
674 "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
676 }catch(MusicLockingException ex){
677 return new ReturnType(ResultType.FAILURE,ex.getMessage());
686 * @return Boolean Indicates success or failure
687 * @throws MusicServiceException
691 public static ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) throws MusicServiceException {
692 // this is mainly for some functions like keyspace creation etc which does not
693 // really need the bells and whistles of Music locking.
694 boolean result = false;
696 result = getDSHandle().executePut(queryObject, consistency);
697 } catch (MusicQueryException | MusicServiceException ex) {
698 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
699 throw new MusicServiceException(ex.getMessage());
701 return result?ResultType.SUCCESS:ResultType.FAILURE;
705 * This method performs DDL operation on cassandra.
707 * @param queryObject query object containing prepared query and values
709 * @throws MusicServiceException
711 public static ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException {
712 ResultSet results = null;
714 results = getDSHandle().executeEventualGet(queryObject);
715 } catch (MusicQueryException | MusicServiceException e) {
716 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
717 throw new MusicServiceException(e.getMessage());
723 * This method performs DDL operations on cassandra, if the the resource is available. Lock ID
724 * is used to check if the resource is free.
726 * @param keyspaceName name of the keyspace
727 * @param tableName name of the table
728 * @param primaryKey primary key value
729 * @param queryObject query object containing prepared query and values
730 * @param lockId lock ID to check if the resource is free to perform the operation.
733 public static ResultSet criticalGet(String keyspaceName, String tableName, String primaryKey,
734 PreparedQueryObject queryObject, String lockId) throws MusicServiceException {
735 ResultSet results = null;
737 MusicLockState mls = getLockingServiceHandle()
738 .getLockState(keyspaceName + "." + tableName + "." + primaryKey);
739 if (mls.getLockHolder().equals(lockId)) {
740 results = getDSHandle().executeCriticalGet(queryObject);
742 throw new MusicServiceException("YOU DO NOT HAVE THE LOCK");
743 } catch (MusicQueryException | MusicServiceException | MusicLockingException e) {
744 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
750 * This method performs DML operation on cassandra, when the lock of the dd is acquired.
752 * @param keyspaceName name of the keyspace
753 * @param tableName name of the table
754 * @param primaryKey primary key value
755 * @param queryObject query object containing prepared query and values
757 * @throws MusicLockingException
759 public static ReturnType atomicPut(String keyspaceName, String tableName, String primaryKey,
760 PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException {
762 long start = System.currentTimeMillis();
763 String key = keyspaceName + "." + tableName + "." + primaryKey;
764 String lockId = createLockReference(key);
765 long lockCreationTime = System.currentTimeMillis();
766 ReturnType lockAcqResult = acquireLock(key, lockId);
767 long lockAcqTime = System.currentTimeMillis();
768 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
769 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
770 ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
771 queryObject, lockId, conditionInfo);
772 long criticalPutTime = System.currentTimeMillis();
773 voluntaryReleaseLock(lockId);
774 long lockDeleteTime = System.currentTimeMillis();
775 String timingInfo = "|lock creation time:" + (lockCreationTime - start)
776 + "|lock accquire time:" + (lockAcqTime - lockCreationTime)
777 + "|critical put time:" + (criticalPutTime - lockAcqTime)
778 + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|";
779 criticalPutResult.setTimingInfo(timingInfo);
780 return criticalPutResult;
782 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
783 destroyLockRef(lockId);
784 return lockAcqResult;
789 * this function is mainly for the benchmarks to see the effect of lock deletion.
791 * @param keyspaceName
795 * @param conditionInfo
797 * @throws MusicLockingException
799 public static ReturnType atomicPutWithDeleteLock(String keyspaceName, String tableName,
800 String primaryKey, PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException {
802 long start = System.currentTimeMillis();
803 String key = keyspaceName + "." + tableName + "." + primaryKey;
804 String lockId = createLockReference(key);
805 long lockCreationTime = System.currentTimeMillis();
806 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
807 ReturnType lockAcqResult = acquireLock(key, lockId);
808 long lockAcqTime = System.currentTimeMillis();
809 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
810 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
811 ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
812 queryObject, lockId, conditionInfo);
813 long criticalPutTime = System.currentTimeMillis();
815 long lockDeleteTime = System.currentTimeMillis();
816 String timingInfo = "|lock creation time:" + (lockCreationTime - start)
817 + "|lock accquire time:" + (lockAcqTime - lockCreationTime)
818 + "|critical put time:" + (criticalPutTime - lockAcqTime)
819 + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|";
820 criticalPutResult.setTimingInfo(timingInfo);
821 return criticalPutResult;
823 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
825 return lockAcqResult;
833 * This method performs DDL operation on cassasndra, when the lock for the resource is acquired.
835 * @param keyspaceName name of the keyspace
836 * @param tableName name of the table
837 * @param primaryKey primary key value
838 * @param queryObject query object containing prepared query and values
840 * @throws MusicServiceException
841 * @throws MusicLockingException
843 public static ResultSet atomicGet(String keyspaceName, String tableName, String primaryKey,
844 PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException {
845 String key = keyspaceName + "." + tableName + "." + primaryKey;
846 String lockId = createLockReference(key);
847 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
848 ReturnType lockAcqResult = acquireLock(key, lockId);
849 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
850 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
852 criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
853 voluntaryReleaseLock(lockId);
856 destroyLockRef(lockId);
857 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
862 public static ResultSet atomicGetWithDeleteLock(String keyspaceName, String tableName, String primaryKey,
863 PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException {
864 String key = keyspaceName + "." + tableName + "." + primaryKey;
865 String lockId = createLockReference(key);
866 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
868 ReturnType lockAcqResult = acquireLock(key, lockId);
870 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
871 logger.info(EELFLoggerDelegate.applicationLogger, "acquired lock with id " + lockId);
872 ResultSet result = criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
877 logger.info(EELFLoggerDelegate.applicationLogger, "unable to acquire lock, id " + lockId);
885 * authenticate user logic
896 public static Map<String, Object> autheticateUser(String nameSpace, String userId,
897 String password, String keyspace, String aid, String operation)
899 Map<String, Object> resultMap = new HashMap<>();
901 resultMap = CachingUtil.validateRequest(nameSpace, userId, password, keyspace, aid,
903 if (!resultMap.isEmpty())
905 String isAAFApp = null;
907 isAAFApp= CachingUtil.isAAFApplication(nameSpace);
908 } catch(MusicServiceException e) {
909 resultMap.put("Exception", e.getMessage());
912 if(isAAFApp == null) {
913 resultMap.put("Exception", "Namespace: "+nameSpace+" doesn't exist. Please make sure ns(appName)"
914 + " is correct and Application is onboarded.");
917 boolean isAAF = Boolean.valueOf(isAAFApp);
918 if (userId == null || password == null) {
919 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
920 logger.error(EELFLoggerDelegate.errorLogger,"One or more required headers is missing. userId: " + userId
921 + " :: password: " + password);
922 resultMap.put("Exception",
923 "UserId and Password are mandatory for the operation " + operation);
926 if(!isAAF && !(operation.equals("createKeySpace"))) {
927 resultMap = CachingUtil.authenticateAIDUser(nameSpace, userId, password, keyspace);
928 if (!resultMap.isEmpty())
932 if (isAAF && nameSpace != null && userId != null && password != null) {
933 boolean isValid = true;
935 isValid = CachingUtil.authenticateAAFUser(nameSpace, userId, password, keyspace);
936 } catch (Exception e) {
937 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
938 logger.error(EELFLoggerDelegate.errorLogger,"Got exception while AAF authentication for namespace " + nameSpace);
939 resultMap.put("Exception", e.getMessage());
942 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
943 resultMap.put("Exception", "User not authenticated...");
945 if (!resultMap.isEmpty())
950 if (operation.equals("createKeySpace")) {
951 logger.info(EELFLoggerDelegate.applicationLogger,"AID is not provided. Creating new UUID for keyspace.");
952 PreparedQueryObject pQuery = new PreparedQueryObject();
953 pQuery.appendQueryString(
954 "select uuid from admin.keyspace_master where application_name=? and username=? and keyspace_name=? allow filtering");
955 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), nameSpace));
956 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
957 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),
958 MusicUtil.DEFAULTKEYSPACENAME));
961 Row rs = MusicCore.get(pQuery).one();
962 uuid = rs.getUUID("uuid").toString();
963 resultMap.put("uuid", "existing");
964 } catch (Exception e) {
965 logger.info(EELFLoggerDelegate.applicationLogger,"No UUID found in DB. So creating new UUID.");
966 uuid = CachingUtil.generateUUID();
967 resultMap.put("uuid", "new");
969 resultMap.put("aid", uuid);
979 public static Map<String, Object> validateLock(String lockName) {
980 Map<String, Object> resultMap = new HashMap<>();
981 String[] locks = lockName.split("\\.");
982 if(locks.length < 3) {
983 resultMap.put("Exception", "Invalid lock. Please make sure lock is of the type keyspaceName.tableName.primaryKey");
986 String keyspace= locks[0];
987 if(keyspace.startsWith("$"))
988 keyspace = keyspace.substring(1);
989 resultMap.put("keyspace",keyspace);