Changes Listed below:
[music.git] / src / main / java / org / onap / music / main / MusicUtil.java
1 /*
2  * ============LICENSE_START==========================================
3  * org.onap.music
4  * ===================================================================
5  *  Copyright (c) 2017 AT&T Intellectual Property
6  * ===================================================================
7  *  Modifications Copyright (c) 2018 IBM.
8  *  Modifications Copyright (c) 2019 Samsung.
9  * ===================================================================
10  *  Licensed under the Apache License, Version 2.0 (the "License");
11  *  you may not use this file except in compliance with the License.
12  *  You may obtain a copy of the License at
13  *
14  *     http://www.apache.org/licenses/LICENSE-2.0
15  *
16  *  Unless required by applicable law or agreed to in writing, software
17  *  distributed under the License is distributed on an "AS IS" BASIS,
18  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  *  See the License for the specific language governing permissions and
20  *  limitations under the License.
21  *
22  * ============LICENSE_END=============================================
23  * ====================================================================
24  */
25
26 package org.onap.music.main;
27
28 import com.datastax.driver.core.ColumnDefinitions;
29 import com.datastax.driver.core.ColumnDefinitions.Definition;
30 import com.datastax.driver.core.ResultSet;
31 import com.datastax.driver.core.Row;
32 import java.io.File;
33 import java.io.FileNotFoundException;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.math.BigInteger;
37 import java.nio.ByteBuffer;
38 import java.util.ArrayList;
39 import java.util.HashMap;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Properties;
43 import java.util.Scanner;
44 import java.util.StringTokenizer;
45 import java.util.UUID;
46 import java.util.concurrent.ConcurrentHashMap;
47 import java.util.concurrent.ConcurrentMap;
48
49 import javax.ws.rs.core.Response;
50 import javax.ws.rs.core.Response.ResponseBuilder;
51 import org.onap.music.datastore.MusicDataStoreHandle;
52 import org.onap.music.datastore.PreparedQueryObject;
53 import org.onap.music.eelf.logging.EELFLoggerDelegate;
54 import org.onap.music.eelf.logging.format.AppMessages;
55 import org.onap.music.eelf.logging.format.ErrorSeverity;
56 import org.onap.music.eelf.logging.format.ErrorTypes;
57 import org.onap.music.exceptions.MusicQueryException;
58 import org.onap.music.exceptions.MusicServiceException;
59 import org.onap.music.service.MusicCoreService;
60 import org.onap.music.service.impl.MusicCassaCore;
61
62 import com.datastax.driver.core.ConsistencyLevel;
63 import com.datastax.driver.core.DataType;
64 import com.sun.jersey.core.util.Base64;
65
66 /**
67  * @author nelson24
68  *
69  *         Properties This will take Properties and load them into MusicUtil.
70  *         This is a hack for now. Eventually it would bebest to do this in
71  *         another way.
72  *
73  */
74 public class MusicUtil {
75     private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicUtil.class);
76
77     public static final String ATOMIC = "atomic";
78     public static final String EVENTUAL = "eventual";
79     public static final String CRITICAL = "critical";
80     public static final String EVENTUAL_NB = "eventual_nb";
81     public static final String ALL = "all";
82     public static final String QUORUM = "quorum";
83     public static final String ONE = "one";
84     public static final String ATOMICDELETELOCK = "atomic_delete_lock";
85     public static final String DEFAULTKEYSPACENAME = "TBD";
86     private static final String XLATESTVERSION = "X-latestVersion";
87     private static final String XMINORVERSION = "X-minorVersion";
88     private static final String XPATCHVERSION = "X-patchVersion";
89     public static final String SELECT = "select";
90     public static final String INSERT = "insert";
91     public static final String UPDATE = "update";
92     public static final String UPSERT = "upsert";
93     public static final String USERID = "userId";
94     public static final String PASSWORD = "password";
95     public static final String CASSANDRA = "cassandra";
96
97     public static final String AUTHORIZATION = "Authorization";
98
99     private static final String LOCALHOST = "localhost";
100     private static final String PROPERTIES_FILE = "/opt/app/music/etc/music.properties";
101
102     private static int myId = 0;
103     private static ArrayList<String> allIds = new ArrayList<>();
104     private static String publicIp = "";
105     private static ArrayList<String> allPublicIps = new ArrayList<>();
106     private static String myZkHost = LOCALHOST;
107     private static String myCassaHost = LOCALHOST;
108     private static String defaultMusicIp = LOCALHOST;
109     private static int cassandraPort = 9042;
110     private static int notifytimeout = 30000;
111     private static int notifyinterval = 5000;
112     private static int cacheObjectMaxLife = -1;
113     private static String lockUsing = MusicUtil.CASSANDRA;
114     private static boolean isCadi = false;
115     private static boolean isKeyspaceActive = false;
116     
117     private static boolean debug = true;
118     private static String version = "0.0.0";
119     private static String build = "";
120     private static String musicRestIp = LOCALHOST;
121     private static String musicPropertiesFilePath = PROPERTIES_FILE;
122     private static long defaultLockLeasePeriod = 6000;
123     private static int retryCount = 3;
124     private static final String[] propKeys = new String[] { "cassandra.host", "music.ip", "debug",
125         "version", "music.rest.ip", "music.properties", "lock.lease.period", "id", "all.ids", 
126         "public.ip","all.pubic.ips", "cassandra.user", "cassandra.password", "aaf.endpoint.url",
127         "admin.username","admin.password","aaf.admin.url","music.namespace","admin.aaf.role",
128         "cassandra.port","lock.using","retry.count"};
129     private static final String[] cosistencyLevel = new String[] {
130         "ALL","EACH_QUORUM","QUORUM","LOCAL_QUORUM","ONE","TWO",
131         "THREE","LOCAL_ONE","ANY","SERIAL","LOCAL_SERIAL"};
132     private static final Map<String,ConsistencyLevel> consistencyName = new HashMap<>();
133
134     static {
135         consistencyName.put("ONE",ConsistencyLevel.ONE);
136         consistencyName.put("TWO",ConsistencyLevel.TWO);
137         consistencyName.put("THREE",ConsistencyLevel.THREE);
138         consistencyName.put("SERIAL",ConsistencyLevel.SERIAL);
139         consistencyName.put("ALL",ConsistencyLevel.ALL);
140         consistencyName.put("EACH_QUORUM",ConsistencyLevel.EACH_QUORUM);
141         consistencyName.put("QUORUM",ConsistencyLevel.QUORUM);
142         consistencyName.put("LOCAL_QUORUM",ConsistencyLevel.LOCAL_QUORUM);
143         consistencyName.put("LOCAL_ONE",ConsistencyLevel.LOCAL_ONE);
144         consistencyName.put("LOCAL_SERIAL",ConsistencyLevel.LOCAL_SERIAL);
145     }
146
147     private static String cassName = "cassandra";
148     private static String cassPwd;
149     private static String aafEndpointUrl = null;
150     public static ConcurrentMap<String, Long> zkNodeMap = new ConcurrentHashMap<>();
151     private static String adminId = "username";
152     private static String adminPass= "password";
153     private static String aafAdminUrl= null;
154     private static String musicNamespace= "org.onap.music.api";
155     private static String adminAafRole= "org.onap.music.api.admin_api";
156     
157     public static final long MusicEternityEpochMillis = 1533081600000L; // Wednesday, August 1, 2018 12:00:00 AM
158
159     public static final long MaxLockReferenceTimePart = 1000000000000L; // millis after eternity (eq sometime in 2050)
160     
161     public static final long MaxCriticalSectionDurationMillis = 1L * 24 * 60 * 60 * 1000; // 1 day
162
163
164     public static String getLockUsing() {
165         return lockUsing;
166     }
167
168
169     public static void setLockUsing(String lockUsing) {
170         MusicUtil.lockUsing = lockUsing;
171     }
172     
173     public static String getAafAdminUrl() {
174         return aafAdminUrl;
175     }
176
177
178     public static void setAafAdminUrl(String aafAdminUrl) {
179         MusicUtil.aafAdminUrl = aafAdminUrl;
180     }
181
182
183     public static String getMusicNamespace() {
184         return musicNamespace;
185     }
186
187
188     public static void setMusicNamespace(String musicNamespace) {
189         MusicUtil.musicNamespace = musicNamespace;
190     }
191
192
193     public static String getAdminAafRole() {
194         return adminAafRole;
195     }
196
197
198     public static void setAdminAafRole(String adminAafRole) {
199         MusicUtil.adminAafRole = adminAafRole;
200     }
201
202
203
204     public static String getAdminId() {
205         return adminId;
206     }
207
208
209     public static void setAdminId(String adminId) {
210         MusicUtil.adminId = adminId;
211     }
212
213
214     public static String getAdminPass() {
215         return adminPass;
216     }
217
218     public static void setAdminPass(String adminPass) {
219         MusicUtil.adminPass = adminPass;
220     }
221
222     private MusicUtil() {
223         throw new IllegalStateException("Utility Class");
224     }
225     /**
226      *
227      * @return cassandra port
228      */
229     public static int getCassandraPort() {
230         return cassandraPort;
231     }
232
233     /**
234      * set cassandra port
235      * @param cassandraPort
236      */
237     public static void setCassandraPort(int cassandraPort) {
238         MusicUtil.cassandraPort = cassandraPort;
239     }
240     /**
241      * @return the cassName
242      */
243     public static String getCassName() {
244         return cassName;
245     }
246
247     /**
248      * @return the cassPwd
249      */
250     public static String getCassPwd() {
251         return cassPwd;
252     }
253
254     /**
255      * @return the aafEndpointUrl
256      */
257     public static String getAafEndpointUrl() {
258         return aafEndpointUrl;
259     }
260
261     /**
262      *
263      * @param aafEndpointUrl
264      */
265     public static void setAafEndpointUrl(String aafEndpointUrl) {
266         MusicUtil.aafEndpointUrl = aafEndpointUrl;
267     }
268
269     /**
270      *
271      * @return
272      */
273     public static int getMyId() {
274         return myId;
275     }
276
277     /**
278      *
279      * @param myId
280      */
281     public static void setMyId(int myId) {
282         MusicUtil.myId = myId;
283     }
284
285     /**
286      *
287      * @return
288      */
289     public static List<String> getAllIds() {
290         return allIds;
291     }
292
293     /**
294      *
295      * @param allIds
296      */
297     public static void setAllIds(List<String> allIds) {
298         MusicUtil.allIds = (ArrayList<String>) allIds;
299     }
300
301     /**
302      *
303      * @return
304      */
305     public static String getPublicIp() {
306         return publicIp;
307     }
308
309     /**
310      *
311      * @param publicIp
312      */
313     public static void setPublicIp(String publicIp) {
314         MusicUtil.publicIp = publicIp;
315     }
316
317     /**
318      *
319      * @return
320      */
321     public static List<String> getAllPublicIps() {
322         return allPublicIps;
323     }
324
325     /**
326      *
327      * @param allPublicIps
328      */
329     public static void setAllPublicIps(List<String> allPublicIps) {
330         MusicUtil.allPublicIps = (ArrayList<String>) allPublicIps;
331     }
332
333     /**
334      * Returns An array of property names that should be in the Properties
335      * files.
336      *
337      * @return
338      */
339     public static String[] getPropkeys() {
340         return propKeys;
341     }
342
343     /**
344      * Get MusicRestIp - default = localhost property file value - music.rest.ip
345      *
346      * @return
347      */
348     public static String getMusicRestIp() {
349         return musicRestIp;
350     }
351
352     /**
353      * Set MusicRestIp
354      *
355      * @param musicRestIp
356      */
357     public static void setMusicRestIp(String musicRestIp) {
358         MusicUtil.musicRestIp = musicRestIp;
359     }
360
361     /**
362      * Get MusicPropertiesFilePath - Default = /opt/music/music.properties
363      * property file value - music.properties
364      *
365      * @return
366      */
367     public static String getMusicPropertiesFilePath() {
368         return musicPropertiesFilePath;
369     }
370
371     /**
372      * Set MusicPropertiesFilePath
373      *
374      * @param musicPropertiesFilePath
375      */
376     public static void setMusicPropertiesFilePath(String musicPropertiesFilePath) {
377         MusicUtil.musicPropertiesFilePath = musicPropertiesFilePath;
378     }
379
380     /**
381      * Get DefaultLockLeasePeriod - Default = 6000 property file value -
382      * lock.lease.period
383      *
384      * @return
385      */
386     public static long getDefaultLockLeasePeriod() {
387         return defaultLockLeasePeriod;
388     }
389
390     /**
391      * Set DefaultLockLeasePeriod
392      *
393      * @param defaultLockLeasePeriod
394      */
395     public static void setDefaultLockLeasePeriod(long defaultLockLeasePeriod) {
396         MusicUtil.defaultLockLeasePeriod = defaultLockLeasePeriod;
397     }
398
399     /**
400      * Set Debug
401      *
402      * @param debug
403      */
404     public static void setDebug(boolean debug) {
405         MusicUtil.debug = debug;
406     }
407
408     /**
409      * Is Debug - Default = true property file value - debug
410      *
411      * @return
412      */
413     public static boolean isDebug() {
414         return debug;
415     }
416
417     /**
418      * Set Version
419      *
420      * @param version
421      */
422     public static void setVersion(String version) {
423         MusicUtil.version = version;
424     }
425
426     /**
427      * Return the version property file value - version.
428      *
429      * @return
430      */
431     public static String getVersion() {
432         return version;
433     }
434
435     /**
436      * Set the build of project which is a combination of the 
437      * version and the date.
438      * 
439      * @param build - version-date.
440      */
441     public static void setBuild(String build) {
442         MusicUtil.build = build;
443     }
444
445     /**
446      * Return the build version-date.
447      */
448     public static String getBuild() {
449         return build;
450     }
451
452     /**
453      * Get MyCassHost - Cassandra Hostname - Default = localhost property file
454      * value - cassandra.host
455      *
456      * @return
457      */
458     public static String getMyCassaHost() {
459         return myCassaHost;
460     }
461
462     /**
463      * Set MyCassHost - Cassandra Hostname
464      *
465      * @param myCassaHost .
466      */
467     public static void setMyCassaHost(String myCassaHost) {
468         MusicUtil.myCassaHost = myCassaHost;
469     }
470
471     /**
472      * Get DefaultMusicIp - Default = localhost property file value - music.ip
473      *
474      * @return
475      */
476     public static String getDefaultMusicIp() {
477         return defaultMusicIp;
478     }
479
480     /**
481      * Set DefaultMusicIp
482      *
483      * @param defaultMusicIp .
484      */
485     public static void setDefaultMusicIp(String defaultMusicIp) {
486         MusicUtil.defaultMusicIp = defaultMusicIp;
487     }
488     
489     /**
490      * Gey default retry count
491      * @return
492      */
493     public static int getRetryCount() {
494         return retryCount;
495     }
496
497     /**
498      * Set retry count
499      * @param retryCount .
500      */
501     public static void setRetryCount(int retryCount) {
502         MusicUtil.retryCount = retryCount;
503     }
504
505
506     /**
507      * This is used to turn keyspace creation api on/off.
508      * 
509      */
510     public static void setKeyspaceActive(Boolean keyspaceActive) {
511         MusicUtil.isKeyspaceActive = keyspaceActive;
512     }
513
514     /**
515      * This is used to turn keyspace creation api on/off.
516      * @return boolean isKeyspaceActive
517      */
518     public static boolean isKeyspaceActive() {
519         return isKeyspaceActive;
520     }
521
522     /**
523      * .
524      * @return String
525      */
526     public static String getTestType() {
527         String testType = "";
528         try {
529             Scanner fileScanner = new Scanner(new File(""));
530             testType = fileScanner.next();// ignore the my id line
531             @SuppressWarnings("unused")
532             String batchSize = fileScanner.next();// ignore the my public ip line
533             fileScanner.close();
534         } catch (FileNotFoundException e) {
535             logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), e);
536         }
537         return testType;
538
539     }
540
541     /**
542      *
543      * @param time
544      */
545     public static void sleep(long time) {
546         try {
547             Thread.sleep(time);
548         } catch (InterruptedException e) {
549             logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), e);
550             Thread.currentThread().interrupt();
551         }
552     }
553
554     /**
555      * Utility function to check if the query object is valid.
556      *
557      * @param withparams
558      * @param queryObject
559      * @return
560      */
561     public static boolean isValidQueryObject(boolean withparams, PreparedQueryObject queryObject) {
562         if (withparams) {
563             int noOfValues = queryObject.getValues().size();
564             int noOfParams = 0;
565             char[] temp = queryObject.getQuery().toCharArray();
566             for (int i = 0; i < temp.length; i++) {
567                 if (temp[i] == '?')
568                     noOfParams++;
569             }
570             return (noOfValues == noOfParams);
571         } else {
572             return !queryObject.getQuery().isEmpty();
573         }
574
575     }
576
577     public static void setCassName(String cassName) {
578         MusicUtil.cassName = cassName;
579     }
580
581     public static void setCassPwd(String cassPwd) {
582         MusicUtil.cassPwd = cassPwd;
583     }
584
585     @SuppressWarnings("unchecked")
586     public static String convertToCQLDataType(DataType type, Object valueObj) throws Exception {
587
588         String value = "";
589         switch (type.getName()) {
590         case UUID:
591             value = valueObj + "";
592             break;
593         case TEXT:
594         case VARCHAR:
595             String valueString = valueObj + "";
596             valueString = valueString.replace("'", "''");
597             value = "'" + valueString + "'";
598             break;
599         case MAP: {
600             Map<String, Object> otMap = (Map<String, Object>) valueObj;
601             value = "{" + jsonMaptoSqlString(otMap, ",") + "}";
602             break;
603         }
604         default:
605             value = valueObj + "";
606             break;
607         }
608         return value;
609     }
610
611     /**
612      *
613      * @param colType
614      * @param valueObj
615      * @return
616      * @throws MusicTypeConversionException
617      * @throws Exception
618      */
619     @SuppressWarnings("unchecked")
620     public static Object convertToActualDataType(DataType colType, Object valueObj) throws Exception {
621         String valueObjString = valueObj + "";
622         switch (colType.getName()) {
623             case UUID:
624                 return UUID.fromString(valueObjString);
625             case VARINT:
626                 return BigInteger.valueOf(Long.parseLong(valueObjString));
627             case BIGINT:
628                 return Long.parseLong(valueObjString);
629             case INT:
630                 return Integer.parseInt(valueObjString);
631             case FLOAT:
632                 return Float.parseFloat(valueObjString);
633             case DOUBLE:
634                 return Double.parseDouble(valueObjString);
635             case BOOLEAN:
636                 return Boolean.parseBoolean(valueObjString);
637             case MAP:
638                 return (Map<String, Object>) valueObj;
639             case LIST:
640                 return (List<Object>)valueObj;
641             case BLOB:
642
643             default:
644                 return valueObjString;
645         }
646     }
647
648     public static ByteBuffer convertToActualDataType(DataType colType, byte[] valueObj) {
649         ByteBuffer buffer = ByteBuffer.wrap(valueObj);
650         return buffer;
651     }
652
653     /**
654      *
655      * Utility function to parse json map into sql like string
656      *
657      * @param jMap
658      * @param lineDelimiter
659      * @return
660      */
661
662     public static String jsonMaptoSqlString(Map<String, Object> jMap, String lineDelimiter) throws Exception{
663         StringBuilder sqlString = new StringBuilder();
664         int counter = 0;
665         for (Map.Entry<String, Object> entry : jMap.entrySet()) {
666             Object ot = entry.getValue();
667             String value = ot + "";
668             if (ot instanceof String) {
669                 value = "'" + value.replace("'", "''") + "'";
670             }
671             sqlString.append("'" + entry.getKey() + "':" + value);
672             if (counter != jMap.size() - 1)
673                 sqlString.append(lineDelimiter);
674             counter = counter + 1;
675         }
676         return sqlString.toString();
677     }
678
679     @SuppressWarnings("unused")
680     public static String buildVersion(String major, String minor, String patch) {
681         if (minor != null) {
682             major += "." + minor;
683             if (patch != null) {
684                 major += "." + patch;
685             }
686         }
687         return major;
688     }
689
690     /**
691      * Currently this will build a header with X-latestVersion, X-minorVersion and X-pathcVersion
692      * X-latestVerstion will be equal to the latest full version.
693      * X-minorVersion - will be equal to the latest minor version.
694      * X-pathVersion - will be equal to the latest patch version.
695      * Future plans will change this.
696      * @param response
697      * @param major
698      * @param minor
699      * @param patch
700      * @return
701      */
702     public static ResponseBuilder buildVersionResponse(String major, String minor, String patch) {
703         ResponseBuilder response = Response.noContent();
704         String versionIn = buildVersion(major,minor,patch);
705         String version = MusicUtil.getVersion();
706         String[] verArray = version.split("\\.",3);
707         if ( minor != null ) {
708             response.header(XMINORVERSION,minor);
709         } else {
710             response.header(XMINORVERSION,verArray[1]);
711         }
712         if ( patch != null ) {
713             response.header(XPATCHVERSION,patch);
714         } else {
715             response.header(XPATCHVERSION,verArray[2]);
716         }
717         response.header(XLATESTVERSION,version);
718         logger.info(EELFLoggerDelegate.applicationLogger,"Version In:" + versionIn);
719         return response;
720     }
721
722
723     public static Map<String,String> extractBasicAuthentication(String authorization){
724         Map<String,String> authValues = new HashMap<>();
725         if(authorization == null) {
726             authValues.put("ERROR", "Authorization cannot be null");
727             return authValues;
728         }
729         authorization = authorization.replaceFirst("Basic", "");
730         String decoded = Base64.base64Decode(authorization);
731         StringTokenizer token = new StringTokenizer(decoded, ":");
732         authValues.put(MusicUtil.USERID, token.nextToken());
733         authValues.put(MusicUtil.PASSWORD,token.nextToken());
734         return authValues;
735
736     }
737
738     public static boolean isValidConsistency(String consistency) {
739         for (String string : cosistencyLevel) {
740             if (string.equalsIgnoreCase(consistency))
741                 return true;
742         }
743         return false;
744
745     }
746
747     public static ConsistencyLevel getConsistencyLevel(String consistency) {
748         return consistencyName.get(consistency.toUpperCase());
749         }
750
751         public static void loadProperties() throws Exception {
752         Properties prop = new Properties();
753         InputStream input = null;
754         try {
755             // load the properties file
756             input = MusicUtil.class.getClassLoader().getResourceAsStream("music.properties");
757             prop.load(input);
758         } catch (Exception ex) {
759             logger.error(EELFLoggerDelegate.errorLogger, "Unable to find properties file.", ex);
760             throw new Exception();
761         } finally {
762             if (input != null) {
763                 try {
764                     input.close();
765                 } catch (IOException e) {
766                     e.printStackTrace();
767                     logger.error(EELFLoggerDelegate.errorLogger, e);
768                 }
769             }
770         }
771         // get the property value and return it
772         MusicUtil.setMyCassaHost(prop.getProperty("cassandra.host"));
773         MusicUtil.setCassName(prop.getProperty("cassandra.user"));
774         MusicUtil.setCassPwd(prop.getProperty("cassandra.password"));
775         MusicUtil.setCassandraPort(Integer.parseInt(prop.getProperty("cassandra.port")));
776         MusicUtil.setNotifyTimeOut(Integer.parseInt(prop.getProperty("notify.timeout")));
777         MusicUtil.setNotifyInterval(Integer.parseInt(prop.getProperty("notify.interval")));
778         MusicUtil.setCacheObjectMaxLife(Integer.parseInt(prop.getProperty("cacheobject.maxlife")));
779     }
780
781     public static void setNotifyInterval(int notifyinterval) {
782         MusicUtil.notifyinterval = notifyinterval;
783     }
784     public static void setNotifyTimeOut(int notifytimeout) {
785         MusicUtil.notifytimeout = notifytimeout;
786     }
787
788     public static int getNotifyInterval() {
789         return MusicUtil.notifyinterval;
790     }
791
792     public static int getNotifyTimeout() {
793         return MusicUtil.notifytimeout;
794     }
795
796     public static int getCacheObjectMaxLife() {
797         return MusicUtil.cacheObjectMaxLife;
798     }
799
800     public static void setCacheObjectMaxLife(int cacheObjectMaxLife) {
801         MusicUtil.cacheObjectMaxLife = cacheObjectMaxLife;
802     }
803     
804     /**
805      * Given the time of write for an update in a critical section, this method provides a transformed timestamp
806      * that ensures that a previous lock holder who is still alive can never corrupt a later critical section.
807      * The main idea is to us the lock reference to clearly demarcate the timestamps across critical sections.
808      * @param the UUID lock reference associated with the write.
809      * @param the long timeOfWrite which is the actual time at which the write took place
810      * @throws MusicServiceException
811      * @throws MusicQueryException
812      */
813     public static long v2sTimeStampInMicroseconds(long ordinal, long timeOfWrite) throws MusicServiceException, MusicQueryException {
814         // TODO: use acquire time instead of music eternity epoch
815         long ts = ordinal * MaxLockReferenceTimePart + (timeOfWrite - MusicEternityEpochMillis);
816
817         return ts;
818     }
819     
820     public static MusicCoreService  getMusicCoreService() {
821         if(getLockUsing().equals(MusicUtil.CASSANDRA))
822             return MusicCassaCore.getInstance();
823         else
824             return MusicCassaCore.getInstance();
825     }
826     
827     /**
828      * @param lockName
829      * @return
830      */
831     public static Map<String, Object> validateLock(String lockName) {
832         Map<String, Object> resultMap = new HashMap<>();
833         String[] locks = lockName.split("\\.");
834         if(locks.length < 3) {
835             resultMap.put("Error", "Invalid lock. Please make sure lock is of the type keyspaceName.tableName.primaryKey");
836             return resultMap;
837         }
838         String keyspace= locks[0];
839         if(keyspace.startsWith("$"))
840             keyspace = keyspace.substring(1);
841         resultMap.put("keyspace",keyspace);
842         return resultMap;
843     }
844
845
846     public static void setIsCadi(boolean isCadi) {
847         MusicUtil.isCadi = isCadi;
848     }
849
850     public static void writeBackToQuorum(PreparedQueryObject selectQuery, String primaryKeyName,
851         PreparedQueryObject updateQuery, String keyspace, String table,
852         Object cqlFormattedPrimaryKeyValue)
853         throws Exception {
854         try {
855             ResultSet results = MusicDataStoreHandle.getDSHandle().executeQuorumConsistencyGet(selectQuery);
856             // write it back to a quorum
857             Row row = results.one();
858             ColumnDefinitions colInfo = row.getColumnDefinitions();
859             int totalColumns = colInfo.size();
860             int counter = 1;
861             StringBuilder fieldValueString = new StringBuilder("");
862             for (Definition definition : colInfo) {
863                 String colName = definition.getName();
864                 if (colName.equals(primaryKeyName))
865                     continue;
866                 DataType colType = definition.getType();
867                 Object valueObj = MusicDataStoreHandle.getDSHandle().getColValue(row, colName, colType);
868                 Object valueString = MusicUtil.convertToActualDataType(colType, valueObj);
869                 fieldValueString.append(colName + " = ?");
870                 updateQuery.addValue(valueString);
871                 if (counter != (totalColumns - 1))
872                     fieldValueString.append(",");
873                 counter = counter + 1;
874             }
875             updateQuery.appendQueryString("UPDATE " + keyspace + "." + table + " SET "
876                 + fieldValueString + " WHERE " + primaryKeyName + "= ? " + ";");
877             updateQuery.addValue(cqlFormattedPrimaryKeyValue);
878
879             MusicDataStoreHandle.getDSHandle().executePut(updateQuery, "critical");
880         } catch (MusicServiceException | MusicQueryException e) {
881             logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.QUERYERROR +""+updateQuery ,
882                 ErrorSeverity.MAJOR, ErrorTypes.QUERYERROR, e);
883         }
884     }
885     
886     public static boolean getIsCadi() {
887         return MusicUtil.isCadi;
888     }
889
890
891     /**
892      * @return a random uuid
893      */
894     public static String generateUUID() {
895         String uuid = UUID.randomUUID().toString();
896         logger.info(EELFLoggerDelegate.applicationLogger,"New AID generated: "+uuid);
897         return uuid;
898     }
899
900 }
901