X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Forg%2Fonap%2Fmusic%2Fservice%2Fimpl%2FMusicCassaCore.java;h=0d2e3f0a0c44c698d09150da5606283a74de879a;hb=90d35b7f55d1ea3eb6ccf8218d9ac42412fd0d90;hp=07864576cec09e70d418532794645b26f97bc718;hpb=aa08eecf40d1f5f49d84cd51e7d6f91789ab6adc;p=music.git diff --git a/src/main/java/org/onap/music/service/impl/MusicCassaCore.java b/src/main/java/org/onap/music/service/impl/MusicCassaCore.java index 07864576..0d2e3f0a 100644 --- a/src/main/java/org/onap/music/service/impl/MusicCassaCore.java +++ b/src/main/java/org/onap/music/service/impl/MusicCassaCore.java @@ -30,13 +30,24 @@ import java.util.List; import java.util.Map; import java.util.StringTokenizer; +import javax.ws.rs.core.MultivaluedMap; + +import org.onap.music.datastore.Condition; import org.onap.music.datastore.MusicDataStore; import org.onap.music.datastore.MusicDataStoreHandle; import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonDelete; +import org.onap.music.datastore.jsonobjects.JsonIndex; +import org.onap.music.datastore.jsonobjects.JsonInsert; +import org.onap.music.datastore.jsonobjects.JsonKeySpace; +import org.onap.music.datastore.jsonobjects.JsonSelect; +import org.onap.music.datastore.jsonobjects.JsonTable; +import org.onap.music.datastore.jsonobjects.JsonUpdate; import org.onap.music.eelf.logging.EELFLoggerDelegate; import org.onap.music.eelf.logging.format.AppMessages; import org.onap.music.eelf.logging.format.ErrorSeverity; import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicDeadlockException; import org.onap.music.exceptions.MusicLockingException; import org.onap.music.exceptions.MusicQueryException; import org.onap.music.exceptions.MusicServiceException; @@ -55,8 +66,6 @@ import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; import com.datastax.driver.core.TableMetadata; -import org.onap.music.datastore.*; - public class MusicCassaCore implements MusicCoreService { private static CassaLockStore mLockHandle = null; @@ -108,6 +117,10 @@ public class MusicCassaCore implements MusicCoreService { } public String createLockReference(String fullyQualifiedKey, LockType locktype) throws MusicLockingException { + return createLockReference(fullyQualifiedKey, locktype, null); + } + + public String createLockReference(String fullyQualifiedKey, LockType locktype, String owner) throws MusicLockingException { String[] splitString = fullyQualifiedKey.split("\\."); String keyspace = splitString[0]; String table = splitString[1]; @@ -116,20 +129,55 @@ public class MusicCassaCore implements MusicCoreService { logger.info(EELFLoggerDelegate.applicationLogger,"Creating lock reference for lock name:" + lockName); long start = System.currentTimeMillis(); String lockReference = null; + + try { + boolean deadlock = getLockingServiceHandle().checkForDeadlock(keyspace, table, lockName, locktype, owner, false); + if (deadlock) { + MusicDeadlockException e = new MusicDeadlockException("Deadlock detected when " + owner + " tried to create lock on " + keyspace + "." + table + "." + lockName); + e.setValues(owner, keyspace, table, lockName); + throw e; + } + } catch (MusicDeadlockException e) { + //just threw this, no need to wrap it + throw e; + } catch (MusicServiceException | MusicQueryException e) { + logger.error(EELFLoggerDelegate.applicationLogger, e); + throw new MusicLockingException("Unable to check for deadlock. " + e.getMessage(), e); + } try { - lockReference = "" + getLockingServiceHandle().genLockRefandEnQueue(keyspace, table, lockName, locktype); + lockReference = "" + getLockingServiceHandle().genLockRefandEnQueue(keyspace, table, lockName, locktype, owner); } catch (MusicLockingException | MusicServiceException | MusicQueryException e) { - e.printStackTrace(); - throw new MusicLockingException("Unable to create lock reference. " + e.getMessage()); + logger.error(EELFLoggerDelegate.applicationLogger, e); + throw new MusicLockingException("Unable to create lock reference. " + e.getMessage(), e); } catch (Exception e) { logger.error(EELFLoggerDelegate.applicationLogger, e); - throw new MusicLockingException("Unable to create lock reference. " + e.getMessage()); + throw new MusicLockingException("Unable to create lock reference. " + e.getMessage(), e); } long end = System.currentTimeMillis(); logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to create lock reference:" + (end - start) + " ms"); return lockReference; } + + public ReturnType promoteLock(String lockId) throws MusicLockingException { + String[] splitString = lockId.split("\\."); + String keyspace = splitString[0].substring(1);//remove '$' + String table = splitString[1]; + String primaryKeyValue = splitString[2].substring(0, splitString[2].lastIndexOf("$")); + String localFullyQualifiedKey = lockId.substring(1, lockId.lastIndexOf("$")); + String lockRef = lockId.substring(lockId.lastIndexOf("$")+1); //lockRef is "$" to end + + logger.info(EELFLoggerDelegate.applicationLogger,"Attempting to promote lock " + lockId); + + try { + return getLockingServiceHandle().promoteLock(keyspace, table, primaryKeyValue, lockRef); + } catch (MusicServiceException e) { + throw new MusicLockingException("Unable to promote lock. ", e); + } catch (MusicQueryException e) { + throw new MusicLockingException("Unable to promote lock. ", e); + } + + } public ReturnType acquireLockWithLease(String fullyQualifiedKey, String lockReference, long leasePeriod) @@ -177,13 +225,19 @@ public class MusicCassaCore implements MusicCoreService { return new ReturnType(ResultType.FAILURE, lockId + " is not a lock holder");//not top of the lock store q } + if (getLockingServiceHandle().checkForDeadlock(keyspace, table, primaryKeyValue, lockInfo.getLocktype(), lockInfo.getOwner(), true)) { + MusicDeadlockException e = new MusicDeadlockException("Deadlock detected when " + lockInfo.getOwner() + " tried to create lock on " + keyspace + "." + table + "." + primaryKeyValue); + e.setValues(lockInfo.getOwner(), keyspace, table, primaryKeyValue); + throw e; + } + //check to see if the value of the key has to be synced in case there was a forceful release String syncTable = keyspace+".unsyncedKeys_"+table; String query = "select * from "+syncTable+" where key='"+localFullyQualifiedKey+"';"; PreparedQueryObject readQueryObject = new PreparedQueryObject(); readQueryObject.appendQueryString(query); ResultSet results = MusicDataStoreHandle.getDSHandle().executeQuorumConsistencyGet(readQueryObject); - if (results.all().size() != 0) { + if (!results.all().isEmpty()) { logger.info("In acquire lock: Since there was a forcible release, need to sync quorum!"); try { syncQuorum(keyspace, table, primaryKeyValue); @@ -311,7 +365,7 @@ public class MusicCassaCore implements MusicCoreService { String table = splitString[1]; String primaryKeyValue = splitString[2]; try { - return getLockingServiceHandle().getCurrentLockHolders(keyspace, table, primaryKeyValue); + return getLockingServiceHandle().getCurrentLockHolders(keyspace, table, primaryKeyValue); } catch (MusicLockingException | MusicServiceException | MusicQueryException e) { logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKINGERROR+fullyQualifiedKey ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); } @@ -413,6 +467,19 @@ public class MusicCassaCore implements MusicCoreService { return destroyLockRef(fullyQualifiedKey, lockReference); } + @Override + public List releaseAllLocksForOwner(String ownerId, String keyspace, String table) throws MusicLockingException, MusicServiceException, MusicQueryException { +// System.out.println("IN RELEASEALLLOCKSFOROWNER, "); + + List lockIds = getLockingServiceHandle().getAllLocksForOwner(ownerId, keyspace, table); + for (String lockId : lockIds) { +// System.out.println(" LOCKID = " + lockId); + //return "$" + keyspace + "." + table + "." + lockName + "$" + String.valueOf(lockRef); + releaseLock("$" + keyspace + "." + table + "." + lockId, true); + } + return lockIds; + } + /** * * @param lockName @@ -813,6 +880,270 @@ public class MusicCassaCore implements MusicCoreService { //deprecated return null; } + + //Methods added for ORM changes + + public ResultType createKeyspace(JsonKeySpace jsonKeySpaceObject,String consistencyInfo) + throws MusicServiceException,MusicQueryException { + ResultType result = nonKeyRelatedPut(jsonKeySpaceObject.genCreateKeyspaceQuery(), consistencyInfo); + logger.info(EELFLoggerDelegate.applicationLogger, " Keyspace Creation Process completed successfully"); + + return result; + } + + public ResultType dropKeyspace(JsonKeySpace jsonKeySpaceObject, String consistencyInfo) + throws MusicServiceException,MusicQueryException { + ResultType result = nonKeyRelatedPut(jsonKeySpaceObject.genDropKeyspaceQuery(), + consistencyInfo); + logger.info(EELFLoggerDelegate.applicationLogger, " Keyspace deletion Process completed successfully"); + return result; + } + + public ResultType createTable(JsonTable jsonTableObject, String consistencyInfo) + throws MusicServiceException, MusicQueryException { + ResultType result = null; + try { + result = createTable(jsonTableObject.getKeyspaceName(), + jsonTableObject.getTableName(), jsonTableObject.genCreateTableQuery(), consistencyInfo); + + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.UNKNOWNERROR, ErrorSeverity.WARN, + ErrorTypes.MUSICSERVICEERROR); + throw new MusicServiceException(ex.getMessage()); + } + logger.info(EELFLoggerDelegate.applicationLogger, " Table Creation Process completed successfully "); + return result; + } + + public ResultType dropTable(JsonTable jsonTableObject,String consistencyInfo) + throws MusicServiceException,MusicQueryException { + ResultType result = nonKeyRelatedPut(jsonTableObject.genDropTableQuery(), + consistencyInfo); + logger.info(EELFLoggerDelegate.applicationLogger, " Table deletion Process completed successfully "); + + return result; + } + + @Override + public ResultType createIndex(JsonIndex jsonIndexObject, String consistencyInfo) + throws MusicServiceException, MusicQueryException{ + ResultType result = nonKeyRelatedPut(jsonIndexObject.genCreateIndexQuery(), + consistencyInfo); + + logger.info(EELFLoggerDelegate.applicationLogger, " Index creation Process completed successfully "); + return result; + } + + /** + * This method performs DDL operation on cassandra. + * + * @param queryObject query object containing prepared query and values + * @return ResultSet + * @throws MusicServiceException + */ + public ResultSet select(JsonSelect jsonSelect, MultivaluedMap rowParams) + throws MusicServiceException, MusicQueryException { + ResultSet results = null; + try { + results = get(jsonSelect.genSelectQuery(rowParams)); + } catch (MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + throw new MusicServiceException(e.getMessage()); + } + return results; + } + + /** + * Select Critical + */ + public ResultSet selectCritical(JsonInsert jsonInsertObj, MultivaluedMap rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException { + + ResultSet results = null; + String consistency = ""; + if(null != jsonInsertObj && null != jsonInsertObj.getConsistencyInfo()) { + consistency = jsonInsertObj.getConsistencyInfo().get("type"); + } + + String lockId = jsonInsertObj.getConsistencyInfo().get("lockId"); + + PreparedQueryObject queryObject = jsonInsertObj.genSelectCriticalPreparedQueryObj(rowParams); + + if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + results = criticalGet(jsonInsertObj.getKeyspaceName(), jsonInsertObj.getTableName(), + jsonInsertObj.getPrimaryKeyVal(), queryObject,lockId); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + results = atomicGet(jsonInsertObj.getKeyspaceName(), jsonInsertObj.getTableName(), + jsonInsertObj.getPrimaryKeyVal(), queryObject); + } + + return results; + } + + /** + * this is insert row into Table + */ + public ReturnType insertIntoTable(JsonInsert jsonInsertObj) + throws MusicLockingException, MusicQueryException, MusicServiceException { + + String consistency = ""; + if(null != jsonInsertObj && null != jsonInsertObj.getConsistencyInfo()) { + consistency = jsonInsertObj.getConsistencyInfo().get("type"); + } + + ReturnType result = null; + + try { + PreparedQueryObject queryObj = null; + queryObj = jsonInsertObj.genInsertPreparedQueryObj(); + + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) { + result = eventualPut(jsonInsertObj.genInsertPreparedQueryObj()); + } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = jsonInsertObj.getConsistencyInfo().get("lockId"); + if(lockId == null) { + logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); + return new ReturnType(ResultType.FAILURE, "LockId cannot be null. Create lock " + + "and acquire lock or use ATOMIC instead of CRITICAL"); + } + result = criticalPut(jsonInsertObj.getKeyspaceName(), + jsonInsertObj.getTableName(), jsonInsertObj.getPrimaryKeyVal(), jsonInsertObj.genInsertPreparedQueryObj(), lockId,null); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + result = atomicPut(jsonInsertObj.getKeyspaceName(), jsonInsertObj.getTableName(), + jsonInsertObj.getPrimaryKeyVal(), jsonInsertObj.genInsertPreparedQueryObj(), null); + } + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity + .WARN, ErrorTypes.MUSICSERVICEERROR, ex); + return new ReturnType(ResultType.FAILURE, ex.getMessage()); + } + + return result; + } + + /** + * This is insert row into Table + */ + public ReturnType updateTable(JsonUpdate jsonUpdateObj, MultivaluedMap rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException { + + ReturnType result = null; + String consistency = ""; + if(null != jsonUpdateObj && null != jsonUpdateObj.getConsistencyInfo()) { + consistency = jsonUpdateObj.getConsistencyInfo().get("type"); + } + PreparedQueryObject queryObject = jsonUpdateObj.genUpdatePreparedQueryObj(rowParams); + + Condition conditionInfo; + if (jsonUpdateObj.getConditions() == null) { + conditionInfo = null; + } else { + // to avoid parsing repeatedly, just send the select query to obtain row + PreparedQueryObject selectQuery = new PreparedQueryObject(); + selectQuery.appendQueryString("SELECT * FROM " + jsonUpdateObj.getKeyspaceName() + "." + jsonUpdateObj.getTableName() + " WHERE " + + jsonUpdateObj.getRowIdString() + ";"); + selectQuery.addValue(jsonUpdateObj.getPrimarKeyValue()); + conditionInfo = new Condition(jsonUpdateObj.getConditions(), selectQuery); + } + + + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) { + result = eventualPut(queryObject); + } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = jsonUpdateObj.getConsistencyInfo().get("lockId"); + if(lockId == null) { + logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); + + return new ReturnType(ResultType.FAILURE, "LockId cannot be null. Create lock " + + "and acquire lock or use ATOMIC instead of CRITICAL"); + } + result = criticalPut(jsonUpdateObj.getKeyspaceName(), jsonUpdateObj.getTableName(), jsonUpdateObj.getPrimarKeyValue(), + queryObject, lockId, conditionInfo); + } else if (consistency.equalsIgnoreCase("atomic_delete_lock")) { + // this function is mainly for the benchmarks + try { + result = atomicPutWithDeleteLock(jsonUpdateObj.getKeyspaceName(), jsonUpdateObj.getTableName(), + jsonUpdateObj.getPrimarKeyValue(), queryObject, conditionInfo); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, + ErrorTypes.GENERALSERVICEERROR, e); + throw new MusicLockingException(AppMessages.UNKNOWNERROR.toString()); + + } + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + try { + result = atomicPut(jsonUpdateObj.getKeyspaceName(), jsonUpdateObj.getTableName(), jsonUpdateObj.getPrimarKeyValue(), + queryObject, conditionInfo); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR, e); + throw new MusicLockingException(AppMessages.UNKNOWNERROR.toString()); + } + } else if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) { + try { + result = eventualPut_nb(queryObject, jsonUpdateObj.getKeyspaceName(), + jsonUpdateObj.getTableName(), jsonUpdateObj.getPrimarKeyValue()); + }catch (Exception e) { + return new ReturnType(ResultType.FAILURE, e.getMessage()); + } + + } + + return result; + } + + /** + * This method is for Delete From Table + */ + public ReturnType deleteFromTable(JsonDelete jsonDeleteObj, MultivaluedMap rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException { + + ReturnType result = null; + String consistency = ""; + if(null != jsonDeleteObj && null != jsonDeleteObj.getConsistencyInfo()) { + consistency = jsonDeleteObj.getConsistencyInfo().get("type"); + } + PreparedQueryObject queryObject = jsonDeleteObj.genDeletePreparedQueryObj(rowParams); + + // get the conditional, if any + Condition conditionInfo; + if (jsonDeleteObj.getConditions() == null) { + conditionInfo = null; + } else { + // to avoid parsing repeatedly, just send the select query to obtain row + PreparedQueryObject selectQuery = new PreparedQueryObject(); + selectQuery.appendQueryString("SELECT * FROM " + jsonDeleteObj.getKeyspaceName() + "." + jsonDeleteObj.getTableName() + " WHERE " + + jsonDeleteObj.getRowIdString() + ";"); + selectQuery.addValue(jsonDeleteObj.getPrimarKeyValue()); + conditionInfo = new Condition(jsonDeleteObj.getConditions(), selectQuery); + } + + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) + result = eventualPut(queryObject); + else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = jsonDeleteObj.getConsistencyInfo().get("lockId"); + if(lockId == null) { + logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); + + return new ReturnType(ResultType.FAILURE, "LockId cannot be null. Create lock " + + "and acquire lock or use ATOMIC instead of CRITICAL"); + } + result = criticalPut(jsonDeleteObj.getKeyspaceName(), + jsonDeleteObj.getTableName(), jsonDeleteObj.getPrimarKeyValue(), + queryObject, lockId, conditionInfo); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + result = atomicPut(jsonDeleteObj.getKeyspaceName(), + jsonDeleteObj.getTableName(), jsonDeleteObj.getPrimarKeyValue(), + queryObject, conditionInfo); + } else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) { + result = eventualPut_nb(queryObject, jsonDeleteObj.getKeyspaceName(), + jsonDeleteObj.getTableName(), jsonDeleteObj.getPrimarKeyValue()); + } + + return result; + } }