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