Merge "Include owner in createLockRef"
authorBharath Balasubramanian <bharathb@research.att.com>
Thu, 10 Oct 2019 20:08:23 +0000 (20:08 +0000)
committerGerrit Code Review <gerrit@onap.org>
Thu, 10 Oct 2019 20:08:23 +0000 (20:08 +0000)
1  2 
music-core/src/main/java/org/onap/music/main/MusicCore.java
music-core/src/main/java/org/onap/music/service/MusicCoreService.java
music-core/src/main/java/org/onap/music/service/impl/MusicCassaCore.java

@@@ -81,12 -81,16 +81,16 @@@ public class MusicCore 
          return musicCore.acquireLockWithLease(key, lockId, leasePeriod);
      }
  
 -    public static String createLockReference(String fullyQualifiedKey) throws MusicLockingException {
 -        return musicCore.createLockReference(fullyQualifiedKey);
 +    public static String createLockReferenceAtomic(String fullyQualifiedKey) throws MusicLockingException {
 +        return musicCore.createLockReferenceAtomic(fullyQualifiedKey);
      }
+     
+     public static String createLockReference(String fullyQualifiedKey, String owner) throws MusicLockingException {
+         return musicCore.createLockReference(fullyQualifiedKey, owner);
+     }
  
 -    public static String createLockReference(String fullyQualifiedKey, LockType locktype) throws MusicLockingException {
 -        return musicCore.createLockReference(fullyQualifiedKey, locktype);
 +    public static String createLockReferenceAtomic(String fullyQualifiedKey, LockType locktype) throws MusicLockingException {
 +        return musicCore.createLockReferenceAtomic(fullyQualifiedKey, locktype);
      }
  
      public static String createLockReference(String fullyQualifiedKey, LockType locktype, String owner) throws MusicLockingException {
@@@ -89,8 -89,15 +89,15 @@@ public interface MusicCoreService 
       * @param fullyQualifiedKey the key to create a lock on
       * @see {@link #creatLockReference(String, LockType)}
       */
 -    public String createLockReference(String fullyQualifiedKey) throws MusicLockingException; // lock name
 +    public String createLockReferenceAtomic(String fullyQualifiedKey) throws MusicLockingException; // lock name
  
+     /**
+      * Create a lock ref in the music lock store
+      * @param fullyQualifiedKey the key to create a lock on
+      * @param owner the owner of the lock, for deadlock prevention
+      */
+     public String createLockReference(String fullyQualifiedKey, String owner) throws MusicLockingException;
+     
      /**
       * Create a lock ref in the music lock store
       * @param fullyQualifiedKey the key to create a lock on
@@@ -113,81 -112,15 +113,84 @@@ public class MusicCassaCore implements 
          return mLockHandle;
      }
  
 -    public String createLockReference(String fullyQualifiedKey) throws MusicLockingException {
 -        return createLockReference(fullyQualifiedKey, LockType.WRITE);
 +    public String createLockReferenceAtomic(String fullyQualifiedKey) throws MusicLockingException {
 +        return createLockReferenceAtomic(fullyQualifiedKey, LockType.WRITE);
      }
+     public String createLockReference(String fullyQualifiedKey, String owner) throws MusicLockingException {
+         return createLockReference(fullyQualifiedKey, LockType.WRITE, owner);
+     }
  
 -    public String createLockReference(String fullyQualifiedKey, LockType locktype) throws MusicLockingException {
 -        return createLockReference(fullyQualifiedKey, locktype, null);
 +    /**
 +     * This will be called for Atomic calls
 +     * 
 +     */
 +    public String createLockReferenceAtomic(String fullyQualifiedKey, LockType locktype) throws MusicLockingException {
 +        String[] splitString = fullyQualifiedKey.split("\\.");
 +        if (splitString.length < 3) {
 +            throw new MusicLockingException("Missing or incorrect lock details. Check table or key name.");
 +        }
 +        String keyspace = splitString[0];
 +        String table = splitString[1];
 +        String lockName = splitString[2];
 +
 +        logger.info(EELFLoggerDelegate.applicationLogger,"Creating lock reference for lock name:" + lockName);
 +        long start = 0L;
 +        long end = 0L;
 +        String lockReference = null;
 +        LockObject peek = null;
 +
 +        /** Lets check for an existing lock. 
 +         * This will allow us to limit the amount of requests going forward.
 +         */
 +        start = System.currentTimeMillis();
 +        try {
 +            peek = getLockingServiceHandle().peekLockQueue(keyspace, table, lockName);
 +        } catch (MusicServiceException | MusicQueryException e) {
 +            //logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(),e);
 +            throw new MusicLockingException("Error getting lockholder info for key [" + lockName +"]:" + e.getMessage());
 +        }
 +        
 +        if(peek!=null && (peek.getLocktype()!=null && peek.getLocktype().equals(LockType.WRITE)) && peek.getAcquireTime()!=null && peek.getLockRef()!=null) {
 +            long currentTime = System.currentTimeMillis();
 +            if((currentTime-Long.parseLong(peek.getAcquireTime()))<MusicUtil.getDefaultLockLeasePeriod()){
 +                //logger.info(EELFLoggerDelegate.applicationLogger,"Lock holder exists and lease not expired. Please try again for key="+lockName);
 +                throw new MusicLockingException("Unable to create lock reference for key [" + lockName + "]. Please try again.");
 +            }
 +        }
 +        end = System.currentTimeMillis();
 +        logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to check for lock reference for key [" + lockName + "]:" + (end - start) + " ms");
 +
 +        start = System.currentTimeMillis();
 +        /* We are Creating a Thread safe set and adding the key to the set. 
 +        * if a key exists then it wil be passed over and not go to the lock creation. 
 +        * If a key doesn't exist then it will set the value in the set and continue to create a lock. 
 +        *
 +        * This will ensure that no 2 threads using the same key will be able to try to create a lock
 +        * This wil in turn squash the amout of LWT Chatter in Cassandra an reduce the amount of
 +        * WriteTimeoutExceptions being experiences on single keys.
 +        */
 +        if ( set.add(fullyQualifiedKey)) {
 +            try {
 +                lockReference = "" + getLockingServiceHandle().genLockRefandEnQueue(keyspace, table, lockName, locktype,null);
 +                set.remove(fullyQualifiedKey);
 +            } catch (MusicLockingException | MusicServiceException | MusicQueryException e) {
 +                set.remove(fullyQualifiedKey);
 +                throw new MusicLockingException(e.getMessage());
 +            } catch (Exception e) {
 +                set.remove(fullyQualifiedKey);
 +                e.printStackTrace();
 +                logger.error(EELFLoggerDelegate.applicationLogger,"Exception in creatLockEnforced:"+ e.getMessage(),e);
 +                throw new MusicLockingException("Unable to create lock reference for key [" + lockName + "]. " + e.getMessage());
 +            }
 +        } else {
 +            throw new MusicLockingException("Unable to create lock reference for key [" + lockName + "]. Please try again.");
 +        }
 +        end = System.currentTimeMillis();
 +        logger.info(EELFLoggerDelegate.debugLogger,"### Set = " + set);
 +        logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to create lock reference  for key [" + lockName + "]:" + (end - start) + " ms");
 +        return lockReference;
 +
 +        //return createLockReference(fullyQualifiedKey, locktype, null);
      }
  
      public String createLockReference(String fullyQualifiedKey, LockType locktype, String owner) throws MusicLockingException {