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