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 * ====================================================================
23 package org.onap.music.main;
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) {
110 MusicUtil.loadProperties();
111 } catch (Exception e) {
112 logger.error(EELFLoggerDelegate.errorLogger, "No properties file defined. Falling back to default.");
114 mDstoreHandle = new MusicDataStore(remoteIp);
116 long end = System.currentTimeMillis();
117 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms");
118 return mDstoreHandle;
124 * @throws MusicServiceException
126 public static MusicDataStore getDSHandle() throws MusicServiceException {
127 logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring data store handle");
128 long start = System.currentTimeMillis();
129 if (mDstoreHandle == null) {
131 MusicUtil.loadProperties();
132 } catch (Exception e) {
133 logger.error(EELFLoggerDelegate.errorLogger, "No properties file defined. Falling back to default.");
135 // Quick Fix - Best to put this into every call to getDSHandle?
136 if (! MusicUtil.getMyCassaHost().equals("localhost") ) {
137 mDstoreHandle = new MusicDataStore(MusicUtil.getMyCassaHost());
139 mDstoreHandle = new MusicDataStore();
142 if(mDstoreHandle.getSession() == null) {
143 String message = "Connection to Cassandra has not been enstablished."
144 + " Please check connection properites and reboot.";
145 logger.info(EELFLoggerDelegate.applicationLogger, message);
146 throw new MusicServiceException(message);
148 long end = System.currentTimeMillis();
149 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms");
150 return mDstoreHandle;
153 public static String createLockReference(String lockName) {
154 logger.info(EELFLoggerDelegate.applicationLogger,"Creating lock reference for lock name:" + lockName);
155 long start = System.currentTimeMillis();
156 String lockId = null;
158 lockId = getLockingServiceHandle().createLockId("/" + lockName);
159 } catch (MusicLockingException e) {
160 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.CREATELOCK+lockName,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
163 long end = System.currentTimeMillis();
164 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to create lock reference:" + (end - start) + " ms");
173 public static boolean isTableOrKeySpaceLock(String key) {
174 String[] splitString = key.split("\\.");
175 if (splitString.length > 2)
186 public static MusicLockState getMusicLockState(String key) {
187 long start = System.currentTimeMillis();
189 String[] splitString = key.split("\\.");
190 String keyspaceName = splitString[0];
191 String tableName = splitString[1];
192 String primaryKey = splitString[2];
194 String lockName = keyspaceName + "." + tableName + "." + primaryKey;
195 mls = getLockingServiceHandle().getLockState(lockName);
196 long end = System.currentTimeMillis();
197 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to get lock state:" + (end - start) + " ms");
199 } catch (NullPointerException | MusicLockingException e) {
200 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
205 public static ReturnType acquireLockWithLease(String key, String lockId, long leasePeriod) {
207 long start = System.currentTimeMillis();
208 /* check if the current lock has exceeded its lease and if yes, release that lock */
209 MusicLockState mls = getMusicLockState(key);
211 if (mls.getLockStatus().equals(LockStatus.LOCKED)) {
212 logger.info(EELFLoggerDelegate.applicationLogger,"The current lock holder for " + key + " is " + mls.getLockHolder()
213 + ". Checking if it has exceeded lease");
214 long currentLockPeriod = System.currentTimeMillis() - mls.getLeaseStartTime();
215 long currentLeasePeriod = mls.getLeasePeriod();
216 if (currentLockPeriod > currentLeasePeriod) {
217 logger.info(EELFLoggerDelegate.applicationLogger,"Lock period " + currentLockPeriod
218 + " has exceeded lease period " + currentLeasePeriod);
219 boolean voluntaryRelease = false;
220 String currentLockHolder = mls.getLockHolder();
221 mls = releaseLock(currentLockHolder, voluntaryRelease);
225 logger.error(EELFLoggerDelegate.errorLogger,key, AppMessages.INVALIDLOCK,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
228 * call the traditional acquire lock now and if the result returned is true, set the
229 * begin time-stamp and lease period
231 if (acquireLock(key, lockId).getResult() == ResultType.SUCCESS) {
232 mls = getMusicLockState(key);// get latest state
234 logger.info(EELFLoggerDelegate.applicationLogger,"Music Lock State is null");
235 return new ReturnType(ResultType.FAILURE, "Could not acquire lock, Lock State is null");
237 if (mls.getLeaseStartTime() == -1) {// set it again only if it is not set already
238 mls.setLeaseStartTime(System.currentTimeMillis());
239 mls.setLeasePeriod(leasePeriod);
240 getLockingServiceHandle().setLockState(key, mls);
242 long end = System.currentTimeMillis();
243 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire leased lock:" + (end - start) + " ms");
244 return new ReturnType(ResultType.SUCCESS, "Accquired lock");
246 long end = System.currentTimeMillis();
247 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to fail to acquire leased lock:" + (end - start) + " ms");
248 return new ReturnType(ResultType.FAILURE, "Could not acquire lock");
250 } catch (Exception e) {
251 StringWriter sw = new StringWriter();
252 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR506E] Failed to aquire lock ",ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
254 String exceptionAsString = sw.toString();
255 return new ReturnType(ResultType.FAILURE,
256 "Exception thrown in acquireLockWithLease:\n" + exceptionAsString);
260 public static ReturnType acquireLock(String key, String lockId) throws MusicLockingException {
262 * first check if I am on top. Since ids are not reusable there is no need to check
263 * lockStatus If the status is unlocked, then the above call will automatically return
266 Boolean result = false;
268 result = getLockingServiceHandle().isMyTurn(lockId);
269 } catch (MusicLockingException e2) {
270 logger.error(EELFLoggerDelegate.errorLogger,AppMessages.INVALIDLOCK + lockId + " " + e2);
271 throw new MusicLockingException();
274 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Not your turn, someone else has the lock");
276 if (!getLockingServiceHandle().lockIdExists(lockId)) {
277 logger.info(EELFLoggerDelegate.applicationLogger, "In acquire lock: this lockId doesn't exist");
278 return new ReturnType(ResultType.FAILURE, "Lockid doesn't exist");
280 } catch (MusicLockingException e) {
281 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
282 throw new MusicLockingException();
284 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: returning failure");
285 return new ReturnType(ResultType.FAILURE, "Not your turn, someone else has the lock");
289 // this is for backward compatibility where locks could also be acquired on just
290 // keyspaces or tables.
291 if (isTableOrKeySpaceLock(key)) {
292 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: A table or keyspace lock so no need to perform sync...so returning true");
293 return new ReturnType(ResultType.SUCCESS, "A table or keyspace lock so no need to perform sync...so returning true");
296 // read the lock name corresponding to the key and if the status is locked or being locked,
298 MusicLockState currentMls = null;
299 MusicLockState newMls = null;
301 currentMls = getMusicLockState(key);
302 String currentLockHolder = currentMls.getLockHolder();
303 if (lockId.equals(currentLockHolder)) {
304 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: You already have the lock!");
305 return new ReturnType(ResultType.SUCCESS, "You already have the lock!");
307 } catch (NullPointerException e) {
308 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
311 // change status to "being locked". This state transition is necessary to ensure syncing
312 // before granting the lock
313 String lockHolder = null;
314 boolean needToSyncQuorum = false;
315 if (currentMls != null)
316 needToSyncQuorum = currentMls.isNeedToSyncQuorum();
319 newMls = new MusicLockState(MusicLockState.LockStatus.BEING_LOCKED, lockHolder,
322 getLockingServiceHandle().setLockState(key, newMls);
323 } catch (MusicLockingException e1) {
324 logger.error(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
326 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to being_locked");
328 // do syncing if this was a forced lock release
329 if (needToSyncQuorum) {
330 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Since there was a forcible release, need to sync quorum!");
333 } catch (Exception e) {
334 logger.error(EELFLoggerDelegate.errorLogger,"Failed to set Lock state " + e);
338 // change status to locked
340 needToSyncQuorum = false;
341 newMls = new MusicLockState(MusicLockState.LockStatus.LOCKED, lockHolder, needToSyncQuorum);
343 getLockingServiceHandle().setLockState(key, newMls);
344 } catch (MusicLockingException e) {
345 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
347 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to locked and assigned current lock ref "
348 + lockId + " as holder");
350 return new ReturnType(result?ResultType.SUCCESS:ResultType.FAILURE, "Set lock state to locked and assigned a lock holder");
357 * @param keyspaceName
362 public boolean createKeyspace(String keyspaceName, JsonKeySpace kspObject) throws Exception {
367 private static void syncQuorum(String key) throws Exception {
368 logger.info(EELFLoggerDelegate.applicationLogger,"Performing sync operation---");
369 String[] splitString = key.split("\\.");
370 String keyspaceName = splitString[0];
371 String tableName = splitString[1];
372 String primaryKeyValue = splitString[2];
373 PreparedQueryObject selectQuery = new PreparedQueryObject();
374 PreparedQueryObject updateQuery = new PreparedQueryObject();
376 // get the primary key d
377 TableMetadata tableInfo = returnColumnMetadata(keyspaceName, tableName);
378 String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();// we only support single
380 DataType primaryKeyType = tableInfo.getPrimaryKey().get(0).getType();
381 Object cqlFormattedPrimaryKeyValue =
382 MusicUtil.convertToActualDataType(primaryKeyType, primaryKeyValue);
384 // get the row of data from a quorum
385 selectQuery.appendQueryString("SELECT * FROM " + keyspaceName + "." + tableName + " WHERE "
386 + primaryKeyName + "= ?" + ";");
387 selectQuery.addValue(cqlFormattedPrimaryKeyValue);
388 ResultSet results = null;
390 results = getDSHandle().executeCriticalGet(selectQuery);
391 // write it back to a quorum
392 Row row = results.one();
393 ColumnDefinitions colInfo = row.getColumnDefinitions();
394 int totalColumns = colInfo.size();
396 StringBuilder fieldValueString = new StringBuilder("");
397 for (Definition definition : colInfo) {
398 String colName = definition.getName();
399 if (colName.equals(primaryKeyName))
401 DataType colType = definition.getType();
402 Object valueObj = getDSHandle().getColValue(row, colName, colType);
403 Object valueString = MusicUtil.convertToActualDataType(colType, valueObj);
404 fieldValueString.append(colName + " = ?");
405 updateQuery.addValue(valueString);
406 if (counter != (totalColumns - 1))
407 fieldValueString.append(",");
408 counter = counter + 1;
410 updateQuery.appendQueryString("UPDATE " + keyspaceName + "." + tableName + " SET "
411 + fieldValueString + " WHERE " + primaryKeyName + "= ? " + ";");
412 updateQuery.addValue(cqlFormattedPrimaryKeyValue);
414 getDSHandle().executePut(updateQuery, "critical");
415 } catch (MusicServiceException | MusicQueryException e) {
416 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.QUERYERROR +""+updateQuery ,ErrorSeverity.MAJOR, ErrorTypes.QUERYERROR);
428 public static ResultSet quorumGet(PreparedQueryObject query) {
429 ResultSet results = null;
431 results = getDSHandle().executeCriticalGet(query);
432 } catch (MusicServiceException | MusicQueryException e) {
433 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.MAJOR, ErrorTypes.GENERALSERVICEERROR);
444 * @throws MusicServiceException
446 public static Map<String, HashMap<String, Object>> marshallResults(ResultSet results) throws MusicServiceException {
447 return getDSHandle().marshalData(results);
455 public static String whoseTurnIsIt(String lockName) {
458 return getLockingServiceHandle().whoseTurnIsIt("/" + lockName) + "";
459 } catch (MusicLockingException e) {
460 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKINGERROR+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
472 public static String getLockNameFromId(String lockId) {
473 StringTokenizer st = new StringTokenizer(lockId);
474 return st.nextToken("$");
477 public static void destroyLockRef(String lockId) {
478 long start = System.currentTimeMillis();
480 getLockingServiceHandle().unlockAndDeleteId(lockId);
481 } catch (MusicLockingException | NoNodeException e) {
482 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DESTROYLOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
484 long end = System.currentTimeMillis();
485 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to destroy lock reference:" + (end - start) + " ms");
488 public static MusicLockState releaseLock(String lockId, boolean voluntaryRelease) {
489 long start = System.currentTimeMillis();
491 getLockingServiceHandle().unlockAndDeleteId(lockId);
492 } catch (MusicLockingException e1) {
493 logger.error(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
494 } catch (KeeperException.NoNodeException nne) {
495 logger.error(EELFLoggerDelegate.errorLogger,"Failed to release Lock " + lockId + " " + nne);
496 MusicLockState mls = new MusicLockState("Lock doesn't exists. Release lock operation failed.");
499 String lockName = getLockNameFromId(lockId);
501 String lockHolder = null;
502 if (voluntaryRelease) {
503 mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder);
504 logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock voluntarily released for " + lockId);
506 boolean needToSyncQuorum = true;
507 mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder,
509 logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock forcibly released for " + lockId);
512 getLockingServiceHandle().setLockState(lockName, mls);
513 } catch (MusicLockingException e) {
514 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
516 long end = System.currentTimeMillis();
517 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to release lock:" + (end - start) + " ms");
521 public static void voluntaryReleaseLock(String lockId) throws MusicLockingException{
523 getLockingServiceHandle().unlockAndDeleteId(lockId);
524 } catch (KeeperException.NoNodeException e) {
532 * @throws MusicLockingException
534 public static void deleteLock(String lockName) throws MusicLockingException {
535 long start = System.currentTimeMillis();
536 logger.info(EELFLoggerDelegate.applicationLogger,"Deleting lock for " + lockName);
538 getLockingServiceHandle().deleteLock("/" + lockName);
539 } catch (MusicLockingException e) {
540 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DELTELOCK+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
541 throw new MusicLockingException(e.getMessage());
543 long end = System.currentTimeMillis();
544 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to delete lock:" + (end - start) + " ms");
554 * @throws MusicServiceException
556 public static TableMetadata returnColumnMetadata(String keyspace, String tablename) throws MusicServiceException {
557 return getDSHandle().returnColumnMetadata(keyspace, tablename);
565 public static void pureZkCreate(String nodeName) {
567 getLockingServiceHandle().getzkLockHandle().createNode(nodeName);
568 } catch (MusicLockingException e) {
569 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
578 public static void pureZkWrite(String nodeName, byte[] data) {
579 long start = System.currentTimeMillis();
580 logger.info(EELFLoggerDelegate.applicationLogger,"Performing zookeeper write to " + nodeName);
582 getLockingServiceHandle().getzkLockHandle().setNodeData(nodeName, data);
583 } catch (MusicLockingException e) {
584 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
586 logger.info(EELFLoggerDelegate.applicationLogger,"Performed zookeeper write to " + nodeName);
587 long end = System.currentTimeMillis();
588 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms");
596 public static byte[] pureZkRead(String nodeName) {
597 long start = System.currentTimeMillis();
600 data = getLockingServiceHandle().getzkLockHandle().getNodeData(nodeName);
601 } catch (MusicLockingException e) {
602 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
604 long end = System.currentTimeMillis();
605 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms");
611 // Prepared Query Additions.
615 * @param keyspaceName
620 * @throws MusicServiceException
622 public static ReturnType eventualPut(PreparedQueryObject queryObject) {
623 boolean result = false;
625 result = getDSHandle().executePut(queryObject, MusicUtil.EVENTUAL);
626 } catch (MusicServiceException | MusicQueryException ex) {
627 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
628 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() + " " + ex.getCause() + " " + ex);
629 return new ReturnType(ResultType.FAILURE, ex.getMessage());
632 return new ReturnType(ResultType.SUCCESS, "Success");
634 return new ReturnType(ResultType.FAILURE, "Failure");
640 * @param keyspaceName
647 public static ReturnType criticalPut(String keyspaceName, String tableName, String primaryKey,
648 PreparedQueryObject queryObject, String lockId, Condition conditionInfo) {
649 long start = System.currentTimeMillis();
652 MusicLockState mls = getLockingServiceHandle()
653 .getLockState(keyspaceName + "." + tableName + "." + primaryKey);
654 if (mls.getLockHolder().equals(lockId) == true) {
655 if (conditionInfo != null)
657 if (conditionInfo.testCondition() == false)
658 return new ReturnType(ResultType.FAILURE,
659 "Lock acquired but the condition is not true");
660 } catch (Exception e) {
661 return new ReturnType(ResultType.FAILURE,
662 "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
665 getDSHandle().executePut(queryObject, MusicUtil.CRITICAL);
666 long end = System.currentTimeMillis();
667 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the critical put:" + (end - start) + " ms");
668 return new ReturnType(ResultType.SUCCESS, "Update performed");
670 return new ReturnType(ResultType.FAILURE,
671 "Cannot perform operation since you are the not the lock holder");
672 } catch (MusicQueryException | MusicServiceException e) {
673 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
674 return new ReturnType(ResultType.FAILURE,
675 "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
677 }catch(MusicLockingException ex){
678 return new ReturnType(ResultType.FAILURE,ex.getMessage());
687 * @return Boolean Indicates success or failure
688 * @throws MusicServiceException
692 public static ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) throws MusicServiceException {
693 // this is mainly for some functions like keyspace creation etc which does not
694 // really need the bells and whistles of Music locking.
695 boolean result = false;
697 result = getDSHandle().executePut(queryObject, consistency);
698 } catch (MusicQueryException | MusicServiceException ex) {
699 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
700 throw new MusicServiceException(ex.getMessage());
702 return result?ResultType.SUCCESS:ResultType.FAILURE;
706 * This method performs DDL operation on cassandra.
708 * @param queryObject query object containing prepared query and values
710 * @throws MusicServiceException
712 public static ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException {
713 ResultSet results = null;
715 results = getDSHandle().executeEventualGet(queryObject);
716 } catch (MusicQueryException | MusicServiceException e) {
717 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
718 throw new MusicServiceException(e.getMessage());
724 * This method performs DDL operations on cassandra, if the the resource is available. Lock ID
725 * is used to check if the resource is free.
727 * @param keyspaceName name of the keyspace
728 * @param tableName name of the table
729 * @param primaryKey primary key value
730 * @param queryObject query object containing prepared query and values
731 * @param lockId lock ID to check if the resource is free to perform the operation.
734 public static ResultSet criticalGet(String keyspaceName, String tableName, String primaryKey,
735 PreparedQueryObject queryObject, String lockId) throws MusicServiceException {
736 ResultSet results = null;
738 MusicLockState mls = getLockingServiceHandle()
739 .getLockState(keyspaceName + "." + tableName + "." + primaryKey);
740 if (mls.getLockHolder().equals(lockId)) {
741 results = getDSHandle().executeCriticalGet(queryObject);
743 throw new MusicServiceException("YOU DO NOT HAVE THE LOCK");
744 } catch (MusicQueryException | MusicServiceException | MusicLockingException e) {
745 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
751 * This method performs DML operation on cassandra, when the lock of the dd is acquired.
753 * @param keyspaceName name of the keyspace
754 * @param tableName name of the table
755 * @param primaryKey primary key value
756 * @param queryObject query object containing prepared query and values
758 * @throws MusicLockingException
760 public static ReturnType atomicPut(String keyspaceName, String tableName, String primaryKey,
761 PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException {
763 long start = System.currentTimeMillis();
764 String key = keyspaceName + "." + tableName + "." + primaryKey;
765 String lockId = createLockReference(key);
766 long lockCreationTime = System.currentTimeMillis();
767 ReturnType lockAcqResult = acquireLock(key, lockId);
768 long lockAcqTime = System.currentTimeMillis();
769 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
770 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
771 ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
772 queryObject, lockId, conditionInfo);
773 long criticalPutTime = System.currentTimeMillis();
774 voluntaryReleaseLock(lockId);
775 long lockDeleteTime = System.currentTimeMillis();
776 String timingInfo = "|lock creation time:" + (lockCreationTime - start)
777 + "|lock accquire time:" + (lockAcqTime - lockCreationTime)
778 + "|critical put time:" + (criticalPutTime - lockAcqTime)
779 + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|";
780 criticalPutResult.setTimingInfo(timingInfo);
781 return criticalPutResult;
783 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
784 destroyLockRef(lockId);
785 return lockAcqResult;
790 * this function is mainly for the benchmarks to see the effect of lock deletion.
792 * @param keyspaceName
796 * @param conditionInfo
798 * @throws MusicLockingException
800 public static ReturnType atomicPutWithDeleteLock(String keyspaceName, String tableName,
801 String primaryKey, PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException {
803 long start = System.currentTimeMillis();
804 String key = keyspaceName + "." + tableName + "." + primaryKey;
805 String lockId = createLockReference(key);
806 long lockCreationTime = System.currentTimeMillis();
807 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
808 ReturnType lockAcqResult = acquireLock(key, lockId);
809 long lockAcqTime = System.currentTimeMillis();
810 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
811 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
812 ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
813 queryObject, lockId, conditionInfo);
814 long criticalPutTime = System.currentTimeMillis();
816 long lockDeleteTime = System.currentTimeMillis();
817 String timingInfo = "|lock creation time:" + (lockCreationTime - start)
818 + "|lock accquire time:" + (lockAcqTime - lockCreationTime)
819 + "|critical put time:" + (criticalPutTime - lockAcqTime)
820 + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|";
821 criticalPutResult.setTimingInfo(timingInfo);
822 return criticalPutResult;
824 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
826 return lockAcqResult;
834 * This method performs DDL operation on cassasndra, when the lock for the resource is acquired.
836 * @param keyspaceName name of the keyspace
837 * @param tableName name of the table
838 * @param primaryKey primary key value
839 * @param queryObject query object containing prepared query and values
841 * @throws MusicServiceException
842 * @throws MusicLockingException
844 public static ResultSet atomicGet(String keyspaceName, String tableName, String primaryKey,
845 PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException {
846 String key = keyspaceName + "." + tableName + "." + primaryKey;
847 String lockId = createLockReference(key);
848 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
849 ReturnType lockAcqResult = acquireLock(key, lockId);
850 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
851 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
853 criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
854 voluntaryReleaseLock(lockId);
857 destroyLockRef(lockId);
858 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
863 public static ResultSet atomicGetWithDeleteLock(String keyspaceName, String tableName, String primaryKey,
864 PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException {
865 String key = keyspaceName + "." + tableName + "." + primaryKey;
866 String lockId = createLockReference(key);
867 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
869 ReturnType lockAcqResult = acquireLock(key, lockId);
871 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
872 logger.info(EELFLoggerDelegate.applicationLogger, "acquired lock with id " + lockId);
873 ResultSet result = criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
878 logger.info(EELFLoggerDelegate.applicationLogger, "unable to acquire lock, id " + lockId);
886 * authenticate user logic
897 public static Map<String, Object> autheticateUser(String nameSpace, String userId,
898 String password, String keyspace, String aid, String operation)
900 Map<String, Object> resultMap = new HashMap<>();
902 resultMap = CachingUtil.validateRequest(nameSpace, userId, password, keyspace, aid,
904 if (!resultMap.isEmpty())
906 String isAAFApp = null;
908 isAAFApp= CachingUtil.isAAFApplication(nameSpace);
909 } catch(MusicServiceException e) {
910 resultMap.put("Exception", e.getMessage());
913 if(isAAFApp == null) {
914 resultMap.put("Exception", "Namespace: "+nameSpace+" doesn't exist. Please make sure ns(appName)"
915 + " is correct and Application is onboarded.");
918 boolean isAAF = Boolean.valueOf(isAAFApp);
919 if (userId == null || password == null) {
920 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
921 logger.error(EELFLoggerDelegate.errorLogger,"One or more required headers is missing. userId: " + userId
922 + " :: password: " + password);
923 resultMap.put("Exception",
924 "UserId and Password are mandatory for the operation " + operation);
927 if(!isAAF && !(operation.equals("createKeySpace"))) {
928 resultMap = CachingUtil.authenticateAIDUser(nameSpace, userId, password, keyspace);
929 if (!resultMap.isEmpty())
933 if (isAAF && nameSpace != null && userId != null && password != null) {
934 boolean isValid = true;
936 isValid = CachingUtil.authenticateAAFUser(nameSpace, userId, password, keyspace);
937 } catch (Exception e) {
938 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
939 logger.error(EELFLoggerDelegate.errorLogger,"Got exception while AAF authentication for namespace " + nameSpace);
940 resultMap.put("Exception", e.getMessage());
943 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
944 resultMap.put("Exception", "User not authenticated...");
946 if (!resultMap.isEmpty())
951 if (operation.equals("createKeySpace")) {
952 logger.info(EELFLoggerDelegate.applicationLogger,"AID is not provided. Creating new UUID for keyspace.");
953 PreparedQueryObject pQuery = new PreparedQueryObject();
954 pQuery.appendQueryString(
955 "select uuid from admin.keyspace_master where application_name=? and username=? and keyspace_name=? allow filtering");
956 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), nameSpace));
957 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
958 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),
959 MusicUtil.DEFAULTKEYSPACENAME));
962 Row rs = MusicCore.get(pQuery).one();
963 uuid = rs.getUUID("uuid").toString();
964 resultMap.put("uuid", "existing");
965 } catch (Exception e) {
966 logger.info(EELFLoggerDelegate.applicationLogger,"No UUID found in DB. So creating new UUID.");
967 uuid = CachingUtil.generateUUID();
968 resultMap.put("uuid", "new");
970 resultMap.put("aid", uuid);
980 public static Map<String, Object> validateLock(String lockName) {
981 Map<String, Object> resultMap = new HashMap<>();
982 String[] locks = lockName.split("\\.");
983 if(locks.length < 3) {
984 resultMap.put("Exception", "Invalid lock. Please make sure lock is of the type keyspaceName.tableName.primaryKey");
987 String keyspace= locks[0];
988 if(keyspace.startsWith("$"))
989 keyspace = keyspace.substring(1);
990 resultMap.put("keyspace",keyspace);