Sonar Fixes to increate Coverage on Unit tests
[music.git] / src / main / java / org / onap / music / main / MusicCore.java
1 /*
2  * ============LICENSE_START==========================================
3  * org.onap.music
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
10  * 
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  * 
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.
18  * 
19  * ============LICENSE_END=============================================
20  * ====================================================================
21  */
22 package org.onap.music.main;
23
24
25 import java.io.StringWriter;
26 import java.util.HashMap;
27 import java.util.Map;
28 import java.util.StringTokenizer;
29
30 import org.onap.music.datastore.MusicDataStore;
31 import org.onap.music.datastore.PreparedQueryObject;
32 import org.onap.music.datastore.jsonobjects.JsonKeySpace;
33 import org.onap.music.eelf.logging.EELFLoggerDelegate;
34 // import org.onap.music.eelf.logging.EELFLoggerDelegate;
35 import org.onap.music.exceptions.MusicLockingException;
36 import org.onap.music.exceptions.MusicQueryException;
37 import org.onap.music.exceptions.MusicServiceException;
38 import org.onap.music.lockingservice.MusicLockState;
39 import org.onap.music.lockingservice.MusicLockState.LockStatus;
40 import org.onap.music.lockingservice.MusicLockingService;
41
42 import com.datastax.driver.core.ColumnDefinitions;
43 import com.datastax.driver.core.ColumnDefinitions.Definition;
44 import com.datastax.driver.core.DataType;
45 import com.datastax.driver.core.ResultSet;
46 import com.datastax.driver.core.Row;
47 import com.datastax.driver.core.TableMetadata;
48
49 /**
50  * This class .....
51  * 
52  *
53  */
54 public class MusicCore {
55
56     public static MusicLockingService mLockHandle = null;
57     public static MusicDataStore mDstoreHandle = null;
58     private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicCore.class);
59
60     public static class Condition {
61         Map<String, Object> conditions;
62         PreparedQueryObject selectQueryForTheRow;
63
64         public Condition(Map<String, Object> conditions, PreparedQueryObject selectQueryForTheRow) {
65             this.conditions = conditions;
66             this.selectQueryForTheRow = selectQueryForTheRow;
67         }
68
69         public boolean testCondition() throws Exception {
70             // first generate the row
71             ResultSet results = quorumGet(selectQueryForTheRow);
72             Row row = results.one();
73             return getDSHandle().doesRowSatisfyCondition(row, conditions);
74         }
75     }
76
77
78     public static MusicLockingService getLockingServiceHandle() throws MusicLockingException {
79         logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring lock store handle");
80         long start = System.currentTimeMillis();
81
82         if (mLockHandle == null) {
83             try {
84                 mLockHandle = new MusicLockingService();
85             } catch (Exception e) {
86                 logger.error(EELFLoggerDelegate.errorLogger,"Failed to aquire Locl store handle" + e.getMessage());
87                 throw new MusicLockingException("Failed to aquire Locl store handle " + e);
88             }
89         }
90         long end = System.currentTimeMillis();
91         logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire lock store handle:" + (end - start) + " ms");
92         return mLockHandle;
93     }
94
95     /**
96      * 
97      * @param remoteIp
98      * @return
99      */
100     public static MusicDataStore getDSHandle(String remoteIp) {
101         logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring data store handle");
102         long start = System.currentTimeMillis();
103         if (mDstoreHandle == null) {
104             mDstoreHandle = new MusicDataStore(remoteIp);
105         }
106         long end = System.currentTimeMillis();
107         logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms");
108         return mDstoreHandle;
109     }
110
111     /**
112      * 
113      * @return
114      * @throws MusicServiceException 
115      */
116     public static MusicDataStore getDSHandle() throws MusicServiceException {
117         logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring data store handle");
118         long start = System.currentTimeMillis();
119         if (mDstoreHandle == null) {
120             mDstoreHandle = new MusicDataStore();
121         }
122         if(mDstoreHandle.getSession() == null) {
123                 String message = "Connection to Cassandra has not been enstablished."
124                                 + " Please check connection properites and reboot.";
125                 logger.info(EELFLoggerDelegate.applicationLogger, message);
126             throw new MusicServiceException(message);
127         }
128         long end = System.currentTimeMillis();
129         logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms");
130         return mDstoreHandle;
131     }
132
133     public static String createLockReference(String lockName) {
134         logger.info(EELFLoggerDelegate.applicationLogger,"Creating lock reference for lock name:" + lockName);
135         long start = System.currentTimeMillis();
136         String lockId = null;
137         try {
138             lockId = getLockingServiceHandle().createLockId("/" + lockName);
139         } catch (MusicLockingException e) {
140             logger.error(EELFLoggerDelegate.errorLogger,"Failed to create Lock Reference " + lockName);
141         }
142         long end = System.currentTimeMillis();
143         logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to create lock reference:" + (end - start) + " ms");
144         return lockId;
145     }
146
147     /**
148      * 
149      * @param key
150      * @return
151      */
152     public static boolean isTableOrKeySpaceLock(String key) {
153         String[] splitString = key.split("\\.");
154         if (splitString.length > 2)
155             return false;
156         else
157             return true;
158     }
159
160     /**
161      * 
162      * @param key
163      * @return
164      */
165     public static MusicLockState getMusicLockState(String key) {
166         long start = System.currentTimeMillis();
167         try {
168             String[] splitString = key.split("\\.");
169             String keyspaceName = splitString[0];
170             String tableName = splitString[1];
171             String primaryKey = splitString[2];
172             MusicLockState mls;
173             String lockName = keyspaceName + "." + tableName + "." + primaryKey;
174             mls = getLockingServiceHandle().getLockState(lockName);
175             long end = System.currentTimeMillis();
176             logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to get lock state:" + (end - start) + " ms");
177             return mls;
178         } catch (NullPointerException | MusicLockingException e) {
179             logger.error(EELFLoggerDelegate.errorLogger,"No lock object exists as of now.." + e);
180         }
181         return null;
182     }
183
184     public static ReturnType acquireLockWithLease(String key, String lockId, long leasePeriod) {
185         try {
186             long start = System.currentTimeMillis();
187             /* check if the current lock has exceeded its lease and if yes, release that lock */
188             MusicLockState mls = getMusicLockState(key);
189             if (mls != null) {
190                 if (mls.getLockStatus().equals(LockStatus.LOCKED)) {
191                     logger.info(EELFLoggerDelegate.applicationLogger,"The current lock holder for " + key + " is " + mls.getLockHolder()
192                                     + ". Checking if it has exceeded lease");
193                     long currentLockPeriod = System.currentTimeMillis() - mls.getLeaseStartTime();
194                     long currentLeasePeriod = mls.getLeasePeriod();
195                     if (currentLockPeriod > currentLeasePeriod) {
196                         logger.info(EELFLoggerDelegate.applicationLogger,"Lock period " + currentLockPeriod
197                                         + " has exceeded lease period " + currentLeasePeriod);
198                         boolean voluntaryRelease = false;
199                         String currentLockHolder = mls.getLockHolder();
200                         mls = releaseLock(currentLockHolder, voluntaryRelease);
201                     }
202                 }
203             } else
204                 logger.debug("There is no lock state object for " + key);
205
206             /*
207              * call the traditional acquire lock now and if the result returned is true, set the
208              * begin time-stamp and lease period
209              */
210             if (acquireLock(key, lockId).getResult() == ResultType.SUCCESS) {
211                 mls = getMusicLockState(key);// get latest state
212                 if (mls.getLeaseStartTime() == -1) {// set it again only if it is not set already
213                     mls.setLeaseStartTime(System.currentTimeMillis());
214                     mls.setLeasePeriod(leasePeriod);
215                     getLockingServiceHandle().setLockState(key, mls);
216                 }
217                 long end = System.currentTimeMillis();
218                 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire leased lock:" + (end - start) + " ms");
219                 return new ReturnType(ResultType.SUCCESS, "Accquired lock");
220             } else {
221                 long end = System.currentTimeMillis();
222                 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to fail to acquire leased lock:" + (end - start) + " ms");
223                 return new ReturnType(ResultType.FAILURE, "Could not acquire lock");
224             }
225         } catch (Exception e) {
226             StringWriter sw = new StringWriter();
227             logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
228             String exceptionAsString = sw.toString();
229             return new ReturnType(ResultType.FAILURE,
230                             "Exception thrown in acquireLockWithLease:\n" + exceptionAsString);
231         }
232     }
233
234     public static ReturnType acquireLock(String key, String lockId) {
235         /*
236          * first check if I am on top. Since ids are not reusable there is no need to check
237          * lockStatus If the status is unlocked, then the above call will automatically return
238          * false.
239          */
240         Boolean result = false;
241         try {
242             result = getLockingServiceHandle().isMyTurn(lockId);
243         } catch (MusicLockingException e2) {
244             logger.error(EELFLoggerDelegate.errorLogger,"Failed to aquireLock lockId " + lockId + " " + e2);
245         }
246         if (result == false) {
247             logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Not your turn, someone else has the lock");
248             try {
249                                 if (!getLockingServiceHandle().lockIdExists(lockId)) {
250                                         logger.info(EELFLoggerDelegate.applicationLogger, "In acquire lock: this lockId doesn't exist");
251                                         return new ReturnType(ResultType.FAILURE, "Lockid doesn't exist");
252                                 }
253                         } catch (MusicLockingException e) {
254                                 logger.error(EELFLoggerDelegate.errorLogger,"Failed to check if lockid exists - lockId " + lockId + " " + e);
255                         }
256             logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: returning failure");
257             return new ReturnType(ResultType.FAILURE, "Not your turn, someone else has the lock");
258         }
259
260
261         // this is for backward compatibility where locks could also be acquired on just
262         // keyspaces or tables.
263         if (isTableOrKeySpaceLock(key) == true) {
264             logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: A table or keyspace lock so no need to perform sync...so returning true");
265             return new ReturnType(ResultType.SUCCESS, "A table or keyspace lock so no need to perform sync...so returning true");
266         }
267
268         // read the lock name corresponding to the key and if the status is locked or being locked,
269         // then return false
270         MusicLockState currentMls = null;
271         MusicLockState newMls = null;
272         try {
273             currentMls = getMusicLockState(key);
274             String currentLockHolder = currentMls.getLockHolder();
275             if (lockId.equals(currentLockHolder)) {
276                 logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: You already have the lock!");
277                 return new ReturnType(ResultType.SUCCESS, "You already have the lock!");
278             }
279         } catch (NullPointerException e) {
280             logger.error(EELFLoggerDelegate.errorLogger,"In acquire lock:No one has tried to acquire the lock yet..");
281         }
282
283         // change status to "being locked". This state transition is necessary to ensure syncing
284         // before granting the lock
285         String lockHolder = null;
286         boolean needToSyncQuorum = false;
287         if (currentMls != null)
288             needToSyncQuorum = currentMls.isNeedToSyncQuorum();
289
290
291         newMls = new MusicLockState(MusicLockState.LockStatus.BEING_LOCKED, lockHolder,
292                         needToSyncQuorum);
293         try {
294             getLockingServiceHandle().setLockState(key, newMls);
295         } catch (MusicLockingException e1) {
296             logger.error(EELFLoggerDelegate.errorLogger,"Failed to set Lock state " + key + " " + e1);
297         }
298         logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to being_locked");
299
300         // do syncing if this was a forced lock release
301         if (needToSyncQuorum) {
302             logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Since there was a forcible release, need to sync quorum!");
303             try {
304               syncQuorum(key);
305             } catch (Exception e) {
306               logger.error(EELFLoggerDelegate.errorLogger,"Failed to set Lock state " + e);
307             }
308         }
309
310         // change status to locked
311         lockHolder = lockId;
312         needToSyncQuorum = false;
313         newMls = new MusicLockState(MusicLockState.LockStatus.LOCKED, lockHolder, needToSyncQuorum);
314         try {
315             getLockingServiceHandle().setLockState(key, newMls);
316         } catch (MusicLockingException e) {
317             logger.error(EELFLoggerDelegate.errorLogger,"Failed to set Lock state " + key + " " + e);
318         }
319         logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to locked and assigned current lock ref "
320                         + lockId + " as holder");
321         
322         return new ReturnType(result?ResultType.SUCCESS:ResultType.FAILURE, "Set lock state to locked and assigned a lock holder");
323     }
324
325
326
327     /**
328      * 
329      * @param keyspaceName
330      * @param kspObject
331      * @return
332      * @throws Exception
333      */
334     public boolean createKeyspace(String keyspaceName, JsonKeySpace kspObject) throws Exception {
335         return true;
336     }
337
338
339     private static void syncQuorum(String key) throws Exception {
340         logger.info(EELFLoggerDelegate.applicationLogger,"Performing sync operation---");
341         String[] splitString = key.split("\\.");
342         String keyspaceName = splitString[0];
343         String tableName = splitString[1];
344         String primaryKeyValue = splitString[2];
345         PreparedQueryObject selectQuery = new PreparedQueryObject();
346         PreparedQueryObject updateQuery = new PreparedQueryObject();
347
348         // get the primary key d
349         TableMetadata tableInfo = returnColumnMetadata(keyspaceName, tableName);
350         String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();// we only support single
351                                                                            // primary key
352         DataType primaryKeyType = tableInfo.getPrimaryKey().get(0).getType();
353         Object cqlFormattedPrimaryKeyValue =
354                         MusicUtil.convertToActualDataType(primaryKeyType, primaryKeyValue);
355
356         // get the row of data from a quorum
357         selectQuery.appendQueryString("SELECT *  FROM " + keyspaceName + "." + tableName + " WHERE "
358                         + primaryKeyName + "= ?" + ";");
359         selectQuery.addValue(cqlFormattedPrimaryKeyValue);
360         // String selectQuery = "SELECT * FROM "+keyspaceName+"."+tableName+ " WHERE
361         // "+primaryKeyName+"="+cqlFormattedPrimaryKeyValue+";";
362         ResultSet results = null;
363         try {
364             results = getDSHandle().executeCriticalGet(selectQuery);
365             // write it back to a quorum
366             Row row = results.one();
367             ColumnDefinitions colInfo = row.getColumnDefinitions();
368             int totalColumns = colInfo.size();
369             int counter = 1;
370             // String fieldValueString="";
371             StringBuilder fieldValueString = new StringBuilder("");
372             for (Definition definition : colInfo) {
373                 String colName = definition.getName();
374                 if (colName.equals(primaryKeyName))
375                     continue;
376                 DataType colType = definition.getType();
377                 Object valueObj = getDSHandle().getColValue(row, colName, colType);
378                 Object valueString = MusicUtil.convertToActualDataType(colType, valueObj);
379                 // fieldValueString = fieldValueString+ colName+"="+valueString;
380                 fieldValueString.append(colName + " = ?");
381                 updateQuery.addValue(valueString);
382                 if (counter != (totalColumns - 1))
383                     fieldValueString.append(",");
384                 counter = counter + 1;
385             }
386             updateQuery.appendQueryString("UPDATE " + keyspaceName + "." + tableName + " SET "
387                             + fieldValueString + " WHERE " + primaryKeyName + "= ? " + ";");
388             updateQuery.addValue(cqlFormattedPrimaryKeyValue);
389             // String updateQuery = "UPDATE "+keyspaceName+"."+tableName+" SET "+fieldValueString+"
390             // WHERE "+primaryKeyName+"="+cqlFormattedPrimaryKeyValue+";";
391
392             getDSHandle().executePut(updateQuery, "critical");
393         } catch (MusicServiceException | MusicQueryException e) {
394             logger.error(EELFLoggerDelegate.errorLogger,"Failed to execute update query " + updateQuery + " " + e);
395         }
396     }
397
398
399
400
401     /**
402      * 
403      * @param query
404      * @return ResultSet
405      */
406     public static ResultSet quorumGet(PreparedQueryObject query) {
407         ResultSet results = null;
408         try {
409             results = getDSHandle().executeCriticalGet(query);
410         } catch (MusicServiceException | MusicQueryException e) {
411             logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
412         }
413         return results;
414
415     }
416
417     /**
418      * 
419      * @param results
420      * @return
421      * @throws MusicServiceException 
422      */
423     public static Map<String, HashMap<String, Object>> marshallResults(ResultSet results) throws MusicServiceException {
424         return getDSHandle().marshalData(results);
425     }
426
427     /**
428      * 
429      * @param lockName
430      * @return
431      */
432     public static String whoseTurnIsIt(String lockName) {
433
434         try {
435             return getLockingServiceHandle().whoseTurnIsIt("/" + lockName) + "";
436         } catch (MusicLockingException e) {
437             logger.error(EELFLoggerDelegate.errorLogger,"Failed whoseTurnIsIt  " + lockName + " " + e);
438         }
439         return null;
440
441
442     }
443
444     /**
445      * 
446      * @param lockId
447      * @return
448      */
449     public static String getLockNameFromId(String lockId) {
450         StringTokenizer st = new StringTokenizer(lockId);
451         return st.nextToken("$");
452     }
453
454     public static void destroyLockRef(String lockId) {
455         long start = System.currentTimeMillis();
456         try {
457             getLockingServiceHandle().unlockAndDeleteId(lockId);
458         } catch (MusicLockingException e) {
459             logger.error(EELFLoggerDelegate.errorLogger,"Failed to Destroy Lock Ref  " + lockId + " " + e);
460         }
461         long end = System.currentTimeMillis();
462         logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to destroy lock reference:" + (end - start) + " ms");
463     }
464
465     public static MusicLockState releaseLock(String lockId, boolean voluntaryRelease) {
466         long start = System.currentTimeMillis();
467         try {
468             getLockingServiceHandle().unlockAndDeleteId(lockId);
469         } catch (MusicLockingException e1) {
470             logger.error(EELFLoggerDelegate.errorLogger,"Failed to release Lock " + lockId + " " + e1);
471         }
472         String lockName = getLockNameFromId(lockId);
473         MusicLockState mls;
474         String lockHolder = null;
475         if (voluntaryRelease) {
476             mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder);
477             logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock voluntarily released for " + lockId);
478         } else {
479             boolean needToSyncQuorum = true;
480             mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder,
481                             needToSyncQuorum);
482             logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock forcibly released for " + lockId);
483         }
484         try {
485             getLockingServiceHandle().setLockState(lockName, mls);
486         } catch (MusicLockingException e) {
487             logger.error(EELFLoggerDelegate.errorLogger,"Failed to release Lock " + lockName + " " + e);
488         }
489         long end = System.currentTimeMillis();
490         logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to release lock:" + (end - start) + " ms");
491         return mls;
492     }
493     
494     public static  void  voluntaryReleaseLock(String lockId) throws MusicLockingException{
495                 getLockingServiceHandle().unlockAndDeleteId(lockId);
496         }
497
498     /**
499      * 
500      * @param lockName
501      */
502     public static void deleteLock(String lockName) {
503         long start = System.currentTimeMillis();
504         logger.info(EELFLoggerDelegate.applicationLogger,"Deleting lock for " + lockName);
505         try {
506             getLockingServiceHandle().deleteLock("/" + lockName);
507         } catch (MusicLockingException e) {
508             logger.error(EELFLoggerDelegate.errorLogger,"Failed to Delete Lock " + lockName + " " + e);
509         }
510         long end = System.currentTimeMillis();
511         logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to delete lock:" + (end - start) + " ms");
512     }
513
514
515
516     /**
517      * 
518      * @param keyspace
519      * @param tablename
520      * @return
521      * @throws MusicServiceException 
522      */
523     public static TableMetadata returnColumnMetadata(String keyspace, String tablename) throws MusicServiceException {
524         return getDSHandle().returnColumnMetadata(keyspace, tablename);
525     }
526
527
528     /**
529      * 
530      * @param nodeName
531      */
532     public static void pureZkCreate(String nodeName) {
533         try {
534             getLockingServiceHandle().getzkLockHandle().createNode(nodeName);
535         } catch (MusicLockingException e) {
536             logger.error(EELFLoggerDelegate.errorLogger,"Failed to get ZK Lock Handle " + e);
537         }
538     }
539
540     /**
541      * 
542      * @param nodeName
543      * @param data
544      */
545     public static void pureZkWrite(String nodeName, byte[] data) {
546         long start = System.currentTimeMillis();
547         logger.info(EELFLoggerDelegate.applicationLogger,"Performing zookeeper write to " + nodeName);
548         try {
549             getLockingServiceHandle().getzkLockHandle().setNodeData(nodeName, data);
550         } catch (MusicLockingException e) {
551             logger.error(EELFLoggerDelegate.errorLogger,"Failed to get ZK Lock Handle " + e);
552         }
553         logger.info(EELFLoggerDelegate.applicationLogger,"Performed zookeeper write to " + nodeName);
554         long end = System.currentTimeMillis();
555         logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms");
556     }
557
558     /**
559      * 
560      * @param nodeName
561      * @return
562      */
563     public static byte[] pureZkRead(String nodeName) {
564         long start = System.currentTimeMillis();
565         byte[] data = null;
566         try {
567             data = getLockingServiceHandle().getzkLockHandle().getNodeData(nodeName);
568         } catch (MusicLockingException e) {
569             logger.error(EELFLoggerDelegate.errorLogger,"Failed to get ZK Lock Handle " + e);
570         }
571         long end = System.currentTimeMillis();
572         logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms");
573         return data;
574     }
575
576
577
578     // Prepared Query Additions.
579
580     /**
581      * 
582      * @param keyspaceName
583      * @param tableName
584      * @param primaryKey
585      * @param queryObject
586      * @return ReturnType
587      * @throws MusicServiceException
588      */
589     public static ReturnType eventualPut(PreparedQueryObject queryObject) {
590         boolean result = false;
591         try {
592             result = getDSHandle().executePut(queryObject, MusicUtil.EVENTUAL);
593         } catch (MusicServiceException | MusicQueryException ex) {
594             logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() + "  " + ex.getCause() + " " + ex);
595         }
596         if (result) {
597             return new ReturnType(ResultType.SUCCESS, "Success");
598         } else {
599             return new ReturnType(ResultType.FAILURE, "Failure");
600         }
601     }
602
603     /**
604      * 
605      * @param keyspaceName
606      * @param tableName
607      * @param primaryKey
608      * @param queryObject
609      * @param lockId
610      * @return
611      */
612     public static ReturnType criticalPut(String keyspaceName, String tableName, String primaryKey,
613                     PreparedQueryObject queryObject, String lockId, Condition conditionInfo) {
614         long start = System.currentTimeMillis();
615
616         try {
617             MusicLockState mls = getLockingServiceHandle()
618                             .getLockState(keyspaceName + "." + tableName + "." + primaryKey);
619             if (mls.getLockHolder().equals(lockId) == true) {
620                 if (conditionInfo != null)
621                   try {
622                     if (conditionInfo.testCondition() == false)
623                         return new ReturnType(ResultType.FAILURE,
624                                         "Lock acquired but the condition is not true");
625                   } catch (Exception e) {
626                     return new ReturnType(ResultType.FAILURE,
627                             "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
628                                             + e.getMessage());
629                   }
630                 getDSHandle().executePut(queryObject, MusicUtil.CRITICAL);
631                 long end = System.currentTimeMillis();
632                 logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the critical put:" + (end - start) + " ms");
633                 return new ReturnType(ResultType.SUCCESS, "Update performed");
634             } else
635                 return new ReturnType(ResultType.FAILURE,
636                                 "Cannot perform operation since you are the not the lock holder");
637         } catch (MusicQueryException | MusicServiceException  e) {
638             logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
639             return new ReturnType(ResultType.FAILURE,
640                             "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
641                                             + e.getMessage());
642         }catch(MusicLockingException ex){
643             return new ReturnType(ResultType.FAILURE,ex.getMessage());
644         }
645
646     }
647
648     /**
649      * 
650      * @param queryObject
651      * @param consistency
652      * @return Boolean Indicates success or failure
653      * @throws MusicServiceException 
654      * 
655      * 
656      */
657     public static boolean nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) throws MusicServiceException {
658         // this is mainly for some functions like keyspace creation etc which does not
659         // really need the bells and whistles of Music locking.
660         boolean result = false;
661         try {
662             result = getDSHandle().executePut(queryObject, consistency);
663         } catch (MusicQueryException | MusicServiceException ex) {
664             logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage());
665             throw new MusicServiceException(ex.getMessage());
666         }
667         return result;
668     }
669
670     /**
671      * This method performs DDL operation on cassandra.
672      * 
673      * @param queryObject query object containing prepared query and values
674      * @return ResultSet
675      * @throws MusicServiceException 
676      */
677     public static ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException {
678         ResultSet results = null;
679         try {
680                         results = getDSHandle().executeEventualGet(queryObject);
681         } catch (MusicQueryException | MusicServiceException e) {
682             logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
683             throw new MusicServiceException(e.getMessage());
684         }
685         return results;
686     }
687
688     /**
689      * This method performs DDL operations on cassandra, if the the resource is available. Lock ID
690      * is used to check if the resource is free.
691      * 
692      * @param keyspaceName name of the keyspace
693      * @param tableName name of the table
694      * @param primaryKey primary key value
695      * @param queryObject query object containing prepared query and values
696      * @param lockId lock ID to check if the resource is free to perform the operation.
697      * @return ResultSet
698      */
699     public static ResultSet criticalGet(String keyspaceName, String tableName, String primaryKey,
700                     PreparedQueryObject queryObject, String lockId) throws MusicServiceException {
701         ResultSet results = null;
702         try {
703             MusicLockState mls = getLockingServiceHandle()
704                             .getLockState(keyspaceName + "." + tableName + "." + primaryKey);
705             if (mls.getLockHolder().equals(lockId)) {
706                 results = getDSHandle().executeCriticalGet(queryObject);
707             } else
708                 throw new MusicServiceException("YOU DO NOT HAVE THE LOCK");
709         } catch (MusicQueryException | MusicServiceException | MusicLockingException e) {
710             logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
711         }
712         return results;
713     }
714
715     /**
716      * This method performs DML operation on cassandra, when the lock of the dd is acquired.
717      * 
718      * @param keyspaceName name of the keyspace
719      * @param tableName name of the table
720      * @param primaryKey primary key value
721      * @param queryObject query object containing prepared query and values
722      * @return ReturnType
723      * @throws MusicLockingException 
724      */
725     public static ReturnType atomicPut(String keyspaceName, String tableName, String primaryKey,
726                     PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException {
727
728         long start = System.currentTimeMillis();
729         String key = keyspaceName + "." + tableName + "." + primaryKey;
730         String lockId = createLockReference(key);
731         long lockCreationTime = System.currentTimeMillis();
732         ReturnType lockAcqResult = acquireLock(key, lockId);
733         long lockAcqTime = System.currentTimeMillis();
734         if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
735             logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
736             ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
737                             queryObject, lockId, conditionInfo);
738             long criticalPutTime = System.currentTimeMillis();
739             voluntaryReleaseLock(lockId);
740             long lockDeleteTime = System.currentTimeMillis();
741             String timingInfo = "|lock creation time:" + (lockCreationTime - start)
742                             + "|lock accquire time:" + (lockAcqTime - lockCreationTime)
743                             + "|critical put time:" + (criticalPutTime - lockAcqTime)
744                             + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|";
745             criticalPutResult.setTimingInfo(timingInfo);
746             return criticalPutResult;
747         } else {
748             logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
749             destroyLockRef(lockId);
750             return lockAcqResult;
751         }
752     }
753     
754     /**
755      * this function is mainly for the benchmarks to see the effect of lock deletion.
756      * 
757      * @param keyspaceName
758      * @param tableName
759      * @param primaryKey
760      * @param queryObject
761      * @param conditionInfo
762      * @return
763      * @throws MusicLockingException 
764      */
765     public static ReturnType atomicPutWithDeleteLock(String keyspaceName, String tableName,
766                     String primaryKey, PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException {
767
768         long start = System.currentTimeMillis();
769         String key = keyspaceName + "." + tableName + "." + primaryKey;
770         String lockId = createLockReference(key);
771         long lockCreationTime = System.currentTimeMillis();
772         long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
773         ReturnType lockAcqResult = acquireLock(key, lockId);
774         long lockAcqTime = System.currentTimeMillis();
775         if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
776             logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
777             ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
778                             queryObject, lockId, conditionInfo);
779             long criticalPutTime = System.currentTimeMillis();
780             deleteLock(key);
781             long lockDeleteTime = System.currentTimeMillis();
782             String timingInfo = "|lock creation time:" + (lockCreationTime - start)
783                             + "|lock accquire time:" + (lockAcqTime - lockCreationTime)
784                             + "|critical put time:" + (criticalPutTime - lockAcqTime)
785                             + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|";
786             criticalPutResult.setTimingInfo(timingInfo);
787             return criticalPutResult;
788         } else {
789             logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
790             deleteLock(key);
791             return lockAcqResult;
792         }
793     }
794     
795
796
797
798     /**
799      * This method performs DDL operation on cassasndra, when the lock for the resource is acquired.
800      * 
801      * @param keyspaceName name of the keyspace
802      * @param tableName name of the table
803      * @param primaryKey primary key value
804      * @param queryObject query object containing prepared query and values
805      * @return ResultSet
806      * @throws MusicServiceException
807      * @throws MusicLockingException 
808      */
809     public static ResultSet atomicGet(String keyspaceName, String tableName, String primaryKey,
810                     PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException {
811         String key = keyspaceName + "." + tableName + "." + primaryKey;
812         String lockId = createLockReference(key);
813         long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
814         ReturnType lockAcqResult = acquireLock(key, lockId);
815         if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
816             logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
817             ResultSet result =
818                             criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
819             voluntaryReleaseLock(lockId);
820             return result;
821         } else {
822                 destroyLockRef(lockId);
823             logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
824             return null;
825         }
826     }
827     
828         public static ResultSet atomicGetWithDeleteLock(String keyspaceName, String tableName, String primaryKey,
829                         PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException {
830                 String key = keyspaceName + "." + tableName + "." + primaryKey;
831                 String lockId = createLockReference(key);
832                 long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
833
834                 ReturnType lockAcqResult = acquireLock(key, lockId);
835
836                 if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
837                         logger.info(EELFLoggerDelegate.applicationLogger, "acquired lock with id " + lockId);
838                         ResultSet result = criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
839                         deleteLock(key);
840                         return result;
841                 } else {
842                         deleteLock(key);
843                         logger.info(EELFLoggerDelegate.applicationLogger, "unable to acquire lock, id " + lockId);
844                         return null;
845                 }
846         }
847     
848     
849
850     /**
851      * authenticate user logic
852      * 
853      * @param nameSpace
854      * @param userId
855      * @param password
856      * @param keyspace
857      * @param aid
858      * @param operation
859      * @return
860      * @throws Exception
861      */
862     public static Map<String, Object> autheticateUser(String nameSpace, String userId,
863                     String password, String keyspace, String aid, String operation)
864                     throws Exception {
865         Map<String, Object> resultMap = new HashMap<>();
866         String uuid = null;
867         resultMap = CachingUtil.validateRequest(nameSpace, userId, password, keyspace, aid,
868                         operation);
869         if (!resultMap.isEmpty())
870             return resultMap;
871         boolean isAAF = CachingUtil.isAAFApplication(nameSpace);
872         if (!isAAF && !(operation.equals("createKeySpace"))) {
873                 if(aid == null) {
874                         resultMap.put("Exception", "Aid is mandatory for nonAAF applications ");
875                         return resultMap;
876                 }
877                 if(operation.contains("Lock")) {
878                         resultMap = CachingUtil.authenticateAIDUserLock(aid, nameSpace);
879                 }
880                 else {
881                         resultMap = CachingUtil.authenticateAIDUser(aid, keyspace);
882                 }
883             
884             if (!resultMap.isEmpty())
885                 return resultMap;
886         }
887         if (aid == null && (userId == null || password == null)) {
888             logger.error(EELFLoggerDelegate.errorLogger,"One or more required headers is missing. userId: " + userId
889                             + " :: password: " + password);
890             resultMap.put("Exception",
891                             "UserId and Password are mandatory for the operation " + operation);
892             return resultMap;
893         }
894         
895         if (isAAF && nameSpace != null && userId != null && password != null) {
896             boolean isValid = true;
897             try {
898                  isValid = CachingUtil.authenticateAAFUser(nameSpace, userId, password, keyspace);
899             } catch (Exception e) {
900                 logger.error(EELFLoggerDelegate.errorLogger,"Got exception while AAF authentication for namespace " + nameSpace);
901                 resultMap.put("Exception", e.getMessage());
902             }
903             if (!isValid) {
904                 logger.error(EELFLoggerDelegate.errorLogger,"User not authenticated with AAF.");
905                 resultMap.put("Exception", "User not authenticated...");
906             }
907             if (!resultMap.isEmpty())
908                 return resultMap;
909
910         }
911
912         if (operation.equals("createKeySpace")) {
913             logger.info(EELFLoggerDelegate.applicationLogger,"AID is not provided. Creating new UUID for keyspace.");
914             PreparedQueryObject pQuery = new PreparedQueryObject();
915             pQuery.appendQueryString(
916                             "select uuid from admin.keyspace_master where application_name=? and username=? and keyspace_name=? allow filtering");
917             pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), nameSpace));
918             pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
919             pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),
920                             MusicUtil.DEFAULTKEYSPACENAME));
921
922             try {
923                 Row rs = MusicCore.get(pQuery).one();
924                 uuid = rs.getUUID("uuid").toString();
925                 resultMap.put("uuid", "existing");
926             } catch (Exception e) {
927                 logger.info(EELFLoggerDelegate.applicationLogger,"No UUID found in DB. So creating new UUID.");
928                 uuid = CachingUtil.generateUUID();
929                 resultMap.put("uuid", "new");
930             }
931
932             pQuery = new PreparedQueryObject();
933             pQuery.appendQueryString(
934                             "INSERT into admin.keyspace_master (uuid, keyspace_name, application_name, is_api, "
935                                             + "password, username, is_aaf) values (?,?,?,?,?,?,?)");
936             pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
937             pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), keyspace));
938             pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), nameSpace));
939             pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True"));
940             pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), password));
941             pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
942             pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF));
943             CachingUtil.updateMusicCache(uuid, keyspace);
944             MusicCore.eventualPut(pQuery);
945             resultMap.put("aid", uuid);
946         }
947
948         return resultMap;
949     }
950 }