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.PrintWriter;
26 import java.io.StringWriter;
27 import java.util.HashMap;
29 import java.util.StringTokenizer;
31 import org.apache.zookeeper.KeeperException;
32 import org.apache.zookeeper.KeeperException.NoNodeException;
33 import org.onap.music.datastore.MusicDataStore;
34 import org.onap.music.datastore.PreparedQueryObject;
35 import org.onap.music.datastore.jsonobjects.JsonKeySpace;
36 import org.onap.music.eelf.logging.EELFLoggerDelegate;
37 import org.onap.music.eelf.logging.format.AppMessages;
38 import org.onap.music.eelf.logging.format.ErrorSeverity;
39 import org.onap.music.eelf.logging.format.ErrorTypes;
40 import org.onap.music.exceptions.MusicLockingException;
41 import org.onap.music.exceptions.MusicQueryException;
42 import org.onap.music.exceptions.MusicServiceException;
43 import org.onap.music.lockingservice.MusicLockState;
44 import org.onap.music.lockingservice.MusicLockState.LockStatus;
45 import org.onap.music.lockingservice.MusicLockingService;
47 import com.datastax.driver.core.ColumnDefinitions;
48 import com.datastax.driver.core.ColumnDefinitions.Definition;
49 import com.datastax.driver.core.DataType;
50 import com.datastax.driver.core.ResultSet;
51 import com.datastax.driver.core.Row;
52 import com.datastax.driver.core.TableMetadata;
59 public class MusicCore {
61 public static MusicLockingService mLockHandle = null;
62 public static MusicDataStore mDstoreHandle = null;
63 private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicCore.class);
65 public static class Condition {
66 Map<String, Object> conditions;
67 PreparedQueryObject selectQueryForTheRow;
69 public Condition(Map<String, Object> conditions, PreparedQueryObject selectQueryForTheRow) {
70 this.conditions = conditions;
71 this.selectQueryForTheRow = selectQueryForTheRow;
74 public boolean testCondition() throws Exception {
75 // first generate the row
76 ResultSet results = quorumGet(selectQueryForTheRow);
77 Row row = results.one();
78 return getDSHandle().doesRowSatisfyCondition(row, conditions);
83 public static MusicLockingService getLockingServiceHandle() throws MusicLockingException {
84 logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring lock store handle");
85 long start = System.currentTimeMillis();
87 if (mLockHandle == null) {
89 mLockHandle = new MusicLockingService();
90 } catch (Exception e) {
91 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKHANDLE,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
92 throw new MusicLockingException("Failed to aquire Locl store handle " + e);
95 long end = System.currentTimeMillis();
96 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire lock store handle:" + (end - start) + " ms");
105 public static MusicDataStore getDSHandle(String remoteIp) {
106 logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring data store handle");
107 long start = System.currentTimeMillis();
108 if (mDstoreHandle == null) {
109 mDstoreHandle = new MusicDataStore(remoteIp);
111 long end = System.currentTimeMillis();
112 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms");
113 return mDstoreHandle;
119 * @throws MusicServiceException
121 public static MusicDataStore getDSHandle() throws MusicServiceException {
122 logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring data store handle");
123 long start = System.currentTimeMillis();
124 if (mDstoreHandle == null) {
125 // Quick Fix - Best to put this into every call to getDSHandle?
126 if (! MusicUtil.getMyCassaHost().equals("localhost") ) {
127 mDstoreHandle = new MusicDataStore(MusicUtil.getMyCassaHost());
129 mDstoreHandle = new MusicDataStore();
132 if(mDstoreHandle.getSession() == null) {
133 String message = "Connection to Cassandra has not been enstablished."
134 + " Please check connection properites and reboot.";
135 logger.info(EELFLoggerDelegate.applicationLogger, message);
136 throw new MusicServiceException(message);
138 long end = System.currentTimeMillis();
139 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms");
140 return mDstoreHandle;
143 public static String createLockReference(String lockName) {
144 logger.info(EELFLoggerDelegate.applicationLogger,"Creating lock reference for lock name:" + lockName);
145 long start = System.currentTimeMillis();
146 String lockId = null;
148 lockId = getLockingServiceHandle().createLockId("/" + lockName);
149 } catch (MusicLockingException e) {
150 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.CREATELOCK+lockName,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
153 long end = System.currentTimeMillis();
154 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to create lock reference:" + (end - start) + " ms");
163 public static boolean isTableOrKeySpaceLock(String key) {
164 String[] splitString = key.split("\\.");
165 if (splitString.length > 2)
176 public static MusicLockState getMusicLockState(String key) {
177 long start = System.currentTimeMillis();
179 String[] splitString = key.split("\\.");
180 String keyspaceName = splitString[0];
181 String tableName = splitString[1];
182 String primaryKey = splitString[2];
184 String lockName = keyspaceName + "." + tableName + "." + primaryKey;
185 mls = getLockingServiceHandle().getLockState(lockName);
186 long end = System.currentTimeMillis();
187 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to get lock state:" + (end - start) + " ms");
189 } catch (NullPointerException | MusicLockingException e) {
190 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
195 public static ReturnType acquireLockWithLease(String key, String lockId, long leasePeriod) {
197 long start = System.currentTimeMillis();
198 /* check if the current lock has exceeded its lease and if yes, release that lock */
199 MusicLockState mls = getMusicLockState(key);
201 if (mls.getLockStatus().equals(LockStatus.LOCKED)) {
202 logger.info(EELFLoggerDelegate.applicationLogger,"The current lock holder for " + key + " is " + mls.getLockHolder()
203 + ". Checking if it has exceeded lease");
204 long currentLockPeriod = System.currentTimeMillis() - mls.getLeaseStartTime();
205 long currentLeasePeriod = mls.getLeasePeriod();
206 if (currentLockPeriod > currentLeasePeriod) {
207 logger.info(EELFLoggerDelegate.applicationLogger,"Lock period " + currentLockPeriod
208 + " has exceeded lease period " + currentLeasePeriod);
209 boolean voluntaryRelease = false;
210 String currentLockHolder = mls.getLockHolder();
211 mls = releaseLock(currentLockHolder, voluntaryRelease);
215 logger.error(EELFLoggerDelegate.errorLogger,key, AppMessages.INVALIDLOCK,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
218 * call the traditional acquire lock now and if the result returned is true, set the
219 * begin time-stamp and lease period
221 if (acquireLock(key, lockId).getResult() == ResultType.SUCCESS) {
222 mls = getMusicLockState(key);// get latest state
224 logger.info(EELFLoggerDelegate.applicationLogger,"Music Lock State is null");
225 return new ReturnType(ResultType.FAILURE, "Could not acquire lock, Lock State is null");
227 if (mls.getLeaseStartTime() == -1) {// set it again only if it is not set already
228 mls.setLeaseStartTime(System.currentTimeMillis());
229 mls.setLeasePeriod(leasePeriod);
230 getLockingServiceHandle().setLockState(key, mls);
232 long end = System.currentTimeMillis();
233 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire leased lock:" + (end - start) + " ms");
234 return new ReturnType(ResultType.SUCCESS, "Accquired lock");
236 long end = System.currentTimeMillis();
237 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to fail to acquire leased lock:" + (end - start) + " ms");
238 return new ReturnType(ResultType.FAILURE, "Could not acquire lock");
240 } catch (Exception e) {
241 StringWriter sw = new StringWriter();
242 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR506E] Failed to aquire lock ",ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
244 String exceptionAsString = sw.toString();
245 return new ReturnType(ResultType.FAILURE,
246 "Exception thrown in acquireLockWithLease:\n" + exceptionAsString);
250 public static ReturnType acquireLock(String key, String lockId) throws MusicLockingException {
252 * first check if I am on top. Since ids are not reusable there is no need to check
253 * lockStatus If the status is unlocked, then the above call will automatically return
256 Boolean result = false;
258 result = getLockingServiceHandle().isMyTurn(lockId);
259 } catch (MusicLockingException e2) {
260 logger.error(EELFLoggerDelegate.errorLogger,AppMessages.INVALIDLOCK + lockId + " " + e2);
261 throw new MusicLockingException();
264 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Not your turn, someone else has the lock");
266 if (!getLockingServiceHandle().lockIdExists(lockId)) {
267 logger.info(EELFLoggerDelegate.applicationLogger, "In acquire lock: this lockId doesn't exist");
268 return new ReturnType(ResultType.FAILURE, "Lockid doesn't exist");
270 } catch (MusicLockingException e) {
271 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
272 throw new MusicLockingException();
274 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: returning failure");
275 return new ReturnType(ResultType.FAILURE, "Not your turn, someone else has the lock");
279 // this is for backward compatibility where locks could also be acquired on just
280 // keyspaces or tables.
281 if (isTableOrKeySpaceLock(key)) {
282 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: A table or keyspace lock so no need to perform sync...so returning true");
283 return new ReturnType(ResultType.SUCCESS, "A table or keyspace lock so no need to perform sync...so returning true");
286 // read the lock name corresponding to the key and if the status is locked or being locked,
288 MusicLockState currentMls = null;
289 MusicLockState newMls = null;
291 currentMls = getMusicLockState(key);
292 String currentLockHolder = currentMls.getLockHolder();
293 if (lockId.equals(currentLockHolder)) {
294 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: You already have the lock!");
295 return new ReturnType(ResultType.SUCCESS, "You already have the lock!");
297 } catch (NullPointerException e) {
298 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
301 // change status to "being locked". This state transition is necessary to ensure syncing
302 // before granting the lock
303 String lockHolder = null;
304 boolean needToSyncQuorum = false;
305 if (currentMls != null)
306 needToSyncQuorum = currentMls.isNeedToSyncQuorum();
309 newMls = new MusicLockState(MusicLockState.LockStatus.BEING_LOCKED, lockHolder,
312 getLockingServiceHandle().setLockState(key, newMls);
313 } catch (MusicLockingException e1) {
314 logger.error(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
316 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to being_locked");
318 // do syncing if this was a forced lock release
319 if (needToSyncQuorum) {
320 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Since there was a forcible release, need to sync quorum!");
323 } catch (Exception e) {
324 logger.error(EELFLoggerDelegate.errorLogger,"Failed to set Lock state " + e);
328 // change status to locked
330 needToSyncQuorum = false;
331 newMls = new MusicLockState(MusicLockState.LockStatus.LOCKED, lockHolder, needToSyncQuorum);
333 getLockingServiceHandle().setLockState(key, newMls);
334 } catch (MusicLockingException e) {
335 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
337 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to locked and assigned current lock ref "
338 + lockId + " as holder");
340 return new ReturnType(result?ResultType.SUCCESS:ResultType.FAILURE, "Set lock state to locked and assigned a lock holder");
347 * @param keyspaceName
352 public boolean createKeyspace(String keyspaceName, JsonKeySpace kspObject) throws Exception {
357 private static void syncQuorum(String key) throws Exception {
358 logger.info(EELFLoggerDelegate.applicationLogger,"Performing sync operation---");
359 String[] splitString = key.split("\\.");
360 String keyspaceName = splitString[0];
361 String tableName = splitString[1];
362 String primaryKeyValue = splitString[2];
363 PreparedQueryObject selectQuery = new PreparedQueryObject();
364 PreparedQueryObject updateQuery = new PreparedQueryObject();
366 // get the primary key d
367 TableMetadata tableInfo = returnColumnMetadata(keyspaceName, tableName);
368 String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();// we only support single
370 DataType primaryKeyType = tableInfo.getPrimaryKey().get(0).getType();
371 Object cqlFormattedPrimaryKeyValue =
372 MusicUtil.convertToActualDataType(primaryKeyType, primaryKeyValue);
374 // get the row of data from a quorum
375 selectQuery.appendQueryString("SELECT * FROM " + keyspaceName + "." + tableName + " WHERE "
376 + primaryKeyName + "= ?" + ";");
377 selectQuery.addValue(cqlFormattedPrimaryKeyValue);
378 ResultSet results = null;
380 results = getDSHandle().executeCriticalGet(selectQuery);
381 // write it back to a quorum
382 Row row = results.one();
383 ColumnDefinitions colInfo = row.getColumnDefinitions();
384 int totalColumns = colInfo.size();
386 StringBuilder fieldValueString = new StringBuilder("");
387 for (Definition definition : colInfo) {
388 String colName = definition.getName();
389 if (colName.equals(primaryKeyName))
391 DataType colType = definition.getType();
392 Object valueObj = getDSHandle().getColValue(row, colName, colType);
393 Object valueString = MusicUtil.convertToActualDataType(colType, valueObj);
394 fieldValueString.append(colName + " = ?");
395 updateQuery.addValue(valueString);
396 if (counter != (totalColumns - 1))
397 fieldValueString.append(",");
398 counter = counter + 1;
400 updateQuery.appendQueryString("UPDATE " + keyspaceName + "." + tableName + " SET "
401 + fieldValueString + " WHERE " + primaryKeyName + "= ? " + ";");
402 updateQuery.addValue(cqlFormattedPrimaryKeyValue);
404 getDSHandle().executePut(updateQuery, "critical");
405 } catch (MusicServiceException | MusicQueryException e) {
406 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.QUERYERROR +""+updateQuery ,ErrorSeverity.MAJOR, ErrorTypes.QUERYERROR);
418 public static ResultSet quorumGet(PreparedQueryObject query) {
419 ResultSet results = null;
421 results = getDSHandle().executeCriticalGet(query);
422 } catch (MusicServiceException | MusicQueryException e) {
423 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.MAJOR, ErrorTypes.GENERALSERVICEERROR);
434 * @throws MusicServiceException
436 public static Map<String, HashMap<String, Object>> marshallResults(ResultSet results) throws MusicServiceException {
437 return getDSHandle().marshalData(results);
445 public static String whoseTurnIsIt(String lockName) {
448 return getLockingServiceHandle().whoseTurnIsIt("/" + lockName) + "";
449 } catch (MusicLockingException e) {
450 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKINGERROR+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
462 public static String getLockNameFromId(String lockId) {
463 StringTokenizer st = new StringTokenizer(lockId);
464 return st.nextToken("$");
467 public static void destroyLockRef(String lockId) {
468 long start = System.currentTimeMillis();
470 getLockingServiceHandle().unlockAndDeleteId(lockId);
471 } catch (MusicLockingException | NoNodeException e) {
472 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DESTROYLOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
474 long end = System.currentTimeMillis();
475 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to destroy lock reference:" + (end - start) + " ms");
478 public static MusicLockState releaseLock(String lockId, boolean voluntaryRelease) {
479 long start = System.currentTimeMillis();
481 getLockingServiceHandle().unlockAndDeleteId(lockId);
482 } catch (MusicLockingException e1) {
483 logger.error(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
484 } catch (KeeperException.NoNodeException nne) {
485 logger.error(EELFLoggerDelegate.errorLogger,"Failed to release Lock " + lockId + " " + nne);
486 MusicLockState mls = new MusicLockState("Lock doesn't exists. Release lock operation failed.");
489 String lockName = getLockNameFromId(lockId);
491 String lockHolder = null;
492 if (voluntaryRelease) {
493 mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder);
494 logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock voluntarily released for " + lockId);
496 boolean needToSyncQuorum = true;
497 mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder,
499 logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock forcibly released for " + lockId);
502 getLockingServiceHandle().setLockState(lockName, mls);
503 } catch (MusicLockingException e) {
504 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
506 long end = System.currentTimeMillis();
507 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to release lock:" + (end - start) + " ms");
511 public static void voluntaryReleaseLock(String lockId) throws MusicLockingException{
513 getLockingServiceHandle().unlockAndDeleteId(lockId);
514 } catch (KeeperException.NoNodeException e) {
522 * @throws MusicLockingException
524 public static void deleteLock(String lockName) throws MusicLockingException {
525 long start = System.currentTimeMillis();
526 logger.info(EELFLoggerDelegate.applicationLogger,"Deleting lock for " + lockName);
528 getLockingServiceHandle().deleteLock("/" + lockName);
529 } catch (MusicLockingException e) {
530 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DELTELOCK+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
531 throw new MusicLockingException(e.getMessage());
533 long end = System.currentTimeMillis();
534 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to delete lock:" + (end - start) + " ms");
544 * @throws MusicServiceException
546 public static TableMetadata returnColumnMetadata(String keyspace, String tablename) throws MusicServiceException {
547 return getDSHandle().returnColumnMetadata(keyspace, tablename);
555 public static void pureZkCreate(String nodeName) {
557 getLockingServiceHandle().getzkLockHandle().createNode(nodeName);
558 } catch (MusicLockingException e) {
559 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
568 public static void pureZkWrite(String nodeName, byte[] data) {
569 long start = System.currentTimeMillis();
570 logger.info(EELFLoggerDelegate.applicationLogger,"Performing zookeeper write to " + nodeName);
572 getLockingServiceHandle().getzkLockHandle().setNodeData(nodeName, data);
573 } catch (MusicLockingException e) {
574 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
576 logger.info(EELFLoggerDelegate.applicationLogger,"Performed zookeeper write to " + nodeName);
577 long end = System.currentTimeMillis();
578 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms");
586 public static byte[] pureZkRead(String nodeName) {
587 long start = System.currentTimeMillis();
590 data = getLockingServiceHandle().getzkLockHandle().getNodeData(nodeName);
591 } catch (MusicLockingException e) {
592 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
594 long end = System.currentTimeMillis();
595 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms");
601 // Prepared Query Additions.
605 * @param keyspaceName
610 * @throws MusicServiceException
612 public static ReturnType eventualPut(PreparedQueryObject queryObject) {
613 boolean result = false;
615 result = getDSHandle().executePut(queryObject, MusicUtil.EVENTUAL);
616 } catch (MusicServiceException | MusicQueryException ex) {
617 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
618 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() + " " + ex.getCause() + " " + ex);
619 return new ReturnType(ResultType.FAILURE, ex.getMessage());
622 return new ReturnType(ResultType.SUCCESS, "Success");
624 return new ReturnType(ResultType.FAILURE, "Failure");
630 * @param keyspaceName
637 public static ReturnType criticalPut(String keyspaceName, String tableName, String primaryKey,
638 PreparedQueryObject queryObject, String lockId, Condition conditionInfo) {
639 long start = System.currentTimeMillis();
642 MusicLockState mls = getLockingServiceHandle()
643 .getLockState(keyspaceName + "." + tableName + "." + primaryKey);
644 if (mls.getLockHolder().equals(lockId) == true) {
645 if (conditionInfo != null)
647 if (conditionInfo.testCondition() == false)
648 return new ReturnType(ResultType.FAILURE,
649 "Lock acquired but the condition is not true");
650 } catch (Exception e) {
651 return new ReturnType(ResultType.FAILURE,
652 "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
655 getDSHandle().executePut(queryObject, MusicUtil.CRITICAL);
656 long end = System.currentTimeMillis();
657 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the critical put:" + (end - start) + " ms");
658 return new ReturnType(ResultType.SUCCESS, "Update performed");
660 return new ReturnType(ResultType.FAILURE,
661 "Cannot perform operation since you are the not the lock holder");
662 } catch (MusicQueryException | MusicServiceException e) {
663 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
664 return new ReturnType(ResultType.FAILURE,
665 "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
667 }catch(MusicLockingException ex){
668 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage());
669 return new ReturnType(ResultType.FAILURE,ex.getMessage());
678 * @return Boolean Indicates success or failure
679 * @throws MusicServiceException
683 public static ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) throws MusicServiceException {
684 // this is mainly for some functions like keyspace creation etc which does not
685 // really need the bells and whistles of Music locking.
686 boolean result = false;
688 result = getDSHandle().executePut(queryObject, consistency);
689 } catch (MusicQueryException | MusicServiceException ex) {
690 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
691 throw new MusicServiceException(ex.getMessage());
693 return result?ResultType.SUCCESS:ResultType.FAILURE;
697 * This method performs DDL operation on cassandra.
699 * @param queryObject query object containing prepared query and values
701 * @throws MusicServiceException
703 public static ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException {
704 ResultSet results = null;
706 results = getDSHandle().executeEventualGet(queryObject);
707 } catch (MusicQueryException | MusicServiceException e) {
708 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
709 throw new MusicServiceException(e.getMessage());
715 * This method performs DDL operations on cassandra, if the the resource is available. Lock ID
716 * is used to check if the resource is free.
718 * @param keyspaceName name of the keyspace
719 * @param tableName name of the table
720 * @param primaryKey primary key value
721 * @param queryObject query object containing prepared query and values
722 * @param lockId lock ID to check if the resource is free to perform the operation.
725 public static ResultSet criticalGet(String keyspaceName, String tableName, String primaryKey,
726 PreparedQueryObject queryObject, String lockId) throws MusicServiceException {
727 ResultSet results = null;
729 MusicLockState mls = getLockingServiceHandle()
730 .getLockState(keyspaceName + "." + tableName + "." + primaryKey);
731 if (mls.getLockHolder().equals(lockId)) {
732 results = getDSHandle().executeCriticalGet(queryObject);
734 throw new MusicServiceException("YOU DO NOT HAVE THE LOCK");
735 } catch (MusicQueryException | MusicServiceException | MusicLockingException e) {
736 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
742 * This method performs DML operation on cassandra, when the lock of the dd is acquired.
744 * @param keyspaceName name of the keyspace
745 * @param tableName name of the table
746 * @param primaryKey primary key value
747 * @param queryObject query object containing prepared query and values
749 * @throws MusicLockingException
751 public static ReturnType atomicPut(String keyspaceName, String tableName, String primaryKey,
752 PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException {
754 long start = System.currentTimeMillis();
755 String key = keyspaceName + "." + tableName + "." + primaryKey;
756 String lockId = createLockReference(key);
757 long lockCreationTime = System.currentTimeMillis();
758 ReturnType lockAcqResult = acquireLock(key, lockId);
759 long lockAcqTime = System.currentTimeMillis();
760 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
761 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
762 ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
763 queryObject, lockId, conditionInfo);
764 long criticalPutTime = System.currentTimeMillis();
765 voluntaryReleaseLock(lockId);
766 long lockDeleteTime = System.currentTimeMillis();
767 String timingInfo = "|lock creation time:" + (lockCreationTime - start)
768 + "|lock accquire time:" + (lockAcqTime - lockCreationTime)
769 + "|critical put time:" + (criticalPutTime - lockAcqTime)
770 + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|";
771 criticalPutResult.setTimingInfo(timingInfo);
772 return criticalPutResult;
774 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
775 destroyLockRef(lockId);
776 return lockAcqResult;
781 * this function is mainly for the benchmarks to see the effect of lock deletion.
783 * @param keyspaceName
787 * @param conditionInfo
789 * @throws MusicLockingException
791 public static ReturnType atomicPutWithDeleteLock(String keyspaceName, String tableName,
792 String primaryKey, PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException {
794 long start = System.currentTimeMillis();
795 String key = keyspaceName + "." + tableName + "." + primaryKey;
796 String lockId = createLockReference(key);
797 long lockCreationTime = System.currentTimeMillis();
798 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
799 ReturnType lockAcqResult = acquireLock(key, lockId);
800 long lockAcqTime = System.currentTimeMillis();
801 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
802 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
803 ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
804 queryObject, lockId, conditionInfo);
805 long criticalPutTime = System.currentTimeMillis();
807 long lockDeleteTime = System.currentTimeMillis();
808 String timingInfo = "|lock creation time:" + (lockCreationTime - start)
809 + "|lock accquire time:" + (lockAcqTime - lockCreationTime)
810 + "|critical put time:" + (criticalPutTime - lockAcqTime)
811 + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|";
812 criticalPutResult.setTimingInfo(timingInfo);
813 return criticalPutResult;
815 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
817 return lockAcqResult;
825 * This method performs DDL operation on cassasndra, when the lock for the resource is acquired.
827 * @param keyspaceName name of the keyspace
828 * @param tableName name of the table
829 * @param primaryKey primary key value
830 * @param queryObject query object containing prepared query and values
832 * @throws MusicServiceException
833 * @throws MusicLockingException
835 public static ResultSet atomicGet(String keyspaceName, String tableName, String primaryKey,
836 PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException {
837 String key = keyspaceName + "." + tableName + "." + primaryKey;
838 String lockId = createLockReference(key);
839 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
840 ReturnType lockAcqResult = acquireLock(key, lockId);
841 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
842 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
844 criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
845 voluntaryReleaseLock(lockId);
848 destroyLockRef(lockId);
849 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
854 public static ResultSet atomicGetWithDeleteLock(String keyspaceName, String tableName, String primaryKey,
855 PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException {
856 String key = keyspaceName + "." + tableName + "." + primaryKey;
857 String lockId = createLockReference(key);
858 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
860 ReturnType lockAcqResult = acquireLock(key, lockId);
862 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
863 logger.info(EELFLoggerDelegate.applicationLogger, "acquired lock with id " + lockId);
864 ResultSet result = criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
869 logger.info(EELFLoggerDelegate.applicationLogger, "unable to acquire lock, id " + lockId);
877 * authenticate user logic
888 public static Map<String, Object> autheticateUser(String nameSpace, String userId,
889 String password, String keyspace, String aid, String operation)
891 Map<String, Object> resultMap = new HashMap<>();
893 resultMap = CachingUtil.validateRequest(nameSpace, userId, password, keyspace, aid,
895 if (!resultMap.isEmpty())
897 String isAAFApp = null;
899 isAAFApp= CachingUtil.isAAFApplication(nameSpace);
900 } catch(MusicServiceException e) {
901 resultMap.put("Exception", e.getMessage());
904 if(isAAFApp == null) {
905 resultMap.put("Exception", "Namespace: "+nameSpace+" doesn't exist. Please make sure ns(appName)"
906 + " is correct and Application is onboarded.");
909 boolean isAAF = Boolean.valueOf(isAAFApp);
910 if (userId == null || password == null) {
911 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
912 logger.error(EELFLoggerDelegate.errorLogger,"One or more required headers is missing. userId: " + userId
913 + " :: password: " + password);
914 resultMap.put("Exception",
915 "UserId and Password are mandatory for the operation " + operation);
918 if(!isAAF && !(operation.equals("createKeySpace"))) {
919 resultMap = CachingUtil.authenticateAIDUser(nameSpace, userId, password, keyspace);
920 if (!resultMap.isEmpty())
924 if (isAAF && nameSpace != null && userId != null && password != null) {
925 boolean isValid = true;
927 isValid = CachingUtil.authenticateAAFUser(nameSpace, userId, password, keyspace);
928 } catch (Exception e) {
929 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
930 logger.error(EELFLoggerDelegate.errorLogger,"Got exception while AAF authentication for namespace " + nameSpace);
931 resultMap.put("Exception", e.getMessage());
934 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
935 resultMap.put("Exception", "User not authenticated...");
937 if (!resultMap.isEmpty())
942 if (operation.equals("createKeySpace")) {
943 logger.info(EELFLoggerDelegate.applicationLogger,"AID is not provided. Creating new UUID for keyspace.");
944 PreparedQueryObject pQuery = new PreparedQueryObject();
945 pQuery.appendQueryString(
946 "select uuid from admin.keyspace_master where application_name=? and username=? and keyspace_name=? allow filtering");
947 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), nameSpace));
948 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
949 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),
950 MusicUtil.DEFAULTKEYSPACENAME));
953 Row rs = MusicCore.get(pQuery).one();
954 uuid = rs.getUUID("uuid").toString();
955 resultMap.put("uuid", "existing");
956 } catch (Exception e) {
957 logger.info(EELFLoggerDelegate.applicationLogger,"No UUID found in DB. So creating new UUID.");
958 uuid = CachingUtil.generateUUID();
959 resultMap.put("uuid", "new");
961 resultMap.put("aid", uuid);
971 public static Map<String, Object> validateLock(String lockName) {
972 Map<String, Object> resultMap = new HashMap<>();
973 String[] locks = lockName.split("\\.");
974 if(locks.length < 3) {
975 resultMap.put("Exception", "Invalid lock. Please make sure lock is of the type keyspaceName.tableName.primaryKey");
978 String keyspace= locks[0];
979 if(keyspace.startsWith("$"))
980 keyspace = keyspace.substring(1);
981 resultMap.put("keyspace",keyspace);