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 if (currentMls.getLockStatus() != MusicLockState.LockStatus.UNLOCKED || currentMls.getLockHolder() != null) {
298 logger.info("In acquire lock: the previous lock has not been released yet! current mls:"+currentMls.toString());
299 return new ReturnType(ResultType.FAILURE, "The previous lock has not been released yet.");
301 } catch (NullPointerException e) {
302 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
305 // change status to "being locked". This state transition is necessary to ensure syncing
306 // before granting the lock
307 String lockHolder = null;
308 boolean needToSyncQuorum = false;
309 if (currentMls != null)
310 needToSyncQuorum = currentMls.isNeedToSyncQuorum();
313 newMls = new MusicLockState(MusicLockState.LockStatus.BEING_LOCKED, lockHolder,
316 getLockingServiceHandle().setLockState(key, newMls);
317 } catch (MusicLockingException e1) {
318 logger.error(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
320 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to being_locked");
322 // do syncing if this was a forced lock release
323 if (needToSyncQuorum) {
324 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Since there was a forcible release, need to sync quorum!");
327 } catch (Exception e) {
328 logger.error(EELFLoggerDelegate.errorLogger,"Failed to set Lock state " + e);
332 // change status to locked
334 needToSyncQuorum = false;
335 newMls = new MusicLockState(MusicLockState.LockStatus.LOCKED, lockHolder, needToSyncQuorum);
337 getLockingServiceHandle().setLockState(key, newMls);
338 } catch (MusicLockingException e) {
339 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
341 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to locked and assigned current lock ref "
342 + lockId + " as holder");
344 return new ReturnType(result?ResultType.SUCCESS:ResultType.FAILURE, "Set lock state to locked and assigned a lock holder");
351 * @param keyspaceName
356 public boolean createKeyspace(String keyspaceName, JsonKeySpace kspObject) throws Exception {
361 private static void syncQuorum(String key) throws Exception {
362 logger.info(EELFLoggerDelegate.applicationLogger,"Performing sync operation---");
363 String[] splitString = key.split("\\.");
364 String keyspaceName = splitString[0];
365 String tableName = splitString[1];
366 String primaryKeyValue = splitString[2];
367 PreparedQueryObject selectQuery = new PreparedQueryObject();
368 PreparedQueryObject updateQuery = new PreparedQueryObject();
370 // get the primary key d
371 TableMetadata tableInfo = returnColumnMetadata(keyspaceName, tableName);
372 String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();// we only support single
374 DataType primaryKeyType = tableInfo.getPrimaryKey().get(0).getType();
375 Object cqlFormattedPrimaryKeyValue =
376 MusicUtil.convertToActualDataType(primaryKeyType, primaryKeyValue);
378 // get the row of data from a quorum
379 selectQuery.appendQueryString("SELECT * FROM " + keyspaceName + "." + tableName + " WHERE "
380 + primaryKeyName + "= ?" + ";");
381 selectQuery.addValue(cqlFormattedPrimaryKeyValue);
382 ResultSet results = null;
384 results = getDSHandle().executeCriticalGet(selectQuery);
385 // write it back to a quorum
386 Row row = results.one();
387 ColumnDefinitions colInfo = row.getColumnDefinitions();
388 int totalColumns = colInfo.size();
390 StringBuilder fieldValueString = new StringBuilder("");
391 for (Definition definition : colInfo) {
392 String colName = definition.getName();
393 if (colName.equals(primaryKeyName))
395 DataType colType = definition.getType();
396 Object valueObj = getDSHandle().getColValue(row, colName, colType);
397 Object valueString = MusicUtil.convertToActualDataType(colType, valueObj);
398 fieldValueString.append(colName + " = ?");
399 updateQuery.addValue(valueString);
400 if (counter != (totalColumns - 1))
401 fieldValueString.append(",");
402 counter = counter + 1;
404 updateQuery.appendQueryString("UPDATE " + keyspaceName + "." + tableName + " SET "
405 + fieldValueString + " WHERE " + primaryKeyName + "= ? " + ";");
406 updateQuery.addValue(cqlFormattedPrimaryKeyValue);
408 getDSHandle().executePut(updateQuery, "critical");
409 } catch (MusicServiceException | MusicQueryException e) {
410 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.QUERYERROR +""+updateQuery ,ErrorSeverity.MAJOR, ErrorTypes.QUERYERROR);
422 public static ResultSet quorumGet(PreparedQueryObject query) {
423 ResultSet results = null;
425 results = getDSHandle().executeCriticalGet(query);
426 } catch (MusicServiceException | MusicQueryException e) {
427 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.MAJOR, ErrorTypes.GENERALSERVICEERROR);
438 * @throws MusicServiceException
440 public static Map<String, HashMap<String, Object>> marshallResults(ResultSet results) throws MusicServiceException {
441 return getDSHandle().marshalData(results);
449 public static String whoseTurnIsIt(String lockName) {
452 return getLockingServiceHandle().whoseTurnIsIt("/" + lockName) + "";
453 } catch (MusicLockingException e) {
454 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKINGERROR+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
466 public static String getLockNameFromId(String lockId) {
467 StringTokenizer st = new StringTokenizer(lockId);
468 return st.nextToken("$");
471 public static void destroyLockRef(String lockId) {
472 long start = System.currentTimeMillis();
474 getLockingServiceHandle().unlockAndDeleteId(lockId);
475 } catch (MusicLockingException | NoNodeException e) {
476 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DESTROYLOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
478 long end = System.currentTimeMillis();
479 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to destroy lock reference:" + (end - start) + " ms");
482 public static MusicLockState releaseLock(String lockId, boolean voluntaryRelease) {
483 long start = System.currentTimeMillis();
485 getLockingServiceHandle().unlockAndDeleteId(lockId);
486 } catch (MusicLockingException e1) {
487 logger.error(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
488 } catch (KeeperException.NoNodeException nne) {
489 logger.error(EELFLoggerDelegate.errorLogger,"Failed to release Lock " + lockId + " " + nne);
490 MusicLockState mls = new MusicLockState("Lock doesn't exists. Release lock operation failed.");
493 String lockName = getLockNameFromId(lockId);
495 String lockHolder = null;
496 if (voluntaryRelease) {
497 mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder);
498 logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock voluntarily released for " + lockId);
500 boolean needToSyncQuorum = true;
501 mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder,
503 logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock forcibly released for " + lockId);
506 getLockingServiceHandle().setLockState(lockName, mls);
507 } catch (MusicLockingException e) {
508 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
510 long end = System.currentTimeMillis();
511 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to release lock:" + (end - start) + " ms");
515 public static void voluntaryReleaseLock(String lockId) throws MusicLockingException{
517 getLockingServiceHandle().unlockAndDeleteId(lockId);
518 String lockName = getLockNameFromId(lockId);
519 String lockHolder = null;
520 MusicLockState mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder);
522 getLockingServiceHandle().setLockState(lockName, mls);
523 } catch (MusicLockingException e) {
524 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
526 } catch (KeeperException.NoNodeException e) {
534 * @throws MusicLockingException
536 public static void deleteLock(String lockName) throws MusicLockingException {
537 long start = System.currentTimeMillis();
538 logger.info(EELFLoggerDelegate.applicationLogger,"Deleting lock for " + lockName);
540 getLockingServiceHandle().deleteLock("/" + lockName);
541 } catch (MusicLockingException e) {
542 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DELTELOCK+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
543 throw new MusicLockingException(e.getMessage());
545 long end = System.currentTimeMillis();
546 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to delete lock:" + (end - start) + " ms");
556 * @throws MusicServiceException
558 public static TableMetadata returnColumnMetadata(String keyspace, String tablename) throws MusicServiceException {
559 return getDSHandle().returnColumnMetadata(keyspace, tablename);
567 public static void pureZkCreate(String nodeName) {
569 getLockingServiceHandle().getzkLockHandle().createNode(nodeName);
570 } catch (MusicLockingException e) {
571 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
580 public static void pureZkWrite(String nodeName, byte[] data) {
581 long start = System.currentTimeMillis();
582 logger.info(EELFLoggerDelegate.applicationLogger,"Performing zookeeper write to " + nodeName);
584 getLockingServiceHandle().getzkLockHandle().setNodeData(nodeName, data);
585 } catch (MusicLockingException e) {
586 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
588 logger.info(EELFLoggerDelegate.applicationLogger,"Performed zookeeper write to " + nodeName);
589 long end = System.currentTimeMillis();
590 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms");
598 public static byte[] pureZkRead(String nodeName) {
599 long start = System.currentTimeMillis();
602 data = getLockingServiceHandle().getzkLockHandle().getNodeData(nodeName);
603 } catch (MusicLockingException e) {
604 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
606 long end = System.currentTimeMillis();
607 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms");
613 // Prepared Query Additions.
617 * @param keyspaceName
622 * @throws MusicServiceException
624 public static ReturnType eventualPut(PreparedQueryObject queryObject) {
625 boolean result = false;
627 result = getDSHandle().executePut(queryObject, MusicUtil.EVENTUAL);
628 } catch (MusicServiceException | MusicQueryException ex) {
629 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
630 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() + " " + ex.getCause() + " " + ex);
631 return new ReturnType(ResultType.FAILURE, ex.getMessage());
634 return new ReturnType(ResultType.SUCCESS, "Success");
636 return new ReturnType(ResultType.FAILURE, "Failure");
642 * @param keyspaceName
649 public static ReturnType criticalPut(String keyspaceName, String tableName, String primaryKey,
650 PreparedQueryObject queryObject, String lockId, Condition conditionInfo) {
651 long start = System.currentTimeMillis();
654 MusicLockState mls = getLockingServiceHandle()
655 .getLockState(keyspaceName + "." + tableName + "." + primaryKey);
656 logger.info("Got MusicLockState object... :"+mls.toString());
657 if (mls.getLockHolder().equals(lockId) == true) {
658 if (conditionInfo != null)
660 if (conditionInfo.testCondition() == false)
661 return new ReturnType(ResultType.FAILURE,
662 "Lock acquired but the condition is not true");
663 } catch (Exception e) {
664 return new ReturnType(ResultType.FAILURE,
665 "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
668 getDSHandle().executePut(queryObject, MusicUtil.CRITICAL);
669 long end = System.currentTimeMillis();
670 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the critical put:" + (end - start) + " ms");
671 return new ReturnType(ResultType.SUCCESS, "Update performed");
673 return new ReturnType(ResultType.FAILURE,
674 "Cannot perform operation since you are the not the lock holder");
675 } catch (MusicQueryException | MusicServiceException e) {
676 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
677 return new ReturnType(ResultType.FAILURE,
678 "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
680 }catch(MusicLockingException ex){
681 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage());
682 return new ReturnType(ResultType.FAILURE,ex.getMessage());
691 * @return Boolean Indicates success or failure
692 * @throws MusicServiceException
696 public static ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) throws MusicServiceException {
697 // this is mainly for some functions like keyspace creation etc which does not
698 // really need the bells and whistles of Music locking.
699 boolean result = false;
701 result = getDSHandle().executePut(queryObject, consistency);
702 } catch (MusicQueryException | MusicServiceException ex) {
703 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
704 throw new MusicServiceException(ex.getMessage());
706 return result?ResultType.SUCCESS:ResultType.FAILURE;
710 * This method performs DDL operation on cassandra.
712 * @param queryObject query object containing prepared query and values
714 * @throws MusicServiceException
716 public static ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException {
717 ResultSet results = null;
719 results = getDSHandle().executeEventualGet(queryObject);
720 } catch (MusicQueryException | MusicServiceException e) {
721 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
722 throw new MusicServiceException(e.getMessage());
728 * This method performs DDL operations on cassandra, if the the resource is available. Lock ID
729 * is used to check if the resource is free.
731 * @param keyspaceName name of the keyspace
732 * @param tableName name of the table
733 * @param primaryKey primary key value
734 * @param queryObject query object containing prepared query and values
735 * @param lockId lock ID to check if the resource is free to perform the operation.
738 public static ResultSet criticalGet(String keyspaceName, String tableName, String primaryKey,
739 PreparedQueryObject queryObject, String lockId) throws MusicServiceException {
740 ResultSet results = null;
742 MusicLockState mls = getLockingServiceHandle()
743 .getLockState(keyspaceName + "." + tableName + "." + primaryKey);
744 if (mls.getLockHolder().equals(lockId)) {
745 results = getDSHandle().executeCriticalGet(queryObject);
747 throw new MusicServiceException("YOU DO NOT HAVE THE LOCK");
748 } catch (MusicQueryException | MusicServiceException | MusicLockingException e) {
749 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
755 * This method performs DML operation on cassandra, when the lock of the dd is acquired.
757 * @param keyspaceName name of the keyspace
758 * @param tableName name of the table
759 * @param primaryKey primary key value
760 * @param queryObject query object containing prepared query and values
762 * @throws MusicLockingException
764 public static ReturnType atomicPut(String keyspaceName, String tableName, String primaryKey,
765 PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException {
767 long start = System.currentTimeMillis();
768 String key = keyspaceName + "." + tableName + "." + primaryKey;
769 String lockId = createLockReference(key);
770 long lockCreationTime = System.currentTimeMillis();
771 ReturnType lockAcqResult = acquireLock(key, lockId);
772 long lockAcqTime = System.currentTimeMillis();
773 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
774 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
775 ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
776 queryObject, lockId, conditionInfo);
777 long criticalPutTime = System.currentTimeMillis();
778 releaseLock(lockId, true);
779 long lockDeleteTime = System.currentTimeMillis();
780 String timingInfo = "|lock creation time:" + (lockCreationTime - start)
781 + "|lock accquire time:" + (lockAcqTime - lockCreationTime)
782 + "|critical put time:" + (criticalPutTime - lockAcqTime)
783 + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|";
784 criticalPutResult.setTimingInfo(timingInfo);
785 return criticalPutResult;
787 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
788 releaseLock(lockId, true);;
789 return lockAcqResult;
794 * this function is mainly for the benchmarks to see the effect of lock deletion.
796 * @param keyspaceName
800 * @param conditionInfo
802 * @throws MusicLockingException
804 public static ReturnType atomicPutWithDeleteLock(String keyspaceName, String tableName,
805 String primaryKey, PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException {
807 long start = System.currentTimeMillis();
808 String key = keyspaceName + "." + tableName + "." + primaryKey;
809 String lockId = createLockReference(key);
810 long lockCreationTime = System.currentTimeMillis();
811 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
812 ReturnType lockAcqResult = acquireLock(key, lockId);
813 long lockAcqTime = System.currentTimeMillis();
814 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
815 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
816 ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
817 queryObject, lockId, conditionInfo);
818 long criticalPutTime = System.currentTimeMillis();
820 long lockDeleteTime = System.currentTimeMillis();
821 String timingInfo = "|lock creation time:" + (lockCreationTime - start)
822 + "|lock accquire time:" + (lockAcqTime - lockCreationTime)
823 + "|critical put time:" + (criticalPutTime - lockAcqTime)
824 + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|";
825 criticalPutResult.setTimingInfo(timingInfo);
826 return criticalPutResult;
828 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
830 return lockAcqResult;
838 * This method performs DDL operation on cassasndra, when the lock for the resource is acquired.
840 * @param keyspaceName name of the keyspace
841 * @param tableName name of the table
842 * @param primaryKey primary key value
843 * @param queryObject query object containing prepared query and values
845 * @throws MusicServiceException
846 * @throws MusicLockingException
848 public static ResultSet atomicGet(String keyspaceName, String tableName, String primaryKey,
849 PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException {
850 String key = keyspaceName + "." + tableName + "." + primaryKey;
851 String lockId = createLockReference(key);
852 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
853 ReturnType lockAcqResult = acquireLock(key, lockId);
854 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
855 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
857 criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
858 releaseLock(lockId, true);
861 releaseLock(lockId, true);
862 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
867 public static ResultSet atomicGetWithDeleteLock(String keyspaceName, String tableName, String primaryKey,
868 PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException {
869 String key = keyspaceName + "." + tableName + "." + primaryKey;
870 String lockId = createLockReference(key);
871 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
873 ReturnType lockAcqResult = acquireLock(key, lockId);
875 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
876 logger.info(EELFLoggerDelegate.applicationLogger, "acquired lock with id " + lockId);
877 ResultSet result = criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
882 logger.info(EELFLoggerDelegate.applicationLogger, "unable to acquire lock, id " + lockId);
890 * authenticate user logic
901 public static Map<String, Object> autheticateUser(String nameSpace, String userId,
902 String password, String keyspace, String aid, String operation)
904 Map<String, Object> resultMap = new HashMap<>();
906 resultMap = CachingUtil.validateRequest(nameSpace, userId, password, keyspace, aid,
908 if (!resultMap.isEmpty())
910 String isAAFApp = null;
912 isAAFApp= CachingUtil.isAAFApplication(nameSpace);
913 } catch(MusicServiceException e) {
914 resultMap.put("Exception", e.getMessage());
917 if(isAAFApp == null) {
918 resultMap.put("Exception", "Namespace: "+nameSpace+" doesn't exist. Please make sure ns(appName)"
919 + " is correct and Application is onboarded.");
922 boolean isAAF = Boolean.valueOf(isAAFApp);
923 if (userId == null || password == null) {
924 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
925 logger.error(EELFLoggerDelegate.errorLogger,"One or more required headers is missing. userId: " + userId
926 + " :: password: " + password);
927 resultMap.put("Exception",
928 "UserId and Password are mandatory for the operation " + operation);
931 if(!isAAF && !(operation.equals("createKeySpace"))) {
932 resultMap = CachingUtil.authenticateAIDUser(nameSpace, userId, password, keyspace);
933 if (!resultMap.isEmpty())
937 if (isAAF && nameSpace != null && userId != null && password != null) {
938 boolean isValid = true;
940 isValid = CachingUtil.authenticateAAFUser(nameSpace, userId, password, keyspace);
941 } catch (Exception e) {
942 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
943 logger.error(EELFLoggerDelegate.errorLogger,"Got exception while AAF authentication for namespace " + nameSpace);
944 resultMap.put("Exception", e.getMessage());
947 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
948 resultMap.put("Exception", "User not authenticated...");
950 if (!resultMap.isEmpty())
955 if (operation.equals("createKeySpace")) {
956 logger.info(EELFLoggerDelegate.applicationLogger,"AID is not provided. Creating new UUID for keyspace.");
957 PreparedQueryObject pQuery = new PreparedQueryObject();
958 pQuery.appendQueryString(
959 "select uuid from admin.keyspace_master where application_name=? and username=? and keyspace_name=? allow filtering");
960 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), nameSpace));
961 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
962 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),
963 MusicUtil.DEFAULTKEYSPACENAME));
966 Row rs = MusicCore.get(pQuery).one();
967 uuid = rs.getUUID("uuid").toString();
968 resultMap.put("uuid", "existing");
969 } catch (Exception e) {
970 logger.info(EELFLoggerDelegate.applicationLogger,"No UUID found in DB. So creating new UUID.");
971 uuid = CachingUtil.generateUUID();
972 resultMap.put("uuid", "new");
974 resultMap.put("aid", uuid);
984 public static Map<String, Object> validateLock(String lockName) {
985 Map<String, Object> resultMap = new HashMap<>();
986 String[] locks = lockName.split("\\.");
987 if(locks.length < 3) {
988 resultMap.put("Exception", "Invalid lock. Please make sure lock is of the type keyspaceName.tableName.primaryKey");
991 String keyspace= locks[0];
992 if(keyspace.startsWith("$"))
993 keyspace = keyspace.substring(1);
994 resultMap.put("keyspace",keyspace);