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