2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (c) 2017 AT&T Intellectual Property
6 * ===================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 * ============LICENSE_END=============================================
20 * ====================================================================
22 package org.onap.music.main;
25 import java.io.StringWriter;
26 import java.util.HashMap;
28 import java.util.StringTokenizer;
30 import org.apache.zookeeper.KeeperException;
31 import org.apache.zookeeper.KeeperException.NoNodeException;
32 import org.onap.music.datastore.MusicDataStore;
33 import org.onap.music.datastore.PreparedQueryObject;
34 import org.onap.music.datastore.jsonobjects.JsonKeySpace;
35 import org.onap.music.eelf.logging.EELFLoggerDelegate;
36 import org.onap.music.eelf.logging.format.AppMessages;
37 import org.onap.music.eelf.logging.format.ErrorSeverity;
38 import org.onap.music.eelf.logging.format.ErrorTypes;
39 import org.onap.music.exceptions.MusicLockingException;
40 import org.onap.music.exceptions.MusicQueryException;
41 import org.onap.music.exceptions.MusicServiceException;
42 import org.onap.music.lockingservice.MusicLockState;
43 import org.onap.music.lockingservice.MusicLockState.LockStatus;
44 import org.onap.music.lockingservice.MusicLockingService;
46 import com.datastax.driver.core.ColumnDefinitions;
47 import com.datastax.driver.core.ColumnDefinitions.Definition;
48 import com.datastax.driver.core.DataType;
49 import com.datastax.driver.core.ResultSet;
50 import com.datastax.driver.core.Row;
51 import com.datastax.driver.core.TableMetadata;
58 public class MusicCore {
60 public static MusicLockingService mLockHandle = null;
61 public static MusicDataStore mDstoreHandle = null;
62 private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicCore.class);
64 public static class Condition {
65 Map<String, Object> conditions;
66 PreparedQueryObject selectQueryForTheRow;
68 public Condition(Map<String, Object> conditions, PreparedQueryObject selectQueryForTheRow) {
69 this.conditions = conditions;
70 this.selectQueryForTheRow = selectQueryForTheRow;
73 public boolean testCondition() throws Exception {
74 // first generate the row
75 ResultSet results = quorumGet(selectQueryForTheRow);
80 return getDSHandle().doesRowSatisfyCondition(row, conditions);
85 public static MusicLockingService getLockingServiceHandle() throws MusicLockingException {
86 logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring lock store handle");
87 long start = System.currentTimeMillis();
89 if (mLockHandle == null) {
91 mLockHandle = new MusicLockingService();
92 } catch (Exception e) {
93 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKHANDLE,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
94 throw new MusicLockingException("Failed to aquire Locl store handle " + e);
97 long end = System.currentTimeMillis();
98 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire lock store handle:" + (end - start) + " ms");
107 public static MusicDataStore getDSHandle(String remoteIp) {
108 logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring data store handle");
109 long start = System.currentTimeMillis();
110 if (mDstoreHandle == null) {
111 mDstoreHandle = new MusicDataStore(remoteIp);
113 long end = System.currentTimeMillis();
114 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms");
115 return mDstoreHandle;
121 * @throws MusicServiceException
123 public static MusicDataStore getDSHandle() throws MusicServiceException {
124 logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring data store handle");
125 long start = System.currentTimeMillis();
126 if (mDstoreHandle == null) {
127 // Quick Fix - Best to put this into every call to getDSHandle?
128 if (! "localhost".equals(MusicUtil.getMyCassaHost())) {
129 mDstoreHandle = new MusicDataStore(MusicUtil.getMyCassaHost());
131 mDstoreHandle = new MusicDataStore();
134 if(mDstoreHandle.getSession() == null) {
135 String message = "Connection to Cassandra has not been enstablished."
136 + " Please check connection properites and reboot.";
137 logger.info(EELFLoggerDelegate.applicationLogger, message);
138 throw new MusicServiceException(message);
140 long end = System.currentTimeMillis();
141 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms");
142 return mDstoreHandle;
145 public static String createLockReference(String lockName) {
146 logger.info(EELFLoggerDelegate.applicationLogger,"Creating lock reference for lock name:" + lockName);
147 long start = System.currentTimeMillis();
148 String lockId = null;
150 lockId = getLockingServiceHandle().createLockId("/" + lockName);
151 } catch (MusicLockingException e) {
152 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.CREATELOCK+lockName,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
155 long end = System.currentTimeMillis();
156 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to create lock reference:" + (end - start) + " ms");
165 public static boolean isTableOrKeySpaceLock(String key) {
166 String[] splitString = key.split("\\.");
167 if (splitString.length > 2)
178 public static MusicLockState getMusicLockState(String key) {
179 long start = System.currentTimeMillis();
181 String[] splitString = key.split("\\.");
182 String keyspaceName = splitString[0];
183 String tableName = splitString[1];
184 String primaryKey = splitString[2];
186 String lockName = keyspaceName + "." + tableName + "." + primaryKey;
187 mls = getLockingServiceHandle().getLockState(lockName);
188 long end = System.currentTimeMillis();
189 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to get lock state:" + (end - start) + " ms");
191 } catch (NullPointerException | MusicLockingException e) {
192 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
197 public static ReturnType acquireLockWithLease(String key, String lockId, long leasePeriod) {
199 long start = System.currentTimeMillis();
200 /* check if the current lock has exceeded its lease and if yes, release that lock */
201 MusicLockState mls = getMusicLockState(key);
203 if (mls.getLockStatus().equals(LockStatus.LOCKED)) {
204 logger.info(EELFLoggerDelegate.applicationLogger,"The current lock holder for " + key + " is " + mls.getLockHolder()
205 + ". Checking if it has exceeded lease");
206 long currentLockPeriod = System.currentTimeMillis() - mls.getLeaseStartTime();
207 long currentLeasePeriod = mls.getLeasePeriod();
208 if (currentLockPeriod > currentLeasePeriod) {
209 logger.info(EELFLoggerDelegate.applicationLogger,"Lock period " + currentLockPeriod
210 + " has exceeded lease period " + currentLeasePeriod);
211 boolean voluntaryRelease = false;
212 String currentLockHolder = mls.getLockHolder();
213 mls = releaseLock(currentLockHolder, voluntaryRelease);
217 logger.error(EELFLoggerDelegate.errorLogger,key, AppMessages.INVALIDLOCK,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
220 * call the traditional acquire lock now and if the result returned is true, set the
221 * begin time-stamp and lease period
223 if (acquireLock(key, lockId).getResult() == ResultType.SUCCESS) {
224 mls = getMusicLockState(key);// get latest state
226 logger.info(EELFLoggerDelegate.applicationLogger,"Music Lock State is null");
227 return new ReturnType(ResultType.FAILURE, "Could not acquire lock, Lock State is null");
229 if (mls.getLeaseStartTime() == -1) {// set it again only if it is not set already
230 mls.setLeaseStartTime(System.currentTimeMillis());
231 mls.setLeasePeriod(leasePeriod);
232 getLockingServiceHandle().setLockState(key, mls);
234 long end = System.currentTimeMillis();
235 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire leased lock:" + (end - start) + " ms");
236 return new ReturnType(ResultType.SUCCESS, "Accquired lock");
238 long end = System.currentTimeMillis();
239 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to fail to acquire leased lock:" + (end - start) + " ms");
240 return new ReturnType(ResultType.FAILURE, "Could not acquire lock");
242 } catch (Exception e) {
243 StringWriter sw = new StringWriter();
244 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR506E] Failed to aquire lock ",ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
246 String exceptionAsString = sw.toString();
247 return new ReturnType(ResultType.FAILURE,
248 "Exception thrown in acquireLockWithLease:\n" + exceptionAsString);
252 public static ReturnType acquireLock(String key, String lockId) throws MusicLockingException {
254 * first check if I am on top. Since ids are not reusable there is no need to check
255 * lockStatus If the status is unlocked, then the above call will automatically return
258 Boolean result = false;
260 result = getLockingServiceHandle().isMyTurn(lockId);
261 } catch (MusicLockingException e2) {
262 logger.error(EELFLoggerDelegate.errorLogger,AppMessages.INVALIDLOCK + lockId + " " + e2);
263 throw new MusicLockingException();
266 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Not your turn, someone else has the lock");
268 if (!getLockingServiceHandle().lockIdExists(lockId)) {
269 logger.info(EELFLoggerDelegate.applicationLogger, "In acquire lock: this lockId doesn't exist");
270 return new ReturnType(ResultType.FAILURE, "Lockid doesn't exist");
272 } catch (MusicLockingException e) {
273 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
274 throw new MusicLockingException();
276 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: returning failure");
277 return new ReturnType(ResultType.FAILURE, "Not your turn, someone else has the lock");
281 // this is for backward compatibility where locks could also be acquired on just
282 // keyspaces or tables.
283 if (isTableOrKeySpaceLock(key)) {
284 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: A table or keyspace lock so no need to perform sync...so returning true");
285 return new ReturnType(ResultType.SUCCESS, "A table or keyspace lock so no need to perform sync...so returning true");
288 // read the lock name corresponding to the key and if the status is locked or being locked,
290 MusicLockState currentMls = null;
291 MusicLockState newMls = null;
293 currentMls = getMusicLockState(key);
294 String currentLockHolder = null;
295 if(currentMls != null) { currentLockHolder = currentMls.getLockHolder(); };
296 if (lockId.equals(currentLockHolder)) {
297 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: You already have the lock!");
298 return new ReturnType(ResultType.SUCCESS, "You already have the lock!");
300 } catch (NullPointerException e) {
301 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
304 // change status to "being locked". This state transition is necessary to ensure syncing
305 // before granting the lock
306 String lockHolder = null;
307 boolean needToSyncQuorum = false;
308 if (currentMls != null)
309 needToSyncQuorum = currentMls.isNeedToSyncQuorum();
312 newMls = new MusicLockState(MusicLockState.LockStatus.BEING_LOCKED, lockHolder,
315 getLockingServiceHandle().setLockState(key, newMls);
316 } catch (MusicLockingException e1) {
317 logger.error(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
319 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to being_locked");
321 // do syncing if this was a forced lock release
322 if (needToSyncQuorum) {
323 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Since there was a forcible release, need to sync quorum!");
326 } catch (Exception e) {
327 logger.error(EELFLoggerDelegate.errorLogger,"Failed to set Lock state " + e);
331 // change status to locked
333 needToSyncQuorum = false;
334 newMls = new MusicLockState(MusicLockState.LockStatus.LOCKED, lockHolder, needToSyncQuorum);
336 getLockingServiceHandle().setLockState(key, newMls);
337 } catch (MusicLockingException e) {
338 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
340 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to locked and assigned current lock ref "
341 + lockId + " as holder");
343 return new ReturnType(result?ResultType.SUCCESS:ResultType.FAILURE, "Set lock state to locked and assigned a lock holder");
350 * @param keyspaceName
355 public boolean createKeyspace(String keyspaceName, JsonKeySpace kspObject) throws Exception {
360 private static void syncQuorum(String key) throws Exception {
361 logger.info(EELFLoggerDelegate.applicationLogger,"Performing sync operation---");
362 String[] splitString = key.split("\\.");
363 String keyspaceName = splitString[0];
364 String tableName = splitString[1];
365 String primaryKeyValue = splitString[2];
366 PreparedQueryObject selectQuery = new PreparedQueryObject();
367 PreparedQueryObject updateQuery = new PreparedQueryObject();
369 // get the primary key d
370 TableMetadata tableInfo = returnColumnMetadata(keyspaceName, tableName);
371 String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();// we only support single
373 DataType primaryKeyType = tableInfo.getPrimaryKey().get(0).getType();
374 Object cqlFormattedPrimaryKeyValue =
375 MusicUtil.convertToActualDataType(primaryKeyType, primaryKeyValue);
377 // get the row of data from a quorum
378 selectQuery.appendQueryString("SELECT * FROM " + keyspaceName + "." + tableName + " WHERE "
379 + primaryKeyName + "= ?" + ";");
380 selectQuery.addValue(cqlFormattedPrimaryKeyValue);
381 ResultSet results = null;
383 results = getDSHandle().executeCriticalGet(selectQuery);
384 // write it back to a quorum
385 Row row = results.one();
386 ColumnDefinitions colInfo = row.getColumnDefinitions();
387 int totalColumns = colInfo.size();
389 StringBuilder fieldValueString = new StringBuilder("");
390 for (Definition definition : colInfo) {
391 String colName = definition.getName();
392 if (colName.equals(primaryKeyName))
394 DataType colType = definition.getType();
395 Object valueObj = getDSHandle().getColValue(row, colName, colType);
396 Object valueString = MusicUtil.convertToActualDataType(colType, valueObj);
397 fieldValueString.append(colName + " = ?");
398 updateQuery.addValue(valueString);
399 if (counter != (totalColumns - 1))
400 fieldValueString.append(",");
401 counter = counter + 1;
403 updateQuery.appendQueryString("UPDATE " + keyspaceName + "." + tableName + " SET "
404 + fieldValueString + " WHERE " + primaryKeyName + "= ? " + ";");
405 updateQuery.addValue(cqlFormattedPrimaryKeyValue);
407 getDSHandle().executePut(updateQuery, "critical");
408 } catch (MusicServiceException | MusicQueryException e) {
409 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.QUERYERROR +""+updateQuery ,ErrorSeverity.MAJOR, ErrorTypes.QUERYERROR);
421 public static ResultSet quorumGet(PreparedQueryObject query) {
422 ResultSet results = null;
424 results = getDSHandle().executeCriticalGet(query);
425 } catch (MusicServiceException | MusicQueryException e) {
426 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.MAJOR, ErrorTypes.GENERALSERVICEERROR);
437 * @throws MusicServiceException
439 public static Map<String, HashMap<String, Object>> marshallResults(ResultSet results) throws MusicServiceException {
440 return getDSHandle().marshalData(results);
448 public static String whoseTurnIsIt(String lockName) {
451 return getLockingServiceHandle().whoseTurnIsIt("/" + lockName) + "";
452 } catch (MusicLockingException e) {
453 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKINGERROR+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
465 public static String getLockNameFromId(String lockId) {
466 StringTokenizer st = new StringTokenizer(lockId);
467 return st.nextToken("$");
470 public static void destroyLockRef(String lockId) {
471 long start = System.currentTimeMillis();
473 getLockingServiceHandle().unlockAndDeleteId(lockId);
474 } catch (MusicLockingException | NoNodeException e) {
475 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DESTROYLOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
477 long end = System.currentTimeMillis();
478 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to destroy lock reference:" + (end - start) + " ms");
481 public static MusicLockState releaseLock(String lockId, boolean voluntaryRelease) {
482 long start = System.currentTimeMillis();
484 getLockingServiceHandle().unlockAndDeleteId(lockId);
485 } catch (MusicLockingException e1) {
486 logger.error(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
487 } catch (KeeperException.NoNodeException nne) {
488 logger.error(EELFLoggerDelegate.errorLogger,"Failed to release Lock " + lockId + " " + nne);
489 MusicLockState mls = new MusicLockState("Lock doesn't exists. Release lock operation failed.");
492 String lockName = getLockNameFromId(lockId);
494 String lockHolder = null;
495 if (voluntaryRelease) {
496 mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder);
497 logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock voluntarily released for " + lockId);
499 boolean needToSyncQuorum = true;
500 mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder,
502 logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock forcibly released for " + lockId);
505 getLockingServiceHandle().setLockState(lockName, mls);
506 } catch (MusicLockingException e) {
507 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
509 long end = System.currentTimeMillis();
510 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to release lock:" + (end - start) + " ms");
514 public static void voluntaryReleaseLock(String lockId) throws MusicLockingException{
516 getLockingServiceHandle().unlockAndDeleteId(lockId);
517 } catch (KeeperException.NoNodeException e) {
525 * @throws MusicLockingException
527 public static void deleteLock(String lockName) throws MusicLockingException {
528 long start = System.currentTimeMillis();
529 logger.info(EELFLoggerDelegate.applicationLogger,"Deleting lock for " + lockName);
531 getLockingServiceHandle().deleteLock("/" + lockName);
532 } catch (MusicLockingException e) {
533 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DELTELOCK+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
534 throw new MusicLockingException(e.getMessage());
536 long end = System.currentTimeMillis();
537 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to delete lock:" + (end - start) + " ms");
547 * @throws MusicServiceException
549 public static TableMetadata returnColumnMetadata(String keyspace, String tablename) throws MusicServiceException {
550 return getDSHandle().returnColumnMetadata(keyspace, tablename);
558 public static void pureZkCreate(String nodeName) {
560 getLockingServiceHandle().getzkLockHandle().createNode(nodeName);
561 } catch (MusicLockingException e) {
562 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
571 public static void pureZkWrite(String nodeName, byte[] data) {
572 long start = System.currentTimeMillis();
573 logger.info(EELFLoggerDelegate.applicationLogger,"Performing zookeeper write to " + nodeName);
575 getLockingServiceHandle().getzkLockHandle().setNodeData(nodeName, data);
576 } catch (MusicLockingException e) {
577 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
579 logger.info(EELFLoggerDelegate.applicationLogger,"Performed zookeeper write to " + nodeName);
580 long end = System.currentTimeMillis();
581 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms");
589 public static byte[] pureZkRead(String nodeName) {
590 long start = System.currentTimeMillis();
593 data = getLockingServiceHandle().getzkLockHandle().getNodeData(nodeName);
594 } catch (MusicLockingException e) {
595 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
597 long end = System.currentTimeMillis();
598 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms");
604 // Prepared Query Additions.
608 * @param keyspaceName
613 * @throws MusicServiceException
615 public static ReturnType eventualPut(PreparedQueryObject queryObject) {
616 boolean result = false;
618 result = getDSHandle().executePut(queryObject, MusicUtil.EVENTUAL);
619 } catch (MusicServiceException | MusicQueryException ex) {
620 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
621 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() + " " + ex.getCause() + " " + ex);
622 return new ReturnType(ResultType.FAILURE, ex.getMessage());
625 return new ReturnType(ResultType.SUCCESS, "Success");
627 return new ReturnType(ResultType.FAILURE, "Failure");
633 * @param keyspaceName
640 public static ReturnType criticalPut(String keyspaceName, String tableName, String primaryKey,
641 PreparedQueryObject queryObject, String lockId, Condition conditionInfo) {
642 long start = System.currentTimeMillis();
645 MusicLockState mls = getLockingServiceHandle()
646 .getLockState(keyspaceName + "." + tableName + "." + primaryKey);
647 if (mls.getLockHolder().equals(lockId) == true) {
648 if (conditionInfo != null)
650 if (conditionInfo.testCondition() == false)
651 return new ReturnType(ResultType.FAILURE,
652 "Lock acquired but the condition is not true");
653 } catch (Exception e) {
654 return new ReturnType(ResultType.FAILURE,
655 "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
658 getDSHandle().executePut(queryObject, MusicUtil.CRITICAL);
659 long end = System.currentTimeMillis();
660 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the critical put:" + (end - start) + " ms");
661 return new ReturnType(ResultType.SUCCESS, "Update performed");
663 return new ReturnType(ResultType.FAILURE,
664 "Cannot perform operation since you are the not the lock holder");
665 } catch (MusicQueryException | MusicServiceException e) {
666 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
667 return new ReturnType(ResultType.FAILURE,
668 "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
670 }catch(MusicLockingException ex){
671 return new ReturnType(ResultType.FAILURE,ex.getMessage());
680 * @return Boolean Indicates success or failure
681 * @throws MusicServiceException
685 public static ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) throws MusicServiceException {
686 // this is mainly for some functions like keyspace creation etc which does not
687 // really need the bells and whistles of Music locking.
688 boolean result = false;
690 result = getDSHandle().executePut(queryObject, consistency);
691 } catch (MusicQueryException | MusicServiceException ex) {
692 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
693 throw new MusicServiceException(ex.getMessage());
695 return result?ResultType.SUCCESS:ResultType.FAILURE;
699 * This method performs DDL operation on cassandra.
701 * @param queryObject query object containing prepared query and values
703 * @throws MusicServiceException
705 public static ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException {
706 ResultSet results = null;
708 results = getDSHandle().executeEventualGet(queryObject);
709 } catch (MusicQueryException | MusicServiceException e) {
710 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
711 throw new MusicServiceException(e.getMessage());
716 public static String getMyHostId() {
717 PreparedQueryObject pQuery = new PreparedQueryObject();
718 pQuery.appendQueryString("SELECT HOST_ID FROM SYSTEM.LOCAL");
721 rs = getDSHandle().executeEventualGet(pQuery);
723 return (row == null) ? "UNKNOWN" : row.getUUID("HOST_ID").toString();
724 } catch (Exception e) {
726 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
728 logger.error(EELFLoggerDelegate.errorLogger, "Some issue during MusicCore.getMyHostId");
733 * This method performs DDL operations on cassandra, if the the resource is available. Lock ID
734 * is used to check if the resource is free.
736 * @param keyspaceName name of the keyspace
737 * @param tableName name of the table
738 * @param primaryKey primary key value
739 * @param queryObject query object containing prepared query and values
740 * @param lockId lock ID to check if the resource is free to perform the operation.
743 public static ResultSet criticalGet(String keyspaceName, String tableName, String primaryKey,
744 PreparedQueryObject queryObject, String lockId) throws MusicServiceException {
745 ResultSet results = null;
747 MusicLockState mls = getLockingServiceHandle()
748 .getLockState(keyspaceName + "." + tableName + "." + primaryKey);
749 if (mls.getLockHolder().equals(lockId)) {
750 results = getDSHandle().executeCriticalGet(queryObject);
752 throw new MusicServiceException("YOU DO NOT HAVE THE LOCK");
753 } catch (MusicQueryException | MusicServiceException | MusicLockingException e) {
754 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
760 * This method performs DML operation on cassandra, when the lock of the dd is acquired.
762 * @param keyspaceName name of the keyspace
763 * @param tableName name of the table
764 * @param primaryKey primary key value
765 * @param queryObject query object containing prepared query and values
767 * @throws MusicLockingException
769 public static ReturnType atomicPut(String keyspaceName, String tableName, String primaryKey,
770 PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException {
772 long start = System.currentTimeMillis();
773 String key = keyspaceName + "." + tableName + "." + primaryKey;
774 String lockId = createLockReference(key);
775 long lockCreationTime = System.currentTimeMillis();
776 ReturnType lockAcqResult = acquireLock(key, lockId);
777 long lockAcqTime = System.currentTimeMillis();
778 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
779 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
780 ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
781 queryObject, lockId, conditionInfo);
782 long criticalPutTime = System.currentTimeMillis();
783 voluntaryReleaseLock(lockId);
784 long lockDeleteTime = System.currentTimeMillis();
785 String timingInfo = "|lock creation time:" + (lockCreationTime - start)
786 + "|lock accquire time:" + (lockAcqTime - lockCreationTime)
787 + "|critical put time:" + (criticalPutTime - lockAcqTime)
788 + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|";
789 criticalPutResult.setTimingInfo(timingInfo);
790 return criticalPutResult;
792 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
793 destroyLockRef(lockId);
794 return lockAcqResult;
799 * this function is mainly for the benchmarks to see the effect of lock deletion.
801 * @param keyspaceName
805 * @param conditionInfo
807 * @throws MusicLockingException
809 public static ReturnType atomicPutWithDeleteLock(String keyspaceName, String tableName,
810 String primaryKey, PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException {
812 long start = System.currentTimeMillis();
813 String key = keyspaceName + "." + tableName + "." + primaryKey;
814 String lockId = createLockReference(key);
815 long lockCreationTime = System.currentTimeMillis();
816 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
817 ReturnType lockAcqResult = acquireLock(key, lockId);
818 long lockAcqTime = System.currentTimeMillis();
819 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
820 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
821 ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
822 queryObject, lockId, conditionInfo);
823 long criticalPutTime = System.currentTimeMillis();
825 long lockDeleteTime = System.currentTimeMillis();
826 String timingInfo = "|lock creation time:" + (lockCreationTime - start)
827 + "|lock accquire time:" + (lockAcqTime - lockCreationTime)
828 + "|critical put time:" + (criticalPutTime - lockAcqTime)
829 + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|";
830 criticalPutResult.setTimingInfo(timingInfo);
831 return criticalPutResult;
833 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
835 return lockAcqResult;
843 * This method performs DDL operation on cassasndra, when the lock for the resource is acquired.
845 * @param keyspaceName name of the keyspace
846 * @param tableName name of the table
847 * @param primaryKey primary key value
848 * @param queryObject query object containing prepared query and values
850 * @throws MusicServiceException
851 * @throws MusicLockingException
853 public static ResultSet atomicGet(String keyspaceName, String tableName, String primaryKey,
854 PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException {
855 String key = keyspaceName + "." + tableName + "." + primaryKey;
856 String lockId = createLockReference(key);
857 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
858 ReturnType lockAcqResult = acquireLock(key, lockId);
859 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
860 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
862 criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
863 voluntaryReleaseLock(lockId);
866 destroyLockRef(lockId);
867 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
872 public static ResultSet atomicGetWithDeleteLock(String keyspaceName, String tableName, String primaryKey,
873 PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException {
874 String key = keyspaceName + "." + tableName + "." + primaryKey;
875 String lockId = createLockReference(key);
876 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
878 ReturnType lockAcqResult = acquireLock(key, lockId);
880 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
881 logger.info(EELFLoggerDelegate.applicationLogger, "acquired lock with id " + lockId);
882 ResultSet result = criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
887 logger.info(EELFLoggerDelegate.applicationLogger, "unable to acquire lock, id " + lockId);
895 * authenticate user logic
906 public static Map<String, Object> autheticateUser(String nameSpace, String userId,
907 String password, String keyspace, String aid, String operation)
909 Map<String, Object> resultMap = new HashMap<>();
911 resultMap = CachingUtil.validateRequest(nameSpace, userId, password, keyspace, aid,
913 if (!resultMap.isEmpty())
915 String isAAFApp = null;
917 isAAFApp= CachingUtil.isAAFApplication(nameSpace);
918 } catch(MusicServiceException e) {
919 resultMap.put("Exception", e.getMessage());
922 if(isAAFApp == null) {
923 resultMap.put("Exception", "Namespace: "+nameSpace+" doesn't exist. Please make sure ns(appName)"
924 + " is correct and Application is onboarded.");
927 boolean isAAF = Boolean.valueOf(isAAFApp);
928 if (userId == null || password == null) {
929 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
930 logger.error(EELFLoggerDelegate.errorLogger,"One or more required headers is missing. userId: " + userId
931 + " :: password: " + password);
932 resultMap.put("Exception",
933 "UserId and Password are mandatory for the operation " + operation);
936 if(!isAAF && !(operation.equals("createKeySpace"))) {
937 resultMap = CachingUtil.authenticateAIDUser(nameSpace, userId, password, keyspace);
938 if (!resultMap.isEmpty())
942 if (isAAF && nameSpace != null && userId != null && password != null) {
943 boolean isValid = true;
945 isValid = CachingUtil.authenticateAAFUser(nameSpace, userId, password, keyspace);
946 } catch (Exception e) {
947 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
948 logger.error(EELFLoggerDelegate.errorLogger,"Got exception while AAF authentication for namespace " + nameSpace);
949 resultMap.put("Exception", e.getMessage());
952 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
953 resultMap.put("Exception", "User not authenticated...");
955 if (!resultMap.isEmpty())
960 if (operation.equals("createKeySpace")) {
961 logger.info(EELFLoggerDelegate.applicationLogger,"AID is not provided. Creating new UUID for keyspace.");
962 PreparedQueryObject pQuery = new PreparedQueryObject();
963 pQuery.appendQueryString(
964 "select uuid from admin.keyspace_master where application_name=? and username=? and keyspace_name=? allow filtering");
965 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), nameSpace));
966 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
967 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),
968 MusicUtil.DEFAULTKEYSPACENAME));
971 Row rs = MusicCore.get(pQuery).one();
972 uuid = rs.getUUID("uuid").toString();
973 resultMap.put("uuid", "existing");
974 } catch (Exception e) {
975 logger.info(EELFLoggerDelegate.applicationLogger,"No UUID found in DB. So creating new UUID.");
976 uuid = CachingUtil.generateUUID();
977 resultMap.put("uuid", "new");
979 resultMap.put("aid", uuid);
989 public static Map<String, Object> validateLock(String lockName) {
990 Map<String, Object> resultMap = new HashMap<>();
991 String[] locks = lockName.split("\\.");
992 if(locks.length < 3) {
993 resultMap.put("Exception", "Invalid lock. Please make sure lock is of the type keyspaceName.tableName.primaryKey");
996 String keyspace= locks[0];
997 if(keyspace.startsWith("$"))
998 keyspace = keyspace.substring(1);
999 resultMap.put("keyspace",keyspace);