2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (c) 2017 AT&T Intellectual Property
6 * ===================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 * ============LICENSE_END=============================================
20 * ====================================================================
22 package org.onap.music.main;
25 import java.io.StringWriter;
26 import java.util.HashMap;
28 import java.util.StringTokenizer;
30 import org.apache.zookeeper.KeeperException;
31 import org.apache.zookeeper.KeeperException.NoNodeException;
32 import org.onap.music.datastore.MusicDataStore;
33 import org.onap.music.datastore.PreparedQueryObject;
34 import org.onap.music.datastore.jsonobjects.JsonKeySpace;
35 import org.onap.music.eelf.logging.EELFLoggerDelegate;
36 import org.onap.music.eelf.logging.format.AppMessages;
37 import org.onap.music.eelf.logging.format.ErrorSeverity;
38 import org.onap.music.eelf.logging.format.ErrorTypes;
39 import org.onap.music.exceptions.MusicLockingException;
40 import org.onap.music.exceptions.MusicQueryException;
41 import org.onap.music.exceptions.MusicServiceException;
42 import org.onap.music.lockingservice.MusicLockState;
43 import org.onap.music.lockingservice.MusicLockState.LockStatus;
44 import org.onap.music.lockingservice.MusicLockingService;
46 import com.datastax.driver.core.ColumnDefinitions;
47 import com.datastax.driver.core.ColumnDefinitions.Definition;
48 import com.datastax.driver.core.DataType;
49 import com.datastax.driver.core.ResultSet;
50 import com.datastax.driver.core.Row;
51 import com.datastax.driver.core.TableMetadata;
58 public class MusicCore {
60 public static MusicLockingService mLockHandle = null;
61 public static MusicDataStore mDstoreHandle = null;
62 private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicCore.class);
64 public static class Condition {
65 Map<String, Object> conditions;
66 PreparedQueryObject selectQueryForTheRow;
68 public Condition(Map<String, Object> conditions, PreparedQueryObject selectQueryForTheRow) {
69 this.conditions = conditions;
70 this.selectQueryForTheRow = selectQueryForTheRow;
73 public boolean testCondition() throws Exception {
74 // first generate the row
75 ResultSet results = quorumGet(selectQueryForTheRow);
76 Row row = results.one();
77 return getDSHandle().doesRowSatisfyCondition(row, conditions);
82 public static MusicLockingService getLockingServiceHandle() throws MusicLockingException {
83 logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring lock store handle");
84 long start = System.currentTimeMillis();
86 if (mLockHandle == null) {
88 mLockHandle = new MusicLockingService();
89 } catch (Exception e) {
90 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKHANDLE,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
91 throw new MusicLockingException("Failed to aquire Locl store handle " + e);
94 long end = System.currentTimeMillis();
95 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire lock store handle:" + (end - start) + " ms");
104 public static MusicDataStore getDSHandle(String remoteIp) {
105 logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring data store handle");
106 long start = System.currentTimeMillis();
107 if (mDstoreHandle == null) {
108 mDstoreHandle = new MusicDataStore(remoteIp);
110 long end = System.currentTimeMillis();
111 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms");
112 return mDstoreHandle;
118 * @throws MusicServiceException
120 public static MusicDataStore getDSHandle() throws MusicServiceException {
121 logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring data store handle");
122 long start = System.currentTimeMillis();
123 if (mDstoreHandle == null) {
124 // Quick Fix - Best to put this into every call to getDSHandle?
125 if (! MusicUtil.getMyCassaHost().equals("localhost") ) {
126 mDstoreHandle = new MusicDataStore(MusicUtil.getMyCassaHost());
128 mDstoreHandle = new MusicDataStore();
131 if(mDstoreHandle.getSession() == null) {
132 String message = "Connection to Cassandra has not been enstablished."
133 + " Please check connection properites and reboot.";
134 logger.info(EELFLoggerDelegate.applicationLogger, message);
135 throw new MusicServiceException(message);
137 long end = System.currentTimeMillis();
138 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms");
139 return mDstoreHandle;
142 public static String createLockReference(String lockName) {
143 logger.info(EELFLoggerDelegate.applicationLogger,"Creating lock reference for lock name:" + lockName);
144 long start = System.currentTimeMillis();
145 String lockId = null;
147 lockId = getLockingServiceHandle().createLockId("/" + lockName);
148 } catch (MusicLockingException e) {
149 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.CREATELOCK+lockName,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
152 long end = System.currentTimeMillis();
153 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to create lock reference:" + (end - start) + " ms");
162 public static boolean isTableOrKeySpaceLock(String key) {
163 String[] splitString = key.split("\\.");
164 if (splitString.length > 2)
175 public static MusicLockState getMusicLockState(String key) {
176 long start = System.currentTimeMillis();
178 String[] splitString = key.split("\\.");
179 String keyspaceName = splitString[0];
180 String tableName = splitString[1];
181 String primaryKey = splitString[2];
183 String lockName = keyspaceName + "." + tableName + "." + primaryKey;
184 mls = getLockingServiceHandle().getLockState(lockName);
185 long end = System.currentTimeMillis();
186 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to get lock state:" + (end - start) + " ms");
188 } catch (NullPointerException | MusicLockingException e) {
189 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
194 public static ReturnType acquireLockWithLease(String key, String lockId, long leasePeriod) {
196 long start = System.currentTimeMillis();
197 /* check if the current lock has exceeded its lease and if yes, release that lock */
198 MusicLockState mls = getMusicLockState(key);
200 if (mls.getLockStatus().equals(LockStatus.LOCKED)) {
201 logger.info(EELFLoggerDelegate.applicationLogger,"The current lock holder for " + key + " is " + mls.getLockHolder()
202 + ". Checking if it has exceeded lease");
203 long currentLockPeriod = System.currentTimeMillis() - mls.getLeaseStartTime();
204 long currentLeasePeriod = mls.getLeasePeriod();
205 if (currentLockPeriod > currentLeasePeriod) {
206 logger.info(EELFLoggerDelegate.applicationLogger,"Lock period " + currentLockPeriod
207 + " has exceeded lease period " + currentLeasePeriod);
208 boolean voluntaryRelease = false;
209 String currentLockHolder = mls.getLockHolder();
210 mls = releaseLock(currentLockHolder, voluntaryRelease);
214 logger.error(EELFLoggerDelegate.errorLogger,key, AppMessages.INVALIDLOCK,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
217 * call the traditional acquire lock now and if the result returned is true, set the
218 * begin time-stamp and lease period
220 if (acquireLock(key, lockId).getResult() == ResultType.SUCCESS) {
221 mls = getMusicLockState(key);// get latest state
223 logger.info(EELFLoggerDelegate.applicationLogger,"Music Lock State is null");
224 return new ReturnType(ResultType.FAILURE, "Could not acquire lock, Lock State is null");
226 if (mls.getLeaseStartTime() == -1) {// set it again only if it is not set already
227 mls.setLeaseStartTime(System.currentTimeMillis());
228 mls.setLeasePeriod(leasePeriod);
229 getLockingServiceHandle().setLockState(key, mls);
231 long end = System.currentTimeMillis();
232 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire leased lock:" + (end - start) + " ms");
233 return new ReturnType(ResultType.SUCCESS, "Accquired lock");
235 long end = System.currentTimeMillis();
236 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to fail to acquire leased lock:" + (end - start) + " ms");
237 return new ReturnType(ResultType.FAILURE, "Could not acquire lock");
239 } catch (Exception e) {
240 StringWriter sw = new StringWriter();
241 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR506E] Failed to aquire lock ",ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
243 String exceptionAsString = sw.toString();
244 return new ReturnType(ResultType.FAILURE,
245 "Exception thrown in acquireLockWithLease:\n" + exceptionAsString);
249 public static ReturnType acquireLock(String key, String lockId) throws MusicLockingException {
251 * first check if I am on top. Since ids are not reusable there is no need to check
252 * lockStatus If the status is unlocked, then the above call will automatically return
255 Boolean result = false;
257 result = getLockingServiceHandle().isMyTurn(lockId);
258 } catch (MusicLockingException e2) {
259 logger.error(EELFLoggerDelegate.errorLogger,AppMessages.INVALIDLOCK + lockId + " " + e2);
260 throw new MusicLockingException();
263 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Not your turn, someone else has the lock");
265 if (!getLockingServiceHandle().lockIdExists(lockId)) {
266 logger.info(EELFLoggerDelegate.applicationLogger, "In acquire lock: this lockId doesn't exist");
267 return new ReturnType(ResultType.FAILURE, "Lockid doesn't exist");
269 } catch (MusicLockingException e) {
270 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
271 throw new MusicLockingException();
273 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: returning failure");
274 return new ReturnType(ResultType.FAILURE, "Not your turn, someone else has the lock");
278 // this is for backward compatibility where locks could also be acquired on just
279 // keyspaces or tables.
280 if (isTableOrKeySpaceLock(key)) {
281 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: A table or keyspace lock so no need to perform sync...so returning true");
282 return new ReturnType(ResultType.SUCCESS, "A table or keyspace lock so no need to perform sync...so returning true");
285 // read the lock name corresponding to the key and if the status is locked or being locked,
287 MusicLockState currentMls = null;
288 MusicLockState newMls = null;
290 currentMls = getMusicLockState(key);
291 String currentLockHolder = currentMls.getLockHolder();
292 if (lockId.equals(currentLockHolder)) {
293 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: You already have the lock!");
294 return new ReturnType(ResultType.SUCCESS, "You already have the lock!");
296 } catch (NullPointerException e) {
297 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
300 // change status to "being locked". This state transition is necessary to ensure syncing
301 // before granting the lock
302 String lockHolder = null;
303 boolean needToSyncQuorum = false;
304 if (currentMls != null)
305 needToSyncQuorum = currentMls.isNeedToSyncQuorum();
308 newMls = new MusicLockState(MusicLockState.LockStatus.BEING_LOCKED, lockHolder,
311 getLockingServiceHandle().setLockState(key, newMls);
312 } catch (MusicLockingException e1) {
313 logger.error(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
315 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to being_locked");
317 // do syncing if this was a forced lock release
318 if (needToSyncQuorum) {
319 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Since there was a forcible release, need to sync quorum!");
322 } catch (Exception e) {
323 logger.error(EELFLoggerDelegate.errorLogger,"Failed to set Lock state " + e);
327 // change status to locked
329 needToSyncQuorum = false;
330 newMls = new MusicLockState(MusicLockState.LockStatus.LOCKED, lockHolder, needToSyncQuorum);
332 getLockingServiceHandle().setLockState(key, newMls);
333 } catch (MusicLockingException e) {
334 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
336 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to locked and assigned current lock ref "
337 + lockId + " as holder");
339 return new ReturnType(result?ResultType.SUCCESS:ResultType.FAILURE, "Set lock state to locked and assigned a lock holder");
346 * @param keyspaceName
351 public boolean createKeyspace(String keyspaceName, JsonKeySpace kspObject) throws Exception {
356 private static void syncQuorum(String key) throws Exception {
357 logger.info(EELFLoggerDelegate.applicationLogger,"Performing sync operation---");
358 String[] splitString = key.split("\\.");
359 String keyspaceName = splitString[0];
360 String tableName = splitString[1];
361 String primaryKeyValue = splitString[2];
362 PreparedQueryObject selectQuery = new PreparedQueryObject();
363 PreparedQueryObject updateQuery = new PreparedQueryObject();
365 // get the primary key d
366 TableMetadata tableInfo = returnColumnMetadata(keyspaceName, tableName);
367 String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();// we only support single
369 DataType primaryKeyType = tableInfo.getPrimaryKey().get(0).getType();
370 Object cqlFormattedPrimaryKeyValue =
371 MusicUtil.convertToActualDataType(primaryKeyType, primaryKeyValue);
373 // get the row of data from a quorum
374 selectQuery.appendQueryString("SELECT * FROM " + keyspaceName + "." + tableName + " WHERE "
375 + primaryKeyName + "= ?" + ";");
376 selectQuery.addValue(cqlFormattedPrimaryKeyValue);
377 ResultSet results = null;
379 results = getDSHandle().executeCriticalGet(selectQuery);
380 // write it back to a quorum
381 Row row = results.one();
382 ColumnDefinitions colInfo = row.getColumnDefinitions();
383 int totalColumns = colInfo.size();
385 StringBuilder fieldValueString = new StringBuilder("");
386 for (Definition definition : colInfo) {
387 String colName = definition.getName();
388 if (colName.equals(primaryKeyName))
390 DataType colType = definition.getType();
391 Object valueObj = getDSHandle().getColValue(row, colName, colType);
392 Object valueString = MusicUtil.convertToActualDataType(colType, valueObj);
393 fieldValueString.append(colName + " = ?");
394 updateQuery.addValue(valueString);
395 if (counter != (totalColumns - 1))
396 fieldValueString.append(",");
397 counter = counter + 1;
399 updateQuery.appendQueryString("UPDATE " + keyspaceName + "." + tableName + " SET "
400 + fieldValueString + " WHERE " + primaryKeyName + "= ? " + ";");
401 updateQuery.addValue(cqlFormattedPrimaryKeyValue);
403 getDSHandle().executePut(updateQuery, "critical");
404 } catch (MusicServiceException | MusicQueryException e) {
405 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.QUERYERROR +""+updateQuery ,ErrorSeverity.MAJOR, ErrorTypes.QUERYERROR);
417 public static ResultSet quorumGet(PreparedQueryObject query) {
418 ResultSet results = null;
420 results = getDSHandle().executeCriticalGet(query);
421 } catch (MusicServiceException | MusicQueryException e) {
422 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.MAJOR, ErrorTypes.GENERALSERVICEERROR);
433 * @throws MusicServiceException
435 public static Map<String, HashMap<String, Object>> marshallResults(ResultSet results) throws MusicServiceException {
436 return getDSHandle().marshalData(results);
444 public static String whoseTurnIsIt(String lockName) {
447 return getLockingServiceHandle().whoseTurnIsIt("/" + lockName) + "";
448 } catch (MusicLockingException e) {
449 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKINGERROR+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
461 public static String getLockNameFromId(String lockId) {
462 StringTokenizer st = new StringTokenizer(lockId);
463 return st.nextToken("$");
466 public static void destroyLockRef(String lockId) {
467 long start = System.currentTimeMillis();
469 getLockingServiceHandle().unlockAndDeleteId(lockId);
470 } catch (MusicLockingException | NoNodeException e) {
471 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DESTROYLOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
473 long end = System.currentTimeMillis();
474 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to destroy lock reference:" + (end - start) + " ms");
477 public static MusicLockState releaseLock(String lockId, boolean voluntaryRelease) {
478 long start = System.currentTimeMillis();
480 getLockingServiceHandle().unlockAndDeleteId(lockId);
481 } catch (MusicLockingException e1) {
482 logger.error(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
483 } catch (KeeperException.NoNodeException nne) {
484 logger.error(EELFLoggerDelegate.errorLogger,"Failed to release Lock " + lockId + " " + nne);
485 MusicLockState mls = new MusicLockState("Lock doesn't exists. Release lock operation failed.");
488 String lockName = getLockNameFromId(lockId);
490 String lockHolder = null;
491 if (voluntaryRelease) {
492 mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder);
493 logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock voluntarily released for " + lockId);
495 boolean needToSyncQuorum = true;
496 mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder,
498 logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock forcibly released for " + lockId);
501 getLockingServiceHandle().setLockState(lockName, mls);
502 } catch (MusicLockingException e) {
503 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
505 long end = System.currentTimeMillis();
506 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to release lock:" + (end - start) + " ms");
510 public static void voluntaryReleaseLock(String lockId) throws MusicLockingException{
512 getLockingServiceHandle().unlockAndDeleteId(lockId);
513 } catch (KeeperException.NoNodeException e) {
522 public static void deleteLock(String lockName) {
523 long start = System.currentTimeMillis();
524 logger.info(EELFLoggerDelegate.applicationLogger,"Deleting lock for " + lockName);
526 getLockingServiceHandle().deleteLock("/" + lockName);
527 } catch (MusicLockingException e) {
528 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DELTELOCK+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
530 long end = System.currentTimeMillis();
531 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to delete lock:" + (end - start) + " ms");
541 * @throws MusicServiceException
543 public static TableMetadata returnColumnMetadata(String keyspace, String tablename) throws MusicServiceException {
544 return getDSHandle().returnColumnMetadata(keyspace, tablename);
552 public static void pureZkCreate(String nodeName) {
554 getLockingServiceHandle().getzkLockHandle().createNode(nodeName);
555 } catch (MusicLockingException e) {
556 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
565 public static void pureZkWrite(String nodeName, byte[] data) {
566 long start = System.currentTimeMillis();
567 logger.info(EELFLoggerDelegate.applicationLogger,"Performing zookeeper write to " + nodeName);
569 getLockingServiceHandle().getzkLockHandle().setNodeData(nodeName, data);
570 } catch (MusicLockingException e) {
571 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
573 logger.info(EELFLoggerDelegate.applicationLogger,"Performed zookeeper write to " + nodeName);
574 long end = System.currentTimeMillis();
575 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms");
583 public static byte[] pureZkRead(String nodeName) {
584 long start = System.currentTimeMillis();
587 data = getLockingServiceHandle().getzkLockHandle().getNodeData(nodeName);
588 } catch (MusicLockingException e) {
589 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
591 long end = System.currentTimeMillis();
592 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms");
598 // Prepared Query Additions.
602 * @param keyspaceName
607 * @throws MusicServiceException
609 public static ReturnType eventualPut(PreparedQueryObject queryObject) {
610 boolean result = false;
612 result = getDSHandle().executePut(queryObject, MusicUtil.EVENTUAL);
613 } catch (MusicServiceException | MusicQueryException ex) {
614 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
615 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() + " " + ex.getCause() + " " + ex);
616 return new ReturnType(ResultType.FAILURE, ex.getMessage());
619 return new ReturnType(ResultType.SUCCESS, "Success");
621 return new ReturnType(ResultType.FAILURE, "Failure");
627 * @param keyspaceName
634 public static ReturnType criticalPut(String keyspaceName, String tableName, String primaryKey,
635 PreparedQueryObject queryObject, String lockId, Condition conditionInfo) {
636 long start = System.currentTimeMillis();
639 MusicLockState mls = getLockingServiceHandle()
640 .getLockState(keyspaceName + "." + tableName + "." + primaryKey);
641 if (mls.getLockHolder().equals(lockId) == true) {
642 if (conditionInfo != null)
644 if (conditionInfo.testCondition() == false)
645 return new ReturnType(ResultType.FAILURE,
646 "Lock acquired but the condition is not true");
647 } catch (Exception e) {
648 return new ReturnType(ResultType.FAILURE,
649 "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
652 getDSHandle().executePut(queryObject, MusicUtil.CRITICAL);
653 long end = System.currentTimeMillis();
654 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the critical put:" + (end - start) + " ms");
655 return new ReturnType(ResultType.SUCCESS, "Update performed");
657 return new ReturnType(ResultType.FAILURE,
658 "Cannot perform operation since you are the not the lock holder");
659 } catch (MusicQueryException | MusicServiceException e) {
660 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
661 return new ReturnType(ResultType.FAILURE,
662 "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
664 }catch(MusicLockingException ex){
665 return new ReturnType(ResultType.FAILURE,ex.getMessage());
674 * @return Boolean Indicates success or failure
675 * @throws MusicServiceException
679 public static ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) throws MusicServiceException {
680 // this is mainly for some functions like keyspace creation etc which does not
681 // really need the bells and whistles of Music locking.
682 boolean result = false;
684 result = getDSHandle().executePut(queryObject, consistency);
685 } catch (MusicQueryException | MusicServiceException ex) {
686 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
687 throw new MusicServiceException(ex.getMessage());
689 return result?ResultType.SUCCESS:ResultType.FAILURE;
693 * This method performs DDL operation on cassandra.
695 * @param queryObject query object containing prepared query and values
697 * @throws MusicServiceException
699 public static ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException {
700 ResultSet results = null;
702 results = getDSHandle().executeEventualGet(queryObject);
703 } catch (MusicQueryException | MusicServiceException e) {
704 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
705 throw new MusicServiceException(e.getMessage());
711 * This method performs DDL operations on cassandra, if the the resource is available. Lock ID
712 * is used to check if the resource is free.
714 * @param keyspaceName name of the keyspace
715 * @param tableName name of the table
716 * @param primaryKey primary key value
717 * @param queryObject query object containing prepared query and values
718 * @param lockId lock ID to check if the resource is free to perform the operation.
721 public static ResultSet criticalGet(String keyspaceName, String tableName, String primaryKey,
722 PreparedQueryObject queryObject, String lockId) throws MusicServiceException {
723 ResultSet results = null;
725 MusicLockState mls = getLockingServiceHandle()
726 .getLockState(keyspaceName + "." + tableName + "." + primaryKey);
727 if (mls.getLockHolder().equals(lockId)) {
728 results = getDSHandle().executeCriticalGet(queryObject);
730 throw new MusicServiceException("YOU DO NOT HAVE THE LOCK");
731 } catch (MusicQueryException | MusicServiceException | MusicLockingException e) {
732 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
738 * This method performs DML operation on cassandra, when the lock of the dd is acquired.
740 * @param keyspaceName name of the keyspace
741 * @param tableName name of the table
742 * @param primaryKey primary key value
743 * @param queryObject query object containing prepared query and values
745 * @throws MusicLockingException
747 public static ReturnType atomicPut(String keyspaceName, String tableName, String primaryKey,
748 PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException {
750 long start = System.currentTimeMillis();
751 String key = keyspaceName + "." + tableName + "." + primaryKey;
752 String lockId = createLockReference(key);
753 long lockCreationTime = System.currentTimeMillis();
754 ReturnType lockAcqResult = acquireLock(key, lockId);
755 long lockAcqTime = System.currentTimeMillis();
756 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
757 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
758 ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
759 queryObject, lockId, conditionInfo);
760 long criticalPutTime = System.currentTimeMillis();
761 voluntaryReleaseLock(lockId);
762 long lockDeleteTime = System.currentTimeMillis();
763 String timingInfo = "|lock creation time:" + (lockCreationTime - start)
764 + "|lock accquire time:" + (lockAcqTime - lockCreationTime)
765 + "|critical put time:" + (criticalPutTime - lockAcqTime)
766 + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|";
767 criticalPutResult.setTimingInfo(timingInfo);
768 return criticalPutResult;
770 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
771 destroyLockRef(lockId);
772 return lockAcqResult;
777 * this function is mainly for the benchmarks to see the effect of lock deletion.
779 * @param keyspaceName
783 * @param conditionInfo
785 * @throws MusicLockingException
787 public static ReturnType atomicPutWithDeleteLock(String keyspaceName, String tableName,
788 String primaryKey, PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException {
790 long start = System.currentTimeMillis();
791 String key = keyspaceName + "." + tableName + "." + primaryKey;
792 String lockId = createLockReference(key);
793 long lockCreationTime = System.currentTimeMillis();
794 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
795 ReturnType lockAcqResult = acquireLock(key, lockId);
796 long lockAcqTime = System.currentTimeMillis();
797 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
798 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
799 ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
800 queryObject, lockId, conditionInfo);
801 long criticalPutTime = System.currentTimeMillis();
803 long lockDeleteTime = System.currentTimeMillis();
804 String timingInfo = "|lock creation time:" + (lockCreationTime - start)
805 + "|lock accquire time:" + (lockAcqTime - lockCreationTime)
806 + "|critical put time:" + (criticalPutTime - lockAcqTime)
807 + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|";
808 criticalPutResult.setTimingInfo(timingInfo);
809 return criticalPutResult;
811 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
813 return lockAcqResult;
821 * This method performs DDL operation on cassasndra, when the lock for the resource is acquired.
823 * @param keyspaceName name of the keyspace
824 * @param tableName name of the table
825 * @param primaryKey primary key value
826 * @param queryObject query object containing prepared query and values
828 * @throws MusicServiceException
829 * @throws MusicLockingException
831 public static ResultSet atomicGet(String keyspaceName, String tableName, String primaryKey,
832 PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException {
833 String key = keyspaceName + "." + tableName + "." + primaryKey;
834 String lockId = createLockReference(key);
835 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
836 ReturnType lockAcqResult = acquireLock(key, lockId);
837 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
838 logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
840 criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
841 voluntaryReleaseLock(lockId);
844 destroyLockRef(lockId);
845 logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
850 public static ResultSet atomicGetWithDeleteLock(String keyspaceName, String tableName, String primaryKey,
851 PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException {
852 String key = keyspaceName + "." + tableName + "." + primaryKey;
853 String lockId = createLockReference(key);
854 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
856 ReturnType lockAcqResult = acquireLock(key, lockId);
858 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
859 logger.info(EELFLoggerDelegate.applicationLogger, "acquired lock with id " + lockId);
860 ResultSet result = criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
865 logger.info(EELFLoggerDelegate.applicationLogger, "unable to acquire lock, id " + lockId);
873 * authenticate user logic
884 public static Map<String, Object> autheticateUser(String nameSpace, String userId,
885 String password, String keyspace, String aid, String operation)
887 Map<String, Object> resultMap = new HashMap<>();
889 resultMap = CachingUtil.validateRequest(nameSpace, userId, password, keyspace, aid,
891 if (!resultMap.isEmpty())
893 String isAAFApp = CachingUtil.isAAFApplication(nameSpace);
894 if(isAAFApp == null) {
895 resultMap.put("Exception", "Namespace: "+nameSpace+" doesn't exist. Please make sure ns(appName)"
896 + " is correct and Application is onboarded.");
899 boolean isAAF = Boolean.valueOf(isAAFApp);
900 if (userId == null || password == null) {
901 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
902 logger.error(EELFLoggerDelegate.errorLogger,"One or more required headers is missing. userId: " + userId
903 + " :: password: " + password);
904 resultMap.put("Exception",
905 "UserId and Password are mandatory for the operation " + operation);
908 if(!isAAF && !(operation.equals("createKeySpace"))) {
909 resultMap = CachingUtil.authenticateAIDUser(nameSpace, userId, password, keyspace);
910 if (!resultMap.isEmpty())
914 if (isAAF && nameSpace != null && userId != null && password != null) {
915 boolean isValid = true;
917 isValid = CachingUtil.authenticateAAFUser(nameSpace, userId, password, keyspace);
918 } catch (Exception e) {
919 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
920 logger.error(EELFLoggerDelegate.errorLogger,"Got exception while AAF authentication for namespace " + nameSpace);
921 resultMap.put("Exception", e.getMessage());
924 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
925 resultMap.put("Exception", "User not authenticated...");
927 if (!resultMap.isEmpty())
932 if (operation.equals("createKeySpace")) {
933 logger.info(EELFLoggerDelegate.applicationLogger,"AID is not provided. Creating new UUID for keyspace.");
934 PreparedQueryObject pQuery = new PreparedQueryObject();
935 pQuery.appendQueryString(
936 "select uuid from admin.keyspace_master where application_name=? and username=? and keyspace_name=? allow filtering");
937 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), nameSpace));
938 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
939 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),
940 MusicUtil.DEFAULTKEYSPACENAME));
943 Row rs = MusicCore.get(pQuery).one();
944 uuid = rs.getUUID("uuid").toString();
945 resultMap.put("uuid", "existing");
946 } catch (Exception e) {
947 logger.info(EELFLoggerDelegate.applicationLogger,"No UUID found in DB. So creating new UUID.");
948 uuid = CachingUtil.generateUUID();
949 resultMap.put("uuid", "new");
951 resultMap.put("aid", uuid);
961 public static Map<String, Object> validateLock(String lockName) {
962 Map<String, Object> resultMap = new HashMap<>();
963 String[] locks = lockName.split("\\.");
964 if(locks.length < 3) {
965 resultMap.put("Exception", "Invalid lock. Please make sure lock is of the type keyspaceName.tableName.primaryKey");
968 String keyspace= locks[0];
969 if(keyspace.startsWith("$"))
970 keyspace = keyspace.substring(1);
971 resultMap.put("keyspace",keyspace);