Issue-ID: MUSIC-481. Removed commented out lines of code.
[music.git] / src / main / java / org / onap / music / datastore / MusicDataStore.java
1 /*
2  * ============LICENSE_START==========================================
3  * org.onap.music
4  * ===================================================================
5  *  Copyright (c) 2017 AT&T Intellectual Property
6  * ===================================================================
7  *  Modifications Copyright (c) 2018-2019 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.datastore;
27
28 import java.net.InetAddress;
29 import java.net.NetworkInterface;
30 import java.net.SocketException;
31 import java.nio.ByteBuffer;
32 import java.util.ArrayList;
33 import java.util.Enumeration;
34 import java.util.HashMap;
35 import java.util.Iterator;
36 import java.util.Map;
37
38 import org.onap.music.eelf.logging.EELFLoggerDelegate;
39 import org.onap.music.eelf.logging.format.AppMessages;
40 import org.onap.music.eelf.logging.format.ErrorSeverity;
41 import org.onap.music.eelf.logging.format.ErrorTypes;
42 import org.onap.music.exceptions.MusicQueryException;
43 import org.onap.music.exceptions.MusicServiceException;
44 import org.onap.music.main.CipherUtil;
45 import org.onap.music.main.MusicUtil;
46 import com.datastax.driver.core.Cluster;
47 import com.datastax.driver.core.ColumnDefinitions;
48 import com.datastax.driver.core.ColumnDefinitions.Definition;
49 import com.datastax.driver.core.ConsistencyLevel;
50 import com.datastax.driver.core.DataType;
51 import com.datastax.driver.core.HostDistance;
52 import com.datastax.driver.core.KeyspaceMetadata;
53 import com.datastax.driver.core.Metadata;
54 import com.datastax.driver.core.PoolingOptions;
55 import com.datastax.driver.core.ResultSet;
56 import com.datastax.driver.core.Row;
57 import com.datastax.driver.core.Session;
58 import com.datastax.driver.core.SimpleStatement;
59 import com.datastax.driver.core.TableMetadata;
60 import com.datastax.driver.core.exceptions.AlreadyExistsException;
61 import com.datastax.driver.core.exceptions.InvalidQueryException;
62 import com.datastax.driver.core.exceptions.NoHostAvailableException;
63
64 /**
65  * @author nelson24
66  *
67  */
68 public class MusicDataStore {
69
70     public static final String CONSISTENCY_LEVEL_ONE = "ONE";
71     public static final String CONSISTENCY_LEVEL_QUORUM = "QUORUM";
72     private Session session;
73     private Cluster cluster;
74
75
76     /**
77      * @param session
78      */
79     public void setSession(Session session) {
80         this.session = session;
81     }
82
83     /**
84      * @param session
85      */
86     public Session getSession() {
87         return session;
88     }
89
90     /**
91      * @param cluster
92      */
93     public void setCluster(Cluster cluster) {
94         this.cluster = cluster;
95     }
96
97
98     private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicDataStore.class);
99
100     /**
101      *
102      */
103     public MusicDataStore() {
104         connectToCassaCluster();
105     }
106
107
108     /**
109      * @param cluster
110      * @param session
111      */
112     public MusicDataStore(Cluster cluster, Session session) {
113         this.session = session;
114         this.cluster = cluster;
115     }
116
117     /**
118      *
119      * @param remoteIp
120      * @throws MusicServiceException
121      */
122     public MusicDataStore(String remoteIp) {
123         try {
124             connectToCassaCluster(remoteIp);
125         } catch (MusicServiceException e) {
126             logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), e);
127         }
128     }
129
130     /**
131      *
132      * @return
133      */
134     private ArrayList<String> getAllPossibleLocalIps() {
135         ArrayList<String> allPossibleIps = new ArrayList<>();
136         try {
137             Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
138             while (en.hasMoreElements()) {
139                 NetworkInterface ni = en.nextElement();
140                 Enumeration<InetAddress> ee = ni.getInetAddresses();
141                 while (ee.hasMoreElements()) {
142                     InetAddress ia = ee.nextElement();
143                     allPossibleIps.add(ia.getHostAddress());
144                 }
145             }
146         } catch (SocketException e) {
147             logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.CONNCECTIVITYERROR,
148                 ErrorSeverity.ERROR, ErrorTypes.CONNECTIONERROR, e);
149         }catch(Exception e) {
150             logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), ErrorSeverity.ERROR, ErrorTypes
151                 .GENERALSERVICEERROR, e);
152         }
153         return allPossibleIps;
154     }
155
156     /**
157      * This method iterates through all available IP addresses and connects to multiple cassandra
158      * clusters.
159      */
160     private void connectToCassaCluster() {
161         Iterator<String> it = getAllPossibleLocalIps().iterator();
162         String address = "localhost";
163         String[] addresses = null;
164         address = MusicUtil.getMyCassaHost();
165         addresses = address.split(",");
166
167         logger.info(EELFLoggerDelegate.applicationLogger,
168                         "Connecting to cassa cluster: Iterating through possible ips:"
169                                         + getAllPossibleLocalIps());
170         PoolingOptions poolingOptions = new PoolingOptions();
171         poolingOptions
172         .setConnectionsPerHost(HostDistance.LOCAL,  4, 10)
173         .setConnectionsPerHost(HostDistance.REMOTE, 2, 4);
174         while (it.hasNext()) {
175             try {
176                 if(MusicUtil.getCassName() != null && MusicUtil.getCassPwd() != null) {
177                     String cassPwd = CipherUtil.decryptPKC(MusicUtil.getCassPwd());
178                     logger.info(EELFLoggerDelegate.applicationLogger,
179                             "Building with credentials "+MusicUtil.getCassName()+" & "+MusicUtil.getCassPwd());
180                     cluster = Cluster.builder().withPort(MusicUtil.getCassandraPort())
181                                         .withCredentials(MusicUtil.getCassName(), cassPwd)
182                                         //.withLoadBalancingPolicy(new RoundRobinPolicy())
183                                         .withoutJMXReporting()
184                                         .withPoolingOptions(poolingOptions)
185                                         .addContactPoints(addresses).build();
186                 }
187                 else
188                     cluster = Cluster.builder().withPort(MusicUtil.getCassandraPort())
189                                         //.withLoadBalancingPolicy(new RoundRobinPolicy())
190                                         .addContactPoints(addresses).build();
191
192                 Metadata metadata = cluster.getMetadata();
193                 logger.info(EELFLoggerDelegate.applicationLogger, "Connected to cassa cluster "
194                                 + metadata.getClusterName() + " at " + address);
195                 session = cluster.connect();
196
197                 break;
198             } catch (NoHostAvailableException e) {
199                 address = it.next();
200                 logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.HOSTUNAVAILABLE,
201                     ErrorSeverity.ERROR, ErrorTypes.CONNECTIONERROR, e);
202             }
203         }
204     }
205
206     /**
207      *
208      */
209     public void close() {
210         session.close();
211     }
212
213     /**
214      * This method connects to cassandra cluster on specific address.
215      *
216      * @param address
217      */
218     private void connectToCassaCluster(String address) throws MusicServiceException {
219         String[] addresses = null;
220         addresses = address.split(",");
221         PoolingOptions poolingOptions = new PoolingOptions();
222         poolingOptions
223         .setConnectionsPerHost(HostDistance.LOCAL,  4, 10)
224         .setConnectionsPerHost(HostDistance.REMOTE, 2, 4);
225         if(MusicUtil.getCassName() != null && MusicUtil.getCassPwd() != null) {
226             String cassPwd = CipherUtil.decryptPKC(MusicUtil.getCassPwd());
227             logger.info(EELFLoggerDelegate.applicationLogger,
228                     "Building with credentials "+MusicUtil.getCassName()+" & "+ MusicUtil.getCassPwd());
229             cluster = Cluster.builder().withPort(MusicUtil.getCassandraPort())
230                         .withCredentials(MusicUtil.getCassName(), cassPwd)
231                         //.withLoadBalancingPolicy(new RoundRobinPolicy())
232                         .withoutJMXReporting()
233                         .withPoolingOptions(poolingOptions)
234                         .addContactPoints(addresses).build();
235         } else {
236             cluster = Cluster.builder().withPort(MusicUtil.getCassandraPort())
237                         .withoutJMXReporting()
238                         .withPoolingOptions(poolingOptions)
239                         .addContactPoints(addresses).build();
240         }
241         
242         Metadata metadata = cluster.getMetadata();
243         logger.info(EELFLoggerDelegate.applicationLogger, "Connected to cassa cluster "
244                         + metadata.getClusterName() + " at " + address);
245         try {
246             session = cluster.connect();
247         } catch (Exception ex) {
248             logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.CASSANDRACONNECTIVITY,
249                 ErrorSeverity.ERROR, ErrorTypes.SERVICEUNAVAILABLE, ex);
250             throw new MusicServiceException(
251                             "Error while connecting to Cassandra cluster.. " + ex.getMessage());
252         }
253     }
254
255     /**
256      *
257      * @param keyspace
258      * @param tableName
259      * @param columnName
260      * @return DataType
261      */
262     public DataType returnColumnDataType(String keyspace, String tableName, String columnName) {
263         KeyspaceMetadata ks = cluster.getMetadata().getKeyspace(keyspace);
264         TableMetadata table = ks.getTable(tableName);
265         return table.getColumn(columnName).getType();
266
267     }
268
269     /**
270      *
271      * @param keyspace
272      * @param tableName
273      * @return TableMetadata
274      */
275     public TableMetadata returnColumnMetadata(String keyspace, String tableName) {
276         KeyspaceMetadata ks = cluster.getMetadata().getKeyspace(keyspace);
277         return ks.getTable(tableName);
278     }
279     
280     /**
281     *
282     * @param keyspace
283     * @param tableName
284     * @return TableMetadata
285     */
286    public KeyspaceMetadata returnKeyspaceMetadata(String keyspace) {
287        KeyspaceMetadata ks = cluster.getMetadata().getKeyspace(keyspace);
288        return ks;
289    }
290
291
292     /**
293      * Utility function to return the Java specific object type.
294      *
295      * @param row
296      * @param colName
297      * @param colType
298      * @return
299      */
300     public Object getColValue(Row row, String colName, DataType colType) {
301
302         switch (colType.getName()) {
303             case VARCHAR:
304                 return row.getString(colName);
305             case UUID:
306                 return row.getUUID(colName);
307             case VARINT:
308                 return row.getVarint(colName);
309             case BIGINT:
310                 return row.getLong(colName);
311             case INT:
312                 return row.getInt(colName);
313             case FLOAT:
314                 return row.getFloat(colName);
315             case DOUBLE:
316                 return row.getDouble(colName);
317             case BOOLEAN:
318                 return row.getBool(colName);
319             case MAP:
320                 return row.getMap(colName, String.class, String.class);
321             case LIST:
322                 return row.getList(colName, String.class);
323             default:
324                 return null;
325         }
326     }
327
328     public byte[] getBlobValue(Row row, String colName, DataType colType) {
329         ByteBuffer bb = row.getBytes(colName);
330         return bb.array();
331     }
332
333     public boolean doesRowSatisfyCondition(Row row, Map<String, Object> condition) throws Exception {
334         ColumnDefinitions colInfo = row.getColumnDefinitions();
335
336         for (Map.Entry<String, Object> entry : condition.entrySet()) {
337             String colName = entry.getKey();
338             DataType colType = colInfo.getType(colName);
339             Object columnValue = getColValue(row, colName, colType);
340             Object conditionValue = MusicUtil.convertToActualDataType(colType, entry.getValue());
341             if (columnValue.equals(conditionValue) == false)
342                 return false;
343         }
344         return true;
345     }
346
347     /**
348      * Utility function to store ResultSet values in to a MAP for output.
349      *
350      * @param results
351      * @return MAP
352      */
353     public Map<String, HashMap<String, Object>> marshalData(ResultSet results) {
354         Map<String, HashMap<String, Object>> resultMap =
355                         new HashMap<>();
356         int counter = 0;
357         for (Row row : results) {
358             ColumnDefinitions colInfo = row.getColumnDefinitions();
359             HashMap<String, Object> resultOutput = new HashMap<>();
360             for (Definition definition : colInfo) {
361                 if (!(("vector_ts").equals(definition.getName()))) {
362                     if(definition.getType().toString().toLowerCase().contains("blob")) {
363                         resultOutput.put(definition.getName(),
364                                 getBlobValue(row, definition.getName(), definition.getType()));
365                     } else {
366                         resultOutput.put(definition.getName(),
367                                     getColValue(row, definition.getName(), definition.getType()));
368                     }
369                 }
370             }
371             resultMap.put("row " + counter, resultOutput);
372             counter++;
373         }
374         return resultMap;
375     }
376
377
378     // Prepared Statements 1802 additions
379     
380     public boolean executePut(PreparedQueryObject queryObject, String consistency)
381             throws MusicServiceException, MusicQueryException {
382         return executePut(queryObject, consistency, 0);
383     }
384     /**
385      * This Method performs DDL and DML operations on Cassandra using specified consistency level
386      *
387      * @param queryObject Object containing cassandra prepared query and values.
388      * @param consistency Specify consistency level for data synchronization across cassandra
389      *        replicas
390      * @return Boolean Indicates operation success or failure
391      * @throws MusicServiceException
392      * @throws MusicQueryException
393      */
394     public boolean executePut(PreparedQueryObject queryObject, String consistency,long timeSlot)
395                     throws MusicServiceException, MusicQueryException {
396
397         boolean result = false;
398         long timeOfWrite = System.currentTimeMillis();
399         if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) {
400             logger.error(EELFLoggerDelegate.errorLogger, queryObject.getQuery(),AppMessages.QUERYERROR, ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
401             throw new MusicQueryException("Ill formed queryObject for the request = " + "["
402                             + queryObject.getQuery() + "]");
403         }
404         logger.debug(EELFLoggerDelegate.applicationLogger,
405                         "In preprared Execute Put: the actual insert query:"
406                                         + queryObject.getQuery() + "; the values"
407                                         + queryObject.getValues());
408         SimpleStatement preparedInsert = null;
409
410         try {
411             preparedInsert = new SimpleStatement(queryObject.getQuery(), queryObject.getValues().toArray());
412             if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
413                 logger.info(EELFLoggerDelegate.applicationLogger, "Executing critical put query");
414                 preparedInsert.setConsistencyLevel(ConsistencyLevel.QUORUM);
415             } else if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) {
416                 logger.info(EELFLoggerDelegate.applicationLogger, "Executing simple put query");
417                 if(queryObject.getConsistency() == null)
418                     preparedInsert.setConsistencyLevel(ConsistencyLevel.ONE);
419                 else
420                     preparedInsert.setConsistencyLevel(MusicUtil.getConsistencyLevel(queryObject.getConsistency()));
421             } else if (consistency.equalsIgnoreCase(MusicUtil.ONE)) {
422                 preparedInsert.setConsistencyLevel(ConsistencyLevel.ONE);
423             }  else if (consistency.equalsIgnoreCase(MusicUtil.QUORUM)) {
424                 preparedInsert.setConsistencyLevel(ConsistencyLevel.LOCAL_QUORUM);
425             } else if (consistency.equalsIgnoreCase(MusicUtil.ALL)) {
426                 preparedInsert.setConsistencyLevel(ConsistencyLevel.ALL);
427             }
428             long timestamp = MusicUtil.v2sTimeStampInMicroseconds(timeSlot, timeOfWrite);
429             preparedInsert.setDefaultTimestamp(timestamp);
430
431             ResultSet rs = session.execute(preparedInsert);
432             result = rs.wasApplied();
433
434         }
435         catch (AlreadyExistsException ae) {
436             // logger.error(EELFLoggerDelegate.errorLogger,"AlreadExistsException: " + ae.getMessage(),AppMessages.QUERYERROR,
437             // ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
438             throw new MusicQueryException("AlreadyExistsException: " + ae.getMessage(),ae);
439         } catch ( InvalidQueryException e ) {
440             // logger.error(EELFLoggerDelegate.errorLogger,"InvalidQueryException: " + e.getMessage(),AppMessages.SESSIONFAILED + " [" 
441             // + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
442             throw new MusicQueryException("InvalidQueryException: " + e.getMessage(),e);
443         } catch (Exception e) {
444             // logger.error(EELFLoggerDelegate.errorLogger,e.getClass().toString() + ":" + e.getMessage(),AppMessages.SESSIONFAILED + " [" 
445             //     + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR, e);
446             throw new MusicServiceException("Executing Session Failure for Request = " + "["
447                 + queryObject.getQuery() + "]" + " Reason = " + e.getMessage(),e);
448         }
449         return result;
450     }
451
452  /*   *//**
453      * This method performs DDL operations on Cassandra using consistency level ONE.
454      *
455      * @param queryObject Object containing cassandra prepared query and values.
456      * @return ResultSet
457      * @throws MusicServiceException
458      * @throws MusicQueryException
459      *//*
460     public ResultSet executeEventualGet(PreparedQueryObject queryObject)
461                     throws MusicServiceException, MusicQueryException {
462         CacheAccess<String, PreparedStatement> queryBank = CachingUtil.getStatementBank();
463         PreparedStatement preparedEventualGet = null;
464         if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) {
465             logger.error(EELFLoggerDelegate.errorLogger, "",AppMessages.QUERYERROR+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
466             throw new MusicQueryException("Ill formed queryObject for the request = " + "["
467                             + queryObject.getQuery() + "]");
468         }
469         logger.info(EELFLoggerDelegate.applicationLogger,
470                         "Executing Eventual  get query:" + queryObject.getQuery());
471
472         ResultSet results = null;
473         try {
474             if(queryBank.get(queryObject.getQuery()) != null )
475                 preparedEventualGet=queryBank.get(queryObject.getQuery());
476             else {
477                 preparedEventualGet = session.prepare(queryObject.getQuery());
478                 CachingUtil.updateStatementBank(queryObject.getQuery(), preparedEventualGet);
479             }
480             if(queryObject.getConsistency() == null) {
481                 preparedEventualGet.setConsistencyLevel(ConsistencyLevel.ONE);
482             } else {
483                 preparedEventualGet.setConsistencyLevel(MusicUtil.getConsistencyLevel(queryObject.getConsistency()));
484             }
485             results = session.execute(preparedEventualGet.bind(queryObject.getValues().toArray()));
486
487         } catch (Exception ex) {
488             logger.error("Exception", ex);
489             logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
490             throw new MusicServiceException(ex.getMessage());
491         }
492         return results;
493     }
494
495     *//**
496      *
497      * This method performs DDL operation on Cassandra using consistency level QUORUM.
498      *
499      * @param queryObject Object containing cassandra prepared query and values.
500      * @return ResultSet
501      * @throws MusicServiceException
502      * @throws MusicQueryException
503      *//*
504     public ResultSet executeCriticalGet(PreparedQueryObject queryObject)
505                     throws MusicServiceException, MusicQueryException {
506         if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) {
507             logger.error(EELFLoggerDelegate.errorLogger, "",AppMessages.QUERYERROR+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
508             throw new MusicQueryException("Error processing Prepared Query Object for the request = " + "["
509                             + queryObject.getQuery() + "]");
510         }
511         logger.info(EELFLoggerDelegate.applicationLogger,
512                         "Executing Critical get query:" + queryObject.getQuery());
513         PreparedStatement preparedEventualGet = session.prepare(queryObject.getQuery());
514         preparedEventualGet.setConsistencyLevel(ConsistencyLevel.QUORUM);
515         ResultSet results = null;
516         try {
517             results = session.execute(preparedEventualGet.bind(queryObject.getValues().toArray()));
518         } catch (Exception ex) {
519             logger.error("Exception", ex);
520             logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
521             throw new MusicServiceException(ex.getMessage());
522         }
523         return results;
524
525     }
526     */
527     public ResultSet executeGet(PreparedQueryObject queryObject,String consistencyLevel) throws MusicQueryException, MusicServiceException {
528         if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) {
529             logger.error(EELFLoggerDelegate.errorLogger, "",AppMessages.QUERYERROR+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
530             throw new MusicQueryException("Error processing Prepared Query Object for the request = " + "["
531                             + queryObject.getQuery() + "]");
532         }
533         ResultSet results = null;
534         try {
535             SimpleStatement statement = new SimpleStatement(queryObject.getQuery(), queryObject.getValues().toArray());
536
537             if (consistencyLevel.equalsIgnoreCase(CONSISTENCY_LEVEL_ONE)) {
538                 if(queryObject.getConsistency() == null) {
539                     statement.setConsistencyLevel(ConsistencyLevel.ONE);
540                 } else {
541                     statement.setConsistencyLevel(MusicUtil.getConsistencyLevel(queryObject.getConsistency()));
542                 }
543             }
544             else if (consistencyLevel.equalsIgnoreCase(CONSISTENCY_LEVEL_QUORUM)) {
545                 statement.setConsistencyLevel(ConsistencyLevel.QUORUM);
546             }
547
548             results = session.execute(statement);
549
550         } catch (Exception ex) {
551             logger.error(EELFLoggerDelegate.errorLogger, "Execute Get Error" + ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject
552                 .getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR, ex);
553             throw new MusicServiceException("Execute Get Error" + ex.getMessage());
554         }
555         
556         return results;
557         
558     }
559     
560     /**
561      * This method performs DDL operations on Cassandra using consistency level ONE.
562      * 
563      * @param queryObject Object containing cassandra prepared query and values.
564      */
565     public ResultSet executeOneConsistencyGet(PreparedQueryObject queryObject)
566                     throws MusicServiceException, MusicQueryException {
567         return executeGet(queryObject, CONSISTENCY_LEVEL_ONE);
568     }
569
570     /**
571      * 
572      * This method performs DDL operation on Cassandra using consistency level QUORUM.
573      * 
574      * @param queryObject Object containing cassandra prepared query and values.
575      */
576     public ResultSet executeQuorumConsistencyGet(PreparedQueryObject queryObject)
577                     throws MusicServiceException, MusicQueryException {
578         return executeGet(queryObject, CONSISTENCY_LEVEL_QUORUM);
579     }
580
581 }