2 * ============LICENSE_START========================================== org.onap.music
3 * =================================================================== Copyright (c) 2017 AT&T
4 * Intellectual Property ===================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
6 * in compliance with the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software distributed under the License
11 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12 * or implied. See the License for the specific language governing permissions and limitations under
15 * ============LICENSE_END=============================================
16 * ====================================================================
18 package org.onap.music.rest;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
24 import java.util.UUID;
25 import javax.servlet.http.HttpServletResponse;
26 import javax.ws.rs.Consumes;
27 import javax.ws.rs.DELETE;
28 import javax.ws.rs.GET;
29 import javax.ws.rs.HeaderParam;
30 import javax.ws.rs.POST;
31 import javax.ws.rs.PUT;
32 import javax.ws.rs.Path;
33 import javax.ws.rs.PathParam;
34 import javax.ws.rs.Produces;
35 import javax.ws.rs.core.Context;
36 import javax.ws.rs.core.MediaType;
37 import javax.ws.rs.core.MultivaluedMap;
38 import javax.ws.rs.core.UriInfo;
39 import org.onap.music.datastore.PreparedQueryObject;
40 import org.onap.music.datastore.jsonobjects.JsonDelete;
41 import org.onap.music.datastore.jsonobjects.JsonInsert;
42 import org.onap.music.datastore.jsonobjects.JsonKeySpace;
43 import org.onap.music.datastore.jsonobjects.JsonTable;
44 import org.onap.music.datastore.jsonobjects.JsonUpdate;
45 import org.onap.music.eelf.logging.EELFLoggerDelegate;
46 import org.onap.music.exceptions.MusicServiceException;
47 import org.onap.music.main.CachingUtil;
48 import org.onap.music.main.MusicCore;
49 import org.onap.music.main.MusicCore.Condition;
50 import org.onap.music.main.MusicUtil;
51 import org.onap.music.main.ResultType;
52 import org.onap.music.main.ReturnType;
53 import org.onap.music.response.jsonobjects.JsonResponse;
54 import com.datastax.driver.core.DataType;
55 import com.datastax.driver.core.ResultSet;
56 import com.datastax.driver.core.Row;
57 import com.datastax.driver.core.TableMetadata;
58 import io.swagger.annotations.Api;
59 import io.swagger.annotations.ApiOperation;
60 import io.swagger.annotations.ApiParam;
62 @Path("/v{version: [0-9]+}/keyspaces")
63 @Api(value = "Data Api")
64 public class RestMusicDataAPI {
66 * Header values for Versioning X-minorVersion *** - Used to request or communicate a MINOR
67 * version back from the client to the server, and from the server back to the client - This
68 * will be the MINOR version requested by the client, or the MINOR version of the last MAJOR
69 * version (if not specified by the client on the request) - Contains a single position value
70 * (e.g. if the full version is 1.24.5, X-minorVersion = "24") - Is optional for the client on
71 * request; however, this header should be provided if the client needs to take advantage of
72 * MINOR incremented version functionality - Is mandatory for the server on response
74 *** X-patchVersion *** - Used only to communicate a PATCH version in a response for
75 * troubleshooting purposes only, and will not be provided by the client on request - This will
76 * be the latest PATCH version of the MINOR requested by the client, or the latest PATCH version
77 * of the MAJOR (if not specified by the client on the request) - Contains a single position
78 * value (e.g. if the full version is 1.24.5, X-patchVersion = "5") - Is mandatory for the
81 *** X-latestVersion *** - Used only to communicate an API's latest version - Is mandatory for the
82 * server on response, and shall include the entire version of the API (e.g. if the full version
83 * is 1.24.5, X-latestVersion = "1.24.5") - Used in the response to inform clients that they are
84 * not using the latest version of the API
88 private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicDataAPI.class);
89 private static String xLatestVersion = "X-latestVersion";
91 private class RowIdentifier {
92 public String primarKeyValue;
93 public StringBuilder rowIdString;
94 @SuppressWarnings("unused")
95 public PreparedQueryObject queryObject;// the string with all the row
96 // identifiers separated by AND
98 public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString,
99 PreparedQueryObject queryObject) {
100 this.primarKeyValue = primaryKeyValue;
101 this.rowIdString = rowIdString;
102 this.queryObject = queryObject;
106 @SuppressWarnings("unused")
107 private String buildVersion(String major, String minor, String patch) {
109 major += "." + minor;
111 major += "." + patch;
118 * Create Keyspace REST
121 * @param keyspaceName
127 @ApiOperation(value = "Create Keyspace", response = String.class)
128 @Consumes(MediaType.APPLICATION_JSON)
129 @Produces(MediaType.APPLICATION_JSON)
130 public Map<String, Object> createKeySpace(
131 @ApiParam(value = "Major Version",
132 required = true) @PathParam("version") String version,
133 @ApiParam(value = "Minor Version",
134 required = false) @HeaderParam("X-minorVersion") String minorVersion,
135 @ApiParam(value = "Patch Version",
136 required = false) @HeaderParam("X-patchVersion") String patchVersion,
137 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
138 @ApiParam(value = "Application namespace",
139 required = true) @HeaderParam("ns") String ns,
140 @ApiParam(value = "userId",
141 required = true) @HeaderParam("userId") String userId,
142 @ApiParam(value = "Password",
143 required = true) @HeaderParam("password") String password,
144 JsonKeySpace kspObject,
145 @ApiParam(value = "Keyspace Name",
146 required = true) @PathParam("name") String keyspaceName,
147 @Context HttpServletResponse response) throws Exception {
148 Map<String, Object> resultMap = CachingUtil.verifyOnboarding(ns, userId, password);
149 response.addHeader(xLatestVersion, MusicUtil.getVersion());
150 if (!resultMap.isEmpty()) {
154 resultMap = MusicCore.autheticateUser(ns, userId, password, keyspaceName, aid,
156 String newAid = null;
157 if (!resultMap.isEmpty()) {
158 if (resultMap.containsKey("aid")) {
159 newAid = (String) resultMap.get("aid");
164 String consistency = MusicUtil.EVENTUAL;// for now this needs only
168 PreparedQueryObject queryObject = new PreparedQueryObject();
169 boolean result = false;
170 long start = System.currentTimeMillis();
171 Map<String, Object> replicationInfo = kspObject.getReplicationInfo();
172 String repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}";
173 queryObject.appendQueryString(
174 "CREATE KEYSPACE " + keyspaceName + " WITH replication = " + repString);
175 if (kspObject.getDurabilityOfWrites() != null) {
176 queryObject.appendQueryString(
177 " AND durable_writes = " + kspObject.getDurabilityOfWrites());
180 queryObject.appendQueryString(";");
181 long end = System.currentTimeMillis();
182 logger.info(EELFLoggerDelegate.applicationLogger,
183 "Time taken for setting up query in create keyspace:" + (end - start));
186 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
187 logger.error(EELFLoggerDelegate.errorLogger, "resulta = " + result);
188 } catch (Exception e) {
189 logger.error(EELFLoggerDelegate.errorLogger, e.getMessage());
190 resultMap.put("Exception", "Couldn't create keyspace. Please make sure all the information is correct.");
193 logger.debug("result = " + result);
195 resultMap.put("Status", String.valueOf(result));
196 if(!resultMap.containsKey("Exception"))
197 resultMap.put("Exception", "Keyspace already exists. Please contact admin.");
198 if (resultMap.get("uuid").equals("new")) {
199 queryObject = new PreparedQueryObject();
200 queryObject.appendQueryString(
201 "DELETE FROM admin.keyspace_master where uuid = " + newAid);
202 queryObject.appendQueryString(";");
203 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
204 resultMap.remove("aid");
205 resultMap.remove("uuid");
209 queryObject = new PreparedQueryObject();
210 queryObject.appendQueryString(
211 "UPDATE admin.keyspace_master SET keyspace_name=? where uuid = ?;");
212 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(),
213 MusicUtil.DEFAULTKEYSPACENAME));
214 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), newAid));
215 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
216 resultMap.remove("aid");
217 resultMap.remove("uuid");
223 queryObject = new PreparedQueryObject();
224 queryObject.appendQueryString("CREATE ROLE IF NOT EXISTS '" + userId
225 + "' WITH PASSWORD = '" + password + "' AND LOGIN = true;");
226 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
227 queryObject = new PreparedQueryObject();
228 queryObject.appendQueryString("GRANT ALL PERMISSIONS on KEYSPACE " + keyspaceName
229 + " to '" + userId + "'");
230 queryObject.appendQueryString(";");
231 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
232 } catch (Exception e) {
233 logger.error(EELFLoggerDelegate.errorLogger, e.getMessage());
235 resultMap.remove("uuid");
236 if (CachingUtil.isAAFApplication(ns))
237 resultMap.remove("aid");
238 resultMap.put("Status", String.valueOf(result));
246 * @param keyspaceName
252 @ApiOperation(value = "Delete Keyspace", response = String.class)
253 @Consumes(MediaType.APPLICATION_JSON)
254 @Produces(MediaType.APPLICATION_JSON)
255 public Map<String, Object> dropKeySpace(
256 @ApiParam(value = "Major Version",
257 required = true) @PathParam("version") String version,
258 @ApiParam(value = "Minor Version",
259 required = false) @HeaderParam("X-minorVersion") String minorVersion,
260 @ApiParam(value = "Patch Version",
261 required = false) @HeaderParam("X-patchVersion") String patchVersion,
262 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
263 @ApiParam(value = "Application namespace",
264 required = true) @HeaderParam("ns") String ns,
265 @ApiParam(value = "userId",
266 required = true) @HeaderParam("userId") String userId,
267 @ApiParam(value = "Password",
268 required = true) @HeaderParam("password") String password,
269 JsonKeySpace kspObject,
270 @ApiParam(value = "Keyspace Name",
271 required = true) @PathParam("name") String keyspaceName,
272 @Context HttpServletResponse response) throws Exception {
273 Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password,
274 keyspaceName, aid, "dropKeySpace");
275 response.addHeader(xLatestVersion, MusicUtil.getVersion());
276 if (resultMap.containsKey("aid"))
277 resultMap.remove("aid");
278 if (!resultMap.isEmpty()) {
282 String consistency = MusicUtil.EVENTUAL;// for now this needs only
285 String appName = CachingUtil.getAppName(keyspaceName);
286 String uuid = CachingUtil.getUuidFromMusicCache(keyspaceName);
287 PreparedQueryObject pQuery = new PreparedQueryObject();
288 pQuery.appendQueryString(
289 "select count(*) as count from admin.keyspace_master where application_name=? allow filtering;");
290 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName));
291 Row row = MusicCore.get(pQuery).one();
292 long count = row.getLong(0);
295 resultMap.put("Exception", "Keyspace not found. Please make sure keyspace exists.");
297 } else if (count == 1) {
298 pQuery = new PreparedQueryObject();
299 pQuery.appendQueryString(
300 "UPDATE admin.keyspace_master SET keyspace_name=? where uuid = ?;");
301 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),
302 MusicUtil.DEFAULTKEYSPACENAME));
303 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
304 MusicCore.nonKeyRelatedPut(pQuery, consistency);
306 pQuery = new PreparedQueryObject();
307 pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ?");
308 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
309 MusicCore.nonKeyRelatedPut(pQuery, consistency);
312 PreparedQueryObject queryObject = new PreparedQueryObject();
313 queryObject.appendQueryString("DROP KEYSPACE " + keyspaceName + ";");
314 return new JsonResponse(MusicCore.nonKeyRelatedPut(queryObject, consistency), "", "")
327 @Path("/{keyspace}/tables/{tablename}")
328 @ApiOperation(value = "Create Table", response = String.class)
329 @Consumes(MediaType.APPLICATION_JSON)
330 @Produces(MediaType.APPLICATION_JSON)
331 public Map<String, Object> createTable(
332 @ApiParam(value = "Major Version",
333 required = true) @PathParam("version") String version,
334 @ApiParam(value = "Minor Version",
335 required = false) @HeaderParam("X-minorVersion") String minorVersion,
336 @ApiParam(value = "Patch Version",
337 required = false) @HeaderParam("X-patchVersion") String patchVersion,
338 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
339 @ApiParam(value = "Application namespace",
340 required = true) @HeaderParam("ns") String ns,
341 @ApiParam(value = "userId",
342 required = true) @HeaderParam("userId") String userId,
343 @ApiParam(value = "Password",
344 required = true) @HeaderParam("password") String password,
346 @ApiParam(value = "Keyspace Name",
347 required = true) @PathParam("keyspace") String keyspace,
348 @ApiParam(value = "Table Name",
349 required = true) @PathParam("tablename") String tablename,
350 @Context HttpServletResponse response) throws Exception {
351 Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace,
353 response.addHeader(xLatestVersion, MusicUtil.getVersion());
354 if (resultMap.containsKey("aid"))
355 resultMap.remove("aid");
356 if (!resultMap.isEmpty()) {
359 String consistency = MusicUtil.EVENTUAL;
360 // for now this needs only eventual consistency
361 PreparedQueryObject queryObject = new PreparedQueryObject();
362 boolean result = false;
363 // first read the information about the table fields
364 Map<String, String> fields = tableObj.getFields();
365 StringBuilder fieldsString = new StringBuilder("(vector_ts text,");
368 for (Map.Entry<String, String> entry : fields.entrySet()) {
369 fieldsString.append("" + entry.getKey() + " " + entry.getValue() + "");
370 if (entry.getKey().equals("PRIMARY KEY")) {
371 primaryKey = entry.getValue().substring(entry.getValue().indexOf('(') + 1);
372 primaryKey = primaryKey.substring(0, primaryKey.indexOf(')'));
374 if (counter == fields.size() - 1)
375 fieldsString.append(")");
377 fieldsString.append(",");
378 counter = counter + 1;
380 // information about the name-value style properties
381 Map<String, Object> propertiesMap = tableObj.getProperties();
382 StringBuilder propertiesString = new StringBuilder();
383 if (propertiesMap != null) {
385 for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {
386 Object ot = entry.getValue();
387 String value = ot + "";
388 if (ot instanceof String) {
389 value = "'" + value + "'";
390 } else if (ot instanceof Map) {
391 @SuppressWarnings("unchecked")
392 Map<String, Object> otMap = (Map<String, Object>) ot;
393 value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}";
396 propertiesString.append(entry.getKey() + "=" + value + "");
397 if (counter != propertiesMap.size() - 1)
398 propertiesString.append(" AND ");
400 counter = counter + 1;
404 queryObject.appendQueryString(
405 "CREATE TABLE " + keyspace + "." + tablename + " " + fieldsString);
407 if (propertiesMap != null)
408 queryObject.appendQueryString(" WITH " + propertiesString);
410 queryObject.appendQueryString(";");
412 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
413 } catch (MusicServiceException ex) {
414 return new JsonResponse(false, ex.getMessage(), "").toMap();
417 return new JsonResponse(result, "", "").toMap();
429 @Path("/{keyspace}/tables/{tablename}/index/{field}")
430 @ApiOperation(value = "Create Index", response = String.class)
431 @Produces(MediaType.APPLICATION_JSON)
432 public Map<String, Object> createIndex(
433 @ApiParam(value = "Major Version",
434 required = true) @PathParam("version") String version,
435 @ApiParam(value = "Minor Version",
436 required = false) @HeaderParam("X-minorVersion") String minorVersion,
437 @ApiParam(value = "Patch Version",
438 required = false) @HeaderParam("X-patchVersion") String patchVersion,
439 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
440 @ApiParam(value = "Application namespace",
441 required = true) @HeaderParam("ns") String ns,
442 @ApiParam(value = "userId",
443 required = true) @HeaderParam("userId") String userId,
444 @ApiParam(value = "Password",
445 required = true) @HeaderParam("password") String password,
446 @ApiParam(value = "Keyspace Name",
447 required = true) @PathParam("keyspace") String keyspace,
448 @ApiParam(value = "Table Name",
449 required = true) @PathParam("tablename") String tablename,
450 @ApiParam(value = "Field Name",
451 required = true) @PathParam("field") String fieldName,
452 @Context UriInfo info, @Context HttpServletResponse response) throws Exception {
453 Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace,
455 response.addHeader(xLatestVersion, MusicUtil.getVersion());
456 if (resultMap.containsKey("aid"))
457 resultMap.remove("aid");
458 if (!resultMap.isEmpty())
460 MultivaluedMap<String, String> rowParams = info.getQueryParameters();
461 String indexName = "";
462 if (rowParams.getFirst("index_name") != null)
463 indexName = rowParams.getFirst("index_name");
464 PreparedQueryObject query = new PreparedQueryObject();
465 query.appendQueryString("Create index " + indexName + " if not exists on " + keyspace + "."
466 + tablename + " (" + fieldName + ");");
467 return new JsonResponse(MusicCore.nonKeyRelatedPut(query, "eventual"), "", "").toMap();
480 @Path("/{keyspace}/tables/{tablename}/rows")
481 @ApiOperation(value = "Insert Into Table", response = String.class)
482 @Consumes(MediaType.APPLICATION_JSON)
483 @Produces(MediaType.APPLICATION_JSON)
484 public Map<String, Object> insertIntoTable(
485 @ApiParam(value = "Major Version",
486 required = true) @PathParam("version") String version,
487 @ApiParam(value = "Minor Version",
488 required = false) @HeaderParam("X-minorVersion") String minorVersion,
489 @ApiParam(value = "Patch Version",
490 required = false) @HeaderParam("X-patchVersion") String patchVersion,
491 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
492 @ApiParam(value = "Application namespace",
493 required = true) @HeaderParam("ns") String ns,
494 @ApiParam(value = "userId",
495 required = true) @HeaderParam("userId") String userId,
496 @ApiParam(value = "Password",
497 required = true) @HeaderParam("password") String password,
499 @ApiParam(value = "Keyspace Name",
500 required = true) @PathParam("keyspace") String keyspace,
501 @ApiParam(value = "Table Name",
502 required = true) @PathParam("tablename") String tablename,
503 @Context HttpServletResponse response) throws Exception {
504 Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace,
505 aid, "insertIntoTable");
506 response.addHeader(xLatestVersion, MusicUtil.getVersion());
507 if (resultMap.containsKey("aid"))
508 resultMap.remove("aid");
509 if (!resultMap.isEmpty()) {
512 ReturnType result = null;
513 Map<String, Object> valuesMap = insObj.getValues();
514 PreparedQueryObject queryObject = new PreparedQueryObject();
515 TableMetadata tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename);
516 String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();
517 StringBuilder fieldsString = new StringBuilder("(vector_ts,");
519 String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
520 StringBuilder valueString = new StringBuilder("(" + "?" + ",");
521 queryObject.addValue(vectorTs);
523 String primaryKey = "";
525 for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
526 fieldsString.append("" + entry.getKey());
527 Object valueObj = entry.getValue();
528 if (primaryKeyName.equals(entry.getKey())) {
529 primaryKey = entry.getValue() + "";
530 primaryKey = primaryKey.replace("'", "''");
533 DataType colType = tableInfo.getColumn(entry.getKey()).getType();
535 Object formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
536 valueString.append("?");
537 queryObject.addValue(formattedValue);
539 if (counter == valuesMap.size() - 1) {
540 fieldsString.append(")");
541 valueString.append(")");
543 fieldsString.append(",");
544 valueString.append(",");
546 counter = counter + 1;
549 queryObject.appendQueryString("INSERT INTO " + keyspace + "." + tablename + " "
550 + fieldsString + " VALUES " + valueString);
552 String ttl = insObj.getTtl();
553 String timestamp = insObj.getTimestamp();
555 if ((ttl != null) && (timestamp != null)) {
556 logger.info(EELFLoggerDelegate.applicationLogger, "both there");
557 queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
558 queryObject.addValue(Integer.parseInt(ttl));
559 queryObject.addValue(Long.parseLong(timestamp));
562 if ((ttl != null) && (timestamp == null)) {
563 logger.info(EELFLoggerDelegate.applicationLogger, "ONLY TTL there");
564 queryObject.appendQueryString(" USING TTL ?");
565 queryObject.addValue(Integer.parseInt(ttl));
568 if ((ttl == null) && (timestamp != null)) {
569 logger.info(EELFLoggerDelegate.applicationLogger, "ONLY timestamp there");
570 queryObject.appendQueryString(" USING TIMESTAMP ?");
571 queryObject.addValue(Long.parseLong(timestamp));
574 queryObject.appendQueryString(";");
576 String consistency = insObj.getConsistencyInfo().get("type");
578 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) {
579 result = MusicCore.eventualPut(queryObject);
580 } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
581 String lockId = insObj.getConsistencyInfo().get("lockId");
582 result = MusicCore.criticalPut(keyspace, tablename, primaryKey, queryObject, lockId,
584 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
585 result = MusicCore.atomicPut(keyspace, tablename, primaryKey, queryObject, null);
588 else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) {
589 result = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, primaryKey, queryObject, null);
592 return (result != null) ? result.toMap()
593 : new ReturnType(ResultType.FAILURE,
594 "Null result - Please Contact admin").toMap();
595 } catch (Exception ex) {
596 logger.info(EELFLoggerDelegate.applicationLogger, ex.getMessage());
597 return new ReturnType(ResultType.FAILURE, ex.getMessage()).toMap();
611 @Path("/{keyspace}/tables/{tablename}/rows")
612 @ApiOperation(value = "Update Table", response = String.class)
613 @Consumes(MediaType.APPLICATION_JSON)
614 @Produces(MediaType.APPLICATION_JSON)
615 public Map<String, Object> updateTable(
616 @ApiParam(value = "Major Version",
617 required = true) @PathParam("version") String version,
618 @ApiParam(value = "Minor Version",
619 required = false) @HeaderParam("X-minorVersion") String minorVersion,
620 @ApiParam(value = "Patch Version",
621 required = false) @HeaderParam("X-patchVersion") String patchVersion,
622 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
623 @ApiParam(value = "Application namespace",
624 required = true) @HeaderParam("ns") String ns,
625 @ApiParam(value = "userId",
626 required = true) @HeaderParam("userId") String userId,
627 @ApiParam(value = "Password",
628 required = true) @HeaderParam("password") String password,
629 JsonUpdate updateObj,
630 @ApiParam(value = "Keyspace Name",
631 required = true) @PathParam("keyspace") String keyspace,
632 @ApiParam(value = "Table Name",
633 required = true) @PathParam("tablename") String tablename,
634 @Context UriInfo info, @Context HttpServletResponse response) throws Exception {
635 Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace,
637 response.addHeader(xLatestVersion, MusicUtil.getVersion());
638 if (resultMap.containsKey("aid"))
639 resultMap.remove("aid");
640 if (!resultMap.isEmpty()) {
643 long startTime = System.currentTimeMillis();
644 String operationId = UUID.randomUUID().toString();// just for infoging
646 String consistency = updateObj.getConsistencyInfo().get("type");
647 logger.info(EELFLoggerDelegate.applicationLogger, "--------------Music " + consistency
648 + " update-" + operationId + "-------------------------");
649 // obtain the field value pairs of the update
651 PreparedQueryObject queryObject = new PreparedQueryObject();
652 Map<String, Object> valuesMap = updateObj.getValues();
654 TableMetadata tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename);
655 if (tableInfo == null) {
656 return new ReturnType(ResultType.FAILURE,
657 "Table information not found. Please check input for table name= "
658 + keyspace + "." + tablename).toMap();
661 String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
662 StringBuilder fieldValueString = new StringBuilder("vector_ts=?,");
663 queryObject.addValue(vectorTs);
665 for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
666 Object valueObj = entry.getValue();
667 DataType colType = tableInfo.getColumn(entry.getKey()).getType();
668 Object valueString = MusicUtil.convertToActualDataType(colType, valueObj);
669 fieldValueString.append(entry.getKey() + "= ?");
670 queryObject.addValue(valueString);
671 if (counter != valuesMap.size() - 1)
672 fieldValueString.append(",");
673 counter = counter + 1;
675 String ttl = updateObj.getTtl();
676 String timestamp = updateObj.getTimestamp();
678 queryObject.appendQueryString("UPDATE " + keyspace + "." + tablename + " ");
679 if ((ttl != null) && (timestamp != null)) {
681 logger.info("both there");
682 queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
683 queryObject.addValue(Integer.parseInt(ttl));
684 queryObject.addValue(Long.parseLong(timestamp));
687 if ((ttl != null) && (timestamp == null)) {
688 logger.info("ONLY TTL there");
689 queryObject.appendQueryString(" USING TTL ?");
690 queryObject.addValue(Integer.parseInt(ttl));
693 if ((ttl == null) && (timestamp != null)) {
694 logger.info("ONLY timestamp there");
695 queryObject.appendQueryString(" USING TIMESTAMP ?");
696 queryObject.addValue(Long.parseLong(timestamp));
698 // get the row specifier
699 RowIdentifier rowId = null;
701 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
702 } catch (MusicServiceException ex) {
703 return new ReturnType(ResultType.FAILURE, ex.getMessage()).toMap();
706 queryObject.appendQueryString(
707 " SET " + fieldValueString + " WHERE " + rowId.rowIdString + ";");
709 // get the conditional, if any
710 Condition conditionInfo;
711 if (updateObj.getConditions() == null)
712 conditionInfo = null;
713 else {// to avoid parsing repeatedly, just send the select query to
715 PreparedQueryObject selectQuery = new PreparedQueryObject();
716 selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE "
717 + rowId.rowIdString + ";");
718 selectQuery.addValue(rowId.primarKeyValue);
719 conditionInfo = new MusicCore.Condition(updateObj.getConditions(), selectQuery);
722 ReturnType operationResult = null;
723 long jsonParseCompletionTime = System.currentTimeMillis();
725 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL))
726 operationResult = MusicCore.eventualPut(queryObject);
727 else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
728 String lockId = updateObj.getConsistencyInfo().get("lockId");
729 operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue,
730 queryObject, lockId, conditionInfo);
731 } else if (consistency.equalsIgnoreCase("atomic_delete_lock")) {
732 // this function is mainly for the benchmarks
733 operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename,
734 rowId.primarKeyValue, queryObject, conditionInfo);
735 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
736 operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue,
737 queryObject, conditionInfo);
739 long actualUpdateCompletionTime = System.currentTimeMillis();
741 long endTime = System.currentTimeMillis();
742 String timingString = "Time taken in ms for Music " + consistency + " update-" + operationId
743 + ":" + "|total operation time:" + (endTime - startTime)
744 + "|json parsing time:" + (jsonParseCompletionTime - startTime)
745 + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime)
748 if (operationResult != null && operationResult.getTimingInfo() != null) {
749 String lockManagementTime = operationResult.getTimingInfo();
750 timingString = timingString + lockManagementTime;
752 logger.info(EELFLoggerDelegate.applicationLogger, timingString);
753 return (operationResult != null) ? operationResult.toMap()
754 : new ReturnType(ResultType.FAILURE, "Null result - Please Contact admin")
768 @Path("/{keyspace}/tables/{tablename}/rows")
769 @ApiOperation(value = "Delete From table", response = String.class)
770 @Consumes(MediaType.APPLICATION_JSON)
771 @Produces(MediaType.APPLICATION_JSON)
772 public Map<String, Object> deleteFromTable(
773 @ApiParam(value = "Major Version",
774 required = true) @PathParam("version") String version,
775 @ApiParam(value = "Minor Version",
776 required = false) @HeaderParam("X-minorVersion") String minorVersion,
777 @ApiParam(value = "Patch Version",
778 required = false) @HeaderParam("X-patchVersion") String patchVersion,
779 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
780 @ApiParam(value = "Application namespace",
781 required = true) @HeaderParam("ns") String ns,
782 @ApiParam(value = "userId",
783 required = true) @HeaderParam("userId") String userId,
784 @ApiParam(value = "Password",
785 required = true) @HeaderParam("password") String password,
787 @ApiParam(value = "Keyspace Name",
788 required = true) @PathParam("keyspace") String keyspace,
789 @ApiParam(value = "Table Name",
790 required = true) @PathParam("tablename") String tablename,
791 @Context UriInfo info, @Context HttpServletResponse response) throws Exception {
792 Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace,
793 aid, "deleteFromTable");
794 response.addHeader(xLatestVersion, MusicUtil.getVersion());
795 if (resultMap.containsKey("aid"))
796 resultMap.remove("aid");
797 if (!resultMap.isEmpty()) {
800 PreparedQueryObject queryObject = new PreparedQueryObject();
801 StringBuilder columnString = new StringBuilder();
804 ArrayList<String> columnList = delObj.getColumns();
805 if (columnList != null) {
806 for (String column : columnList) {
807 columnString.append(column);
808 if (counter != columnList.size() - 1)
809 columnString.append(",");
810 counter = counter + 1;
814 // get the row specifier
815 RowIdentifier rowId = null;
817 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
818 } catch (MusicServiceException ex) {
819 return new ReturnType(ResultType.FAILURE, ex.getMessage()).toMap();
821 String rowSpec = rowId.rowIdString.toString();
823 if ((columnList != null) && (!rowSpec.isEmpty())) {
824 queryObject.appendQueryString("DELETE " + columnString + " FROM " + keyspace + "."
825 + tablename + " WHERE " + rowSpec + ";");
828 if ((columnList == null) && (!rowSpec.isEmpty())) {
829 queryObject.appendQueryString("DELETE FROM " + keyspace + "." + tablename + " WHERE "
833 if ((columnList != null) && (rowSpec.isEmpty())) {
834 queryObject.appendQueryString(
835 "DELETE " + columnString + " FROM " + keyspace + "." + rowSpec + ";");
838 // get the conditional, if any
839 Condition conditionInfo;
840 if (delObj.getConditions() == null)
841 conditionInfo = null;
842 else {// to avoid parsing repeatedly, just send the select query to
844 PreparedQueryObject selectQuery = new PreparedQueryObject();
845 selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE "
846 + rowId.rowIdString + ";");
847 selectQuery.addValue(rowId.primarKeyValue);
848 conditionInfo = new MusicCore.Condition(delObj.getConditions(), selectQuery);
851 String consistency = delObj.getConsistencyInfo().get("type");
853 ReturnType operationResult = null;
855 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL))
856 operationResult = MusicCore.eventualPut(queryObject);
857 else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
858 String lockId = delObj.getConsistencyInfo().get("lockId");
859 operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue,
860 queryObject, lockId, conditionInfo);
861 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
862 operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue,
863 queryObject, conditionInfo);
865 else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) {
866 operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, rowId.primarKeyValue,
867 queryObject, conditionInfo);
870 return operationResult.toMap();
871 } catch (NullPointerException e) {
872 return new ReturnType(ResultType.FAILURE, e.getMessage()).toMap();
884 @Path("/{keyspace}/tables/{tablename}")
885 @ApiOperation(value = "Drop Table", response = String.class)
886 @Consumes(MediaType.APPLICATION_JSON)
887 @Produces(MediaType.APPLICATION_JSON)
888 public Map<String, Object> dropTable(
889 @ApiParam(value = "Major Version",
890 required = true) @PathParam("version") String version,
891 @ApiParam(value = "Minor Version",
892 required = false) @HeaderParam("X-minorVersion") String minorVersion,
893 @ApiParam(value = "Patch Version",
894 required = false) @HeaderParam("X-patchVersion") String patchVersion,
895 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
896 @ApiParam(value = "Application namespace",
897 required = true) @HeaderParam("ns") String ns,
898 @ApiParam(value = "userId",
899 required = true) @HeaderParam("userId") String userId,
900 @ApiParam(value = "Password",
901 required = true) @HeaderParam("password") String password,
903 @ApiParam(value = "Keyspace Name",
904 required = true) @PathParam("keyspace") String keyspace,
905 @ApiParam(value = "Table Name",
906 required = true) @PathParam("tablename") String tablename,
907 @Context HttpServletResponse response) throws Exception {
908 Map<String, Object> resultMap =
909 MusicCore.autheticateUser(ns, userId, password, keyspace, aid, "dropTable");
910 response.addHeader(xLatestVersion, MusicUtil.getVersion());
911 if (resultMap.containsKey("aid"))
912 resultMap.remove("aid");
913 if (!resultMap.isEmpty()) {
916 String consistency = "eventual";// for now this needs only eventual
918 PreparedQueryObject query = new PreparedQueryObject();
919 query.appendQueryString("DROP TABLE " + keyspace + "." + tablename + ";");
921 return new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency), "", "").toMap();
922 } catch (MusicServiceException ex) {
923 return new JsonResponse(false, ex.getMessage(), "").toMap();
937 @Path("/{keyspace}/tables/{tablename}/rows/criticalget")
938 @ApiOperation(value = "Select Critical", response = Map.class)
939 @Consumes(MediaType.APPLICATION_JSON)
940 @Produces(MediaType.APPLICATION_JSON)
941 public Map<String, HashMap<String, Object>> selectCritical(
942 @ApiParam(value = "Major Version",
943 required = true) @PathParam("version") String version,
944 @ApiParam(value = "Minor Version",
945 required = false) @HeaderParam("X-minorVersion") String minorVersion,
946 @ApiParam(value = "Patch Version",
947 required = false) @HeaderParam("X-patchVersion") String patchVersion,
948 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
949 @ApiParam(value = "Application namespace",
950 required = true) @HeaderParam("ns") String ns,
951 @ApiParam(value = "userId",
952 required = true) @HeaderParam("userId") String userId,
953 @ApiParam(value = "Password",
954 required = true) @HeaderParam("password") String password,
956 @ApiParam(value = "Keyspace Name",
957 required = true) @PathParam("keyspace") String keyspace,
958 @ApiParam(value = "Table Name",
959 required = true) @PathParam("tablename") String tablename,
960 @Context UriInfo info, @Context HttpServletResponse response) throws Exception {
961 Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace,
962 aid, "selectCritical");
963 response.addHeader(xLatestVersion, MusicUtil.getVersion());
964 if (resultMap.containsKey("aid"))
965 resultMap.remove("aid");
966 if (!resultMap.isEmpty()) {
967 logger.error("Error while authentication... ");
968 HashMap<String, Object> tempMap = new HashMap<>();
969 tempMap.putAll(resultMap);
970 Map<String, HashMap<String, Object>> results = new HashMap<>();
971 results.put("Result", tempMap);
974 String lockId = selObj.getConsistencyInfo().get("lockId");
976 PreparedQueryObject queryObject = new PreparedQueryObject();
978 RowIdentifier rowId = null;
980 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
981 } catch (MusicServiceException ex) {
982 return MusicUtil.setErrorResponse(ex);
984 queryObject.appendQueryString(
985 "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowId.rowIdString + ";");
987 ResultSet results = null;
989 String consistency = selObj.getConsistencyInfo().get("type");
991 if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
992 results = MusicCore.criticalGet(keyspace, tablename, rowId.primarKeyValue, queryObject,
994 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
995 results = MusicCore.atomicGet(keyspace, tablename, rowId.primarKeyValue, queryObject);
998 else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) {
999 results = MusicCore.atomicGetWithDeleteLock(keyspace, tablename, rowId.primarKeyValue, queryObject);
1002 return MusicCore.marshallResults(results);
1014 @Path("/{keyspace}/tables/{tablename}/rows")
1015 @ApiOperation(value = "Select All or Select Specivic", response = Map.class)
1016 @Produces(MediaType.APPLICATION_JSON)
1017 public Map<String, HashMap<String, Object>> select(
1018 @ApiParam(value = "Major Version",
1019 required = true) @PathParam("version") String version,
1020 @ApiParam(value = "Minor Version",
1021 required = false) @HeaderParam("X-minorVersion") String minorVersion,
1022 @ApiParam(value = "Patch Version",
1023 required = false) @HeaderParam("X-patchVersion") String patchVersion,
1024 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
1025 @ApiParam(value = "Application namespace",
1026 required = true) @HeaderParam("ns") String ns,
1027 @ApiParam(value = "userId",
1028 required = true) @HeaderParam("userId") String userId,
1029 @ApiParam(value = "Password",
1030 required = true) @HeaderParam("password") String password,
1031 @ApiParam(value = "Keyspace Name",
1032 required = true) @PathParam("keyspace") String keyspace,
1033 @ApiParam(value = "Table Name",
1034 required = true) @PathParam("tablename") String tablename,
1035 @Context UriInfo info, @Context HttpServletResponse response) throws Exception {
1036 Map<String, Object> resultMap =
1037 MusicCore.autheticateUser(ns, userId, password, keyspace, aid, "select");
1038 response.addHeader(xLatestVersion, MusicUtil.getVersion());
1039 if (resultMap.containsKey("aid"))
1040 resultMap.remove("aid");
1041 if (!resultMap.isEmpty()) {
1042 logger.error("Error while authentication... ");
1043 HashMap<String, Object> tempMap = new HashMap<>();
1044 tempMap.putAll(resultMap);
1045 Map<String, HashMap<String, Object>> results = new HashMap<>();
1046 results.put("Result", tempMap);
1049 PreparedQueryObject queryObject = new PreparedQueryObject();
1051 if (info.getQueryParameters().isEmpty())// select all
1052 queryObject.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + ";");
1054 int limit = -1; // do not limit the number of results
1056 queryObject = selectSpecificQuery(version, minorVersion, patchVersion, aid, ns,
1057 userId, password, keyspace, tablename, info, limit);
1058 } catch (MusicServiceException ex) {
1059 return MusicUtil.setErrorResponse(ex);
1064 ResultSet results = MusicCore.get(queryObject);
1065 return MusicCore.marshallResults(results);
1066 } catch (MusicServiceException ex) {
1067 return MusicUtil.setErrorResponse(ex);
1079 * @throws MusicServiceException
1082 public PreparedQueryObject selectSpecificQuery(String version, String minorVersion,
1083 String patchVersion, String aid, String ns, String userId, String password,
1084 String keyspace, String tablename, UriInfo info, int limit)
1085 throws MusicServiceException {
1087 PreparedQueryObject queryObject = new PreparedQueryObject();
1088 StringBuilder rowIdString = getRowIdentifier(keyspace, tablename, info.getQueryParameters(),
1089 queryObject).rowIdString;
1091 queryObject.appendQueryString(
1092 "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowIdString);
1095 queryObject.appendQueryString(" LIMIT " + limit);
1098 queryObject.appendQueryString(";");
1108 * @param queryObject
1110 * @throws MusicServiceException
1113 private RowIdentifier getRowIdentifier(String keyspace, String tablename,
1114 MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject)
1115 throws MusicServiceException {
1116 StringBuilder rowSpec = new StringBuilder();
1118 TableMetadata tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename);
1119 if (tableInfo == null) {
1120 logger.error(EELFLoggerDelegate.errorLogger,
1121 "Table information not found. Please check input for table name= "
1122 + keyspace + "." + tablename);
1123 throw new MusicServiceException(
1124 "Table information not found. Please check input for table name= "
1125 + keyspace + "." + tablename);
1127 StringBuilder primaryKey = new StringBuilder();
1128 for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) {
1129 String keyName = entry.getKey();
1130 List<String> valueList = entry.getValue();
1131 String indValue = valueList.get(0);
1132 DataType colType = tableInfo.getColumn(entry.getKey()).getType();
1133 Object formattedValue = MusicUtil.convertToActualDataType(colType, indValue);
1134 primaryKey.append(indValue);
1135 rowSpec.append(keyName + "= ?");
1136 queryObject.addValue(formattedValue);
1137 if (counter != rowParams.size() - 1)
1138 rowSpec.append(" AND ");
1139 counter = counter + 1;
1141 return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject);