diff options
Diffstat (limited to 'music-core')
87 files changed, 14187 insertions, 0 deletions
diff --git a/music-core/pom.xml b/music-core/pom.xml new file mode 100755 index 00000000..cf7f59e9 --- /dev/null +++ b/music-core/pom.xml @@ -0,0 +1,459 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START========================================== + org.onap.music + =================================================================== + Copyright (c) 2017 AT&T Intellectual Property + =================================================================== + Modifications Copyright (c) 2019 IBM. + =================================================================== + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + ============LICENSE_END============================================= + ==================================================================== +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.onap.music</groupId> + <artifactId>MUSIC-core</artifactId> + <packaging>jar</packaging> + <version>3.2.40-SNAPSHOT</version> + <description> + This is the MUSIC core interface, packaged as a jar file. + </description> + <name>music-core</name> + + <parent> + <groupId>org.onap.music</groupId> + <artifactId>MUSIC</artifactId> + <version>3.2.40-SNAPSHOT</version> + </parent> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <java.version>1.8</java.version> + <jaxrs.version>2.0.1</jaxrs.version> + <cassandra.version>3.6.0</cassandra.version> + </properties> + + <repositories> + <repository> + <id>onap-releases</id> + <name>ONAP - Release Repository</name> + <url>${nexusproxy}/${releaseNexusPath}</url> + </repository> + <repository> + <id>onap-staging</id> + <name>ONAP - Staging Repository</name> + <url>${nexusproxy}/${stagingNexusPath}</url> + </repository> + <repository> + <id>onap-snapshots</id> + <name>ONAP - Snapshot Repository</name> + <url>${nexusproxy}/${snapshotNexusPath}</url> + </repository> + <repository> + <id>onap-public</id> + <name>ONAP public Repository</name> + <url>${nexusproxy}/content/groups/public</url> + </repository> + </repositories> + + <build> + <finalName>${project.artifactId}</finalName> + <sourceDirectory>src/main/java</sourceDirectory> + <outputDirectory>src/main/webapp/WEB-INF/classes</outputDirectory> + <testSourceDirectory>src/test/java</testSourceDirectory> + <testOutputDirectory>target/test-classes</testOutputDirectory> + <defaultGoal>validate</defaultGoal> + <resources> + <resource> + <directory>src/main/resources</directory> + <filtering>true</filtering> + <includes> + <include>**/*.properties</include> + <include>**/*.xml</include> + <include>**/*.ccf</include> + </includes> + </resource> + </resources> + <testResources> + <testResource> + <directory>${project.basedir}/src/test/resources</directory> + </testResource> + </testResources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-checkstyle-plugin</artifactId> + <configuration> + <skip>${maven.check.skip}</skip> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>2.4</version> + <executions> + <execution> + <id>make-a-jar</id> + <phase>compile</phase> + <goals> + <goal>jar</goal> + </goals> + <configuration> + <excludes> + <exclude>**/Sample*</exclude> + </excludes> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-install-plugin</artifactId> + <version>2.4</version> + <executions> + <execution> + <id>core</id> + <phase>install</phase> + <goals> + <goal>install-file</goal> + </goals> + <configuration> + <packaging>jar</packaging> + <artifactId>${project.artifactId}</artifactId> + <groupId>${project.groupId}</groupId> + <version>${project.version}</version> + <file>${project.build.directory}/${project.artifactId}.jar</file> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <dependencies> + <!-- Logging --> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-core</artifactId> + <version>1.2.3</version> + <exclusions> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + <version>1.2.3</version> + <exclusions> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>com.att.eelf</groupId> + <artifactId>eelf-core</artifactId> + <version>1.0.1-oss</version> + <exclusions> + <exclusion> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito</artifactId> + </exclusion> + <exclusion> + <groupId>org.powermock</groupId> + <artifactId>powermock-module-junit4</artifactId> + </exclusion> + </exclusions> + </dependency> + <!-- End Logging --> + <!-- Cassandra --> + <dependency> + <groupId>io.dropwizard.metrics</groupId> + <artifactId>metrics-core</artifactId> + <version>4.1.0-rc3</version> + </dependency> + <dependency> + <groupId>com.datastax.cassandra</groupId> + <artifactId>cassandra-driver-core</artifactId> + <version>${cassandra.version}</version> + </dependency> + <dependency> + <groupId>com.datastax.cassandra</groupId> + <artifactId>cassandra-driver-extras</artifactId> + <version>${cassandra.version}</version> + </dependency> + <!-- /Cassandra --> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-jcs-core</artifactId> + <version>2.2</version> + </dependency> + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + <version>1.11</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>3.8</version> + </dependency> + + <!-- Testing --> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.cassandraunit</groupId> + <artifactId>cassandra-unit-spring</artifactId> + <version>3.5.0.1</version> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </exclusion> + <exclusion> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-core</artifactId> + </exclusion> + <exclusion> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + </exclusion> + <exclusion> + <groupId>org.cassandraunit</groupId> + <artifactId>cassandra-unit</artifactId> + </exclusion> + <exclusion> + <groupId>io.dropwizard.metrics</groupId> + <artifactId>metrics-core</artifactId> + </exclusion> + <exclusion> + <groupId>com.addthis.metrics</groupId> + <artifactId>reporter-config-base</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.cassandraunit</groupId> + <artifactId>cassandra-unit-shaded</artifactId> + <version>3.5.0.1</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>2.23.4</version> + <scope>test</scope> + </dependency> + <!-- /Testing --> + <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-jsr310 --> + <dependency> + <groupId>com.fasterxml.jackson.datatype</groupId> + <artifactId>jackson-datatype-jsr310</artifactId> + <version>2.9.9</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>2.9.9.2</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + <version>2.9.9</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + <version>2.9.9</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + </dependency> + <dependency> + <groupId>io.swagger</groupId> + <artifactId>swagger-jersey-jaxrs</artifactId> + <version>1.5.22</version> + <exclusions> + <exclusion> + <groupId>com.sun.jersey.contribs</groupId> + <artifactId>jersey-multipart</artifactId> + </exclusion> + <exclusion> + <groupId>com.sun.jersey</groupId> + <artifactId>jersey-core</artifactId> + </exclusion> + <exclusion> + <groupId>javax.ws.rs</groupId> + <artifactId>jsr311-api</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>com.sun.jersey.contribs</groupId> + <artifactId>jersey-multipart</artifactId> + <version>1.19</version> + <exclusions> + <exclusion> + <groupId>javax.ws.rs</groupId> + <artifactId>jsr311-api</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>javax.ws.rs</groupId> + <artifactId>javax.ws.rs-api</artifactId> + <version>2.0.1</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </dependency> + <dependency> + <groupId>de.svenkubiak</groupId> + <artifactId>jBCrypt</artifactId> + <version>0.4.1</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-handler</artifactId> + <version>4.1.33.Final</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-buffer</artifactId> + <version>4.1.33.Final</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-codec</artifactId> + <version>4.1.33.Final</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-common</artifactId> + <version>4.1.33.Final</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-resolver</artifactId> + <version>4.1.33.Final</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-transport</artifactId> + <version>4.1.33.Final</version> + </dependency> + <dependency> + <groupId>org.onap.aaf.authz</groupId> + <artifactId>aaf-cadi-aaf</artifactId> + <version>2.1.7</version> + <exclusions> + <exclusion> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.onap.aaf.authz</groupId> + <artifactId>aaf-cadi-client</artifactId> + <version>2.1.7</version> + <exclusions> + <exclusion> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.onap.aaf.authz</groupId> + <artifactId>aaf-cadi-core</artifactId> + <version>2.1.7</version> + <exclusions> + <exclusion> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.8.5</version> + </dependency> + </dependencies> + + <reporting> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>2.10.3</version> + <configuration> + <author>true</author> + <breakiterator>true</breakiterator> + <version>true</version> + <links> + <link>https://docs.oracle.com/javase/7/docs/api/</link> + <link>https://tomcat.apache.org/tomcat-7.0-doc/jspapi/</link> + <link>http://docs.oracle.com/javaee/7/api/</link> + </links> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + </plugins> + </reporting> + + <distributionManagement> + <repository> + <id>ecomp-releases</id> + <name>Release Repository</name> + <url>${nexusproxy}/${releaseNexusPath}</url> + </repository> + <snapshotRepository> + <id>ecomp-snapshots</id> + <name>Snapshot Repository</name> + <url>${nexusproxy}/${snapshotNexusPath}</url> + </snapshotRepository> + <!-- added for javadoc --> + <site> + <id>ecomp-site</id> + <url>dav:${nexusproxy}${sitePath}</url> + </site> + </distributionManagement> +</project> diff --git a/music-core/src/main/java/LICENSE.txt b/music-core/src/main/java/LICENSE.txt new file mode 100644 index 00000000..cc6cdea5 --- /dev/null +++ b/music-core/src/main/java/LICENSE.txt @@ -0,0 +1,24 @@ + +The following license applies to all files in this and sub-directories. Licenses +are included in individual source files where appropriate, and if it differs +from this text, it supersedes this. Any file that does not have license text +defaults to being covered by this text; not all files support the addition of +licenses. +# +# ------------------------------------------------------------------------- +# Copyright (c) 2017 AT&T Intellectual Property +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------- +#
\ No newline at end of file diff --git a/music-core/src/main/java/org/onap/music/datastore/Condition.java b/music-core/src/main/java/org/onap/music/datastore/Condition.java new file mode 100644 index 00000000..c17d9c07 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/datastore/Condition.java @@ -0,0 +1,63 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore; + +import java.util.Map; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.MusicCore; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; + +public class Condition { + private Map<String, Object> conditions; + private PreparedQueryObject selectQueryForTheRow; + + public Condition(Map<String, Object> conditions, PreparedQueryObject selectQueryForTheRow) { + this.conditions = conditions; + this.selectQueryForTheRow = selectQueryForTheRow; + } + + public boolean testCondition() throws Exception { + // first generate the row + ResultSet results = quorumGet(selectQueryForTheRow); + Row row = null; + if(results != null) { + row = results.one(); + } + if(row == null) { + throw new Exception(" No data found to update"); + } + return getDSHandle().doesRowSatisfyCondition(row, conditions); + } + + /* For JUnit testing only */ + public ResultSet quorumGet(PreparedQueryObject selectQueryForTheRow) { + return MusicCore.quorumGet(selectQueryForTheRow); + } + + /* For JUnit testing only */ + public MusicDataStore getDSHandle() throws MusicServiceException { + return MusicDataStoreHandle.getDSHandle(); + } + }
\ No newline at end of file diff --git a/music-core/src/main/java/org/onap/music/datastore/MusicDataStore.java b/music-core/src/main/java/org/onap/music/datastore/MusicDataStore.java new file mode 100755 index 00000000..9ce73cc8 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/datastore/MusicDataStore.java @@ -0,0 +1,540 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (c) 2018-2019 IBM + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore; + +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.lockingservice.cassandra.LockType; +import org.onap.music.main.CipherUtil; +import org.onap.music.main.MusicUtil; +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.ColumnDefinitions; +import com.datastax.driver.core.ColumnDefinitions.Definition; +import com.datastax.driver.core.ConsistencyLevel; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.HostDistance; +import com.datastax.driver.core.KeyspaceMetadata; +import com.datastax.driver.core.Metadata; +import com.datastax.driver.core.PoolingOptions; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.SimpleStatement; +import com.datastax.driver.core.SocketOptions; +import com.datastax.driver.core.TableMetadata; +import com.datastax.driver.core.exceptions.AlreadyExistsException; +import com.datastax.driver.core.exceptions.InvalidQueryException; +import com.datastax.driver.extras.codecs.enums.EnumNameCodec; + +/** + * @author nelson24 + * + */ +public class MusicDataStore { + + public static final String CONSISTENCY_LEVEL_ONE = "ONE"; + public static final String CONSISTENCY_LEVEL_QUORUM = "QUORUM"; + public static final String CONSISTENCY_LEVEL_LOCAL_QUORUM = "LOCAL_QUORUM"; + private Session session; + private Cluster cluster; + + + /** + * Connect to default Cassandra address + */ + public MusicDataStore() { + try { + connectToCassaCluster(MusicUtil.getMyCassaHost()); + } catch (MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), e); + } + } + + + /** + * @param cluster + * @param session + */ + public MusicDataStore(Cluster cluster, Session session) { + this.session = session; + setCluster(cluster); + } + + + /** + * @param session + */ + public void setSession(Session session) { + this.session = session; + } + + /** + * @param session + */ + public Session getSession() { + return session; + } + + /** + * @param cluster + */ + public void setCluster(Cluster cluster) { + EnumNameCodec<LockType> lockTypeCodec = new EnumNameCodec<LockType>(LockType.class); + cluster.getConfiguration().getCodecRegistry().register(lockTypeCodec); + + this.cluster = cluster; + } + + public Cluster getCluster() { + return this.cluster; + } + + + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicDataStore.class); + + + /** + * + * @param remoteIp + * @throws MusicServiceException + */ + public MusicDataStore(String remoteIp) { + try { + connectToCassaCluster(remoteIp); + } catch (MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), e); + } + } + + /** + * + */ + public void close() { + session.close(); + } + + /** + * This method connects to cassandra cluster on specific address. + * + * @param address + */ + private void connectToCassaCluster(String address) throws MusicServiceException { + String[] addresses = null; + addresses = address.split(","); + PoolingOptions poolingOptions = new PoolingOptions(); + poolingOptions + .setConnectionsPerHost(HostDistance.LOCAL, 4, 10) + .setConnectionsPerHost(HostDistance.REMOTE, 2, 4); + + Cluster cluster; + if(MusicUtil.getCassName() != null && MusicUtil.getCassPwd() != null) { + String cassPwd; + if (MusicUtil.getCipherEncKey() != null && !("").equals(MusicUtil.getCipherEncKey())) { + cassPwd = CipherUtil.decryptPKC(MusicUtil.getCassPwd()); + } else { + cassPwd = MusicUtil.getCassPwd(); + } + logger.info(EELFLoggerDelegate.applicationLogger, + "Building with credentials "+MusicUtil.getCassName()+" & "+ MusicUtil.getCassPwd()); + cluster = Cluster.builder().withPort(MusicUtil.getCassandraPort()) + .withCredentials(MusicUtil.getCassName(), cassPwd) + //.withLoadBalancingPolicy(new RoundRobinPolicy()) + .withoutJMXReporting() + .withPoolingOptions(poolingOptions) + .withSocketOptions( + new SocketOptions().setConnectTimeoutMillis(MusicUtil.getCassandraConnectTimeOutMS()) + .setReadTimeoutMillis(MusicUtil.getCassandraReadTimeOutMS())) + .addContactPoints(addresses).build(); + } else { + cluster = Cluster.builder().withPort(MusicUtil.getCassandraPort()) + .withoutJMXReporting() + .withPoolingOptions(poolingOptions) + .withSocketOptions(new SocketOptions() + .setConnectTimeoutMillis(MusicUtil.getCassandraConnectTimeOutMS()) + .setReadTimeoutMillis(MusicUtil.getCassandraReadTimeOutMS())) + .addContactPoints(addresses) + .build(); + } + + this.setCluster(cluster); + Metadata metadata = this.cluster.getMetadata(); + logger.info(EELFLoggerDelegate.applicationLogger, "Connected to cassa cluster " + + metadata.getClusterName() + " at " + address); + + try { + session = this.cluster.connect(); + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.CASSANDRACONNECTIVITY, + ErrorSeverity.ERROR, ErrorTypes.SERVICEUNAVAILABLE, ex); + throw new MusicServiceException( + "Error while connecting to Cassandra cluster.. " + ex.getMessage()); + } + } + + /** + * + * @param keyspace + * @param tableName + * @param columnName + * @return DataType + */ + public DataType returnColumnDataType(String keyspace, String tableName, String columnName) { + KeyspaceMetadata ks = cluster.getMetadata().getKeyspace(keyspace); + TableMetadata table = ks.getTable(tableName); + return table.getColumn(columnName).getType(); + + } + + /** + * + * @param keyspace + * @param tableName + * @return TableMetadata + */ + public TableMetadata returnColumnMetadata(String keyspace, String tableName) { + KeyspaceMetadata ks = cluster.getMetadata().getKeyspace(keyspace); + return ks.getTable(tableName); + } + + /** + * + * @param keyspace + * @param tableName + * @return TableMetadata + */ + public KeyspaceMetadata returnKeyspaceMetadata(String keyspace) { + return cluster.getMetadata().getKeyspace(keyspace); + } + + + /** + * Utility function to return the Java specific object type. + * + * @param row + * @param colName + * @param colType + * @return + */ + public Object getColValue(Row row, String colName, DataType colType) { + + switch (colType.getName()) { + case VARCHAR: + return row.getString(colName); + case UUID: + return row.getUUID(colName); + case VARINT: + return row.getVarint(colName); + case BIGINT: + return row.getLong(colName); + case INT: + return row.getInt(colName); + case FLOAT: + return row.getFloat(colName); + case DOUBLE: + return row.getDouble(colName); + case BOOLEAN: + return row.getBool(colName); + case MAP: + return row.getMap(colName, String.class, String.class); + case LIST: + return row.getList(colName, String.class); + default: + return null; + } + } + + public byte[] getBlobValue(Row row, String colName, DataType colType) { + ByteBuffer bb = row.getBytes(colName); + return bb.array(); + } + + public boolean doesRowSatisfyCondition(Row row, Map<String, Object> condition) throws Exception { + ColumnDefinitions colInfo = row.getColumnDefinitions(); + + for (Map.Entry<String, Object> entry : condition.entrySet()) { + String colName = entry.getKey(); + DataType colType = colInfo.getType(colName); + Object columnValue = getColValue(row, colName, colType); + Object conditionValue = MusicUtil.convertToActualDataType(colType, entry.getValue()); + if (columnValue.equals(conditionValue) == false) + return false; + } + return true; + } + + /** + * Utility function to store ResultSet values in to a MAP for output. + * + * @param results + * @return MAP + */ + public Map<String, HashMap<String, Object>> marshalData(ResultSet results) { + Map<String, HashMap<String, Object>> resultMap = + new HashMap<>(); + int counter = 0; + for (Row row : results) { + ColumnDefinitions colInfo = row.getColumnDefinitions(); + HashMap<String, Object> resultOutput = new HashMap<>(); + for (Definition definition : colInfo) { + if (!(("vector_ts").equals(definition.getName()))) { + if(definition.getType().toString().toLowerCase().contains("blob")) { + resultOutput.put(definition.getName(), + getBlobValue(row, definition.getName(), definition.getType())); + } else { + resultOutput.put(definition.getName(), + getColValue(row, definition.getName(), definition.getType())); + } + } + } + resultMap.put("row " + counter, resultOutput); + counter++; + } + return resultMap; + } + + + // Prepared Statements 1802 additions + + public boolean executePut(PreparedQueryObject queryObject, String consistency) + throws MusicServiceException, MusicQueryException { + return executePut(queryObject, consistency, 0); + } + /** + * This Method performs DDL and DML operations on Cassandra using specified consistency level + * + * @param queryObject Object containing cassandra prepared query and values. + * @param consistency Specify consistency level for data synchronization across cassandra + * replicas + * @return Boolean Indicates operation success or failure + * @throws MusicServiceException + * @throws MusicQueryException + */ + public boolean executePut(PreparedQueryObject queryObject, String consistency,long timeSlot) + throws MusicServiceException, MusicQueryException { + + boolean result = false; + long timeOfWrite = System.currentTimeMillis(); + if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) { + logger.error(EELFLoggerDelegate.errorLogger, queryObject.getQuery(),AppMessages.QUERYERROR, ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicQueryException("Ill formed queryObject for the request = " + "[" + + queryObject.getQuery() + "]"); + } + logger.debug(EELFLoggerDelegate.applicationLogger, + "In preprared Execute Put: the actual insert query:" + + queryObject.getQuery() + "; the values" + + queryObject.getValues()); + SimpleStatement preparedInsert = null; + + try { + preparedInsert = new SimpleStatement(queryObject.getQuery(), queryObject.getValues().toArray()); + if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + logger.info(EELFLoggerDelegate.applicationLogger, "Executing critical put query"); + preparedInsert.setConsistencyLevel(ConsistencyLevel.QUORUM); + } else if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) { + logger.info(EELFLoggerDelegate.applicationLogger, "Executing simple put query"); + if(queryObject.getConsistency() == null) + preparedInsert.setConsistencyLevel(ConsistencyLevel.ONE); + else + preparedInsert.setConsistencyLevel(MusicUtil.getConsistencyLevel(queryObject.getConsistency())); + } else if (consistency.equalsIgnoreCase(MusicUtil.ONE)) { + preparedInsert.setConsistencyLevel(ConsistencyLevel.ONE); + } else if (consistency.equalsIgnoreCase(MusicUtil.QUORUM)) { + preparedInsert.setConsistencyLevel(ConsistencyLevel.LOCAL_QUORUM); + } else if (consistency.equalsIgnoreCase(MusicUtil.ALL)) { + preparedInsert.setConsistencyLevel(ConsistencyLevel.ALL); + } + long timestamp = MusicUtil.v2sTimeStampInMicroseconds(timeSlot, timeOfWrite); + preparedInsert.setDefaultTimestamp(timestamp); + + ResultSet rs = session.execute(preparedInsert); + result = rs.wasApplied(); + } catch (AlreadyExistsException ae) { + throw new MusicServiceException("Already Exists Exception: " + ae.getMessage()); + } catch (InvalidQueryException e) { + if (e.getMessage().contains("unconfigured table")) { + throw new MusicServiceException("Invalid Query Exception: " + e.getMessage()); + } else { + logger.info(EELFLoggerDelegate.applicationLogger, "Query Exception: " + e.getMessage(), + AppMessages.SESSIONFAILED + " [" + queryObject.getQuery() + "]", ErrorSeverity.INFO, + ErrorTypes.QUERYERROR, e); + throw new MusicServiceException("Query Exception: " + e.getMessage()); + } + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), + AppMessages.SESSIONFAILED + " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, + ErrorTypes.QUERYERROR, e); + throw new MusicServiceException("Executing Session Failure for Request = " + "[" + queryObject.getQuery() + + "]" + " Reason = " + e.getMessage()); + } + + return result; + } + + /* *//** + * This method performs DDL operations on Cassandra using consistency level ONE. + * + * @param queryObject Object containing cassandra prepared query and values. + * @return ResultSet + * @throws MusicServiceException + * @throws MusicQueryException + *//* + public ResultSet executeEventualGet(PreparedQueryObject queryObject) + throws MusicServiceException, MusicQueryException { + CacheAccess<String, PreparedStatement> queryBank = CachingUtil.getStatementBank(); + PreparedStatement preparedEventualGet = null; + if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) { + logger.error(EELFLoggerDelegate.errorLogger, "",AppMessages.QUERYERROR+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicQueryException("Ill formed queryObject for the request = " + "[" + + queryObject.getQuery() + "]"); + } + logger.info(EELFLoggerDelegate.applicationLogger, + "Executing Eventual get query:" + queryObject.getQuery()); + + ResultSet results = null; + try { + if(queryBank.get(queryObject.getQuery()) != null ) + preparedEventualGet=queryBank.get(queryObject.getQuery()); + else { + preparedEventualGet = session.prepare(queryObject.getQuery()); + CachingUtil.updateStatementBank(queryObject.getQuery(), preparedEventualGet); + } + if(queryObject.getConsistency() == null) { + preparedEventualGet.setConsistencyLevel(ConsistencyLevel.ONE); + } else { + preparedEventualGet.setConsistencyLevel(MusicUtil.getConsistencyLevel(queryObject.getConsistency())); + } + results = session.execute(preparedEventualGet.bind(queryObject.getValues().toArray())); + + } catch (Exception ex) { + logger.error("Exception", ex); + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicServiceException(ex.getMessage()); + } + return results; + } + + *//** + * + * This method performs DDL operation on Cassandra using consistency level QUORUM. + * + * @param queryObject Object containing cassandra prepared query and values. + * @return ResultSet + * @throws MusicServiceException + * @throws MusicQueryException + *//* + public ResultSet executeCriticalGet(PreparedQueryObject queryObject) + throws MusicServiceException, MusicQueryException { + if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) { + logger.error(EELFLoggerDelegate.errorLogger, "",AppMessages.QUERYERROR+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicQueryException("Error processing Prepared Query Object for the request = " + "[" + + queryObject.getQuery() + "]"); + } + logger.info(EELFLoggerDelegate.applicationLogger, + "Executing Critical get query:" + queryObject.getQuery()); + PreparedStatement preparedEventualGet = session.prepare(queryObject.getQuery()); + preparedEventualGet.setConsistencyLevel(ConsistencyLevel.QUORUM); + ResultSet results = null; + try { + results = session.execute(preparedEventualGet.bind(queryObject.getValues().toArray())); + } catch (Exception ex) { + logger.error("Exception", ex); + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicServiceException(ex.getMessage()); + } + return results; + + } + */ + public ResultSet executeGet(PreparedQueryObject queryObject,String consistencyLevel) throws MusicQueryException, MusicServiceException { + if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) { + logger.error(EELFLoggerDelegate.errorLogger, "",AppMessages.QUERYERROR+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicQueryException("Error processing Prepared Query Object for the request = " + "[" + + queryObject.getQuery() + "]"); + } + ResultSet results = null; + try { + SimpleStatement statement = new SimpleStatement(queryObject.getQuery(), queryObject.getValues().toArray()); + if (consistencyLevel.equalsIgnoreCase(CONSISTENCY_LEVEL_ONE)) { + statement.setConsistencyLevel(ConsistencyLevel.ONE); + } else if (consistencyLevel.equalsIgnoreCase(CONSISTENCY_LEVEL_QUORUM)) { + statement.setConsistencyLevel(ConsistencyLevel.QUORUM); + } else if (consistencyLevel.equalsIgnoreCase(CONSISTENCY_LEVEL_LOCAL_QUORUM)) { + statement.setConsistencyLevel(ConsistencyLevel.LOCAL_QUORUM); + } + + results = session.execute(statement); + + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger, "Execute Get Error" + ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject + .getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR, ex); + throw new MusicServiceException("Execute Get Error" + ex.getMessage()); + } + + return results; + + } + + /** + * This method performs DDL operations on Cassandra using consistency level ONE. + * + * @param queryObject Object containing cassandra prepared query and values. + */ + public ResultSet executeOneConsistencyGet(PreparedQueryObject queryObject) + throws MusicServiceException, MusicQueryException { + return executeGet(queryObject, CONSISTENCY_LEVEL_ONE); + } + + /** + * + * This method performs DDL operation on Cassandra using consistency level LOCAL_QUORUM. + * + * @param queryObject Object containing cassandra prepared query and values. + */ + public ResultSet executeLocalQuorumConsistencyGet(PreparedQueryObject queryObject) + throws MusicServiceException, MusicQueryException { + return executeGet(queryObject, CONSISTENCY_LEVEL_LOCAL_QUORUM); + } + + /** + * + * This method performs DDL operation on Cassandra using consistency level QUORUM. + * + * @param queryObject Object containing cassandra prepared query and values. + */ + public ResultSet executeQuorumConsistencyGet(PreparedQueryObject queryObject) + throws MusicServiceException, MusicQueryException { + return executeGet(queryObject, CONSISTENCY_LEVEL_QUORUM); + } + +} diff --git a/music-core/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java b/music-core/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java new file mode 100644 index 00000000..09fe0d35 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java @@ -0,0 +1,127 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * Modifications Copyright (C) 2019 IBM. + * =================================================================== + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore; + +import java.util.HashMap; +import java.util.Map; + +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.MusicUtil; + +import com.datastax.driver.core.KeyspaceMetadata; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.TableMetadata; + +public class MusicDataStoreHandle { + + private static MusicDataStore mDstoreHandle = null; + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicDataStoreHandle.class); + + private MusicDataStoreHandle(){ + throw new IllegalStateException("Utility class"); + } + + /** + * + * @param remoteIp + * @return + */ + public static MusicDataStore getDSHandle(String remoteIp) { + logger.info(EELFLoggerDelegate.metricsLogger,"Acquiring data store handle"); + long start = System.currentTimeMillis(); + if (mDstoreHandle == null) { + mDstoreHandle = new MusicDataStore(remoteIp); + } + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.metricsLogger,"Time taken to acquire data store handle:" + (end - start) + " ms"); + return mDstoreHandle; + } + + /** + * + * @return + * @throws MusicServiceException + */ + public static MusicDataStore getDSHandle() throws MusicServiceException { + logger.info(EELFLoggerDelegate.metricsLogger,"Acquiring data store handle"); + long start = System.currentTimeMillis(); + if (mDstoreHandle == null) { + // Quick Fix - Best to put this into every call to getDSHandle? + if (!"localhost".equals(MusicUtil.getMyCassaHost())) { + mDstoreHandle = new MusicDataStore(MusicUtil.getMyCassaHost()); + } else { + mDstoreHandle = new MusicDataStore(); + } + } + if(mDstoreHandle.getSession() == null) { + String message = "Connection to Cassandra has not been enstablished." + + " Please check connection properites and reboot."; + logger.info(EELFLoggerDelegate.applicationLogger, message); + throw new MusicServiceException(message); + } + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.metricsLogger,"Time taken to acquire data store handle:" + (end - start) + " ms"); + return mDstoreHandle; + } + + public static void setMDstoreHandle(MusicDataStore dsHandle) { + mDstoreHandle = dsHandle; + } + + /** + * + * @param keyspace + * @param tablename + * @return + * @throws MusicServiceException + */ + public static TableMetadata returnColumnMetadata(String keyspace, String tablename) throws MusicServiceException { + return getDSHandle().returnColumnMetadata(keyspace, tablename); + } + + /** + * + * @param keyspace + * @param tablename + * @return + * @throws MusicServiceException + */ + public static KeyspaceMetadata returnkeyspaceMetadata(String keyspace) throws MusicServiceException { + return getDSHandle().returnKeyspaceMetadata(keyspace); + } + + /** + * + * @param results + * @return + * @throws MusicServiceException + */ + public static Map<String, HashMap<String, Object>> marshallResults(ResultSet results) throws MusicServiceException { + return getDSHandle().marshalData(results); + } + +} diff --git a/music-core/src/main/java/org/onap/music/datastore/PreparedQueryObject.java b/music-core/src/main/java/org/onap/music/datastore/PreparedQueryObject.java new file mode 100644 index 00000000..fdac50be --- /dev/null +++ b/music-core/src/main/java/org/onap/music/datastore/PreparedQueryObject.java @@ -0,0 +1,176 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017-2019 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author srupane + * + */ +public class PreparedQueryObject { + + + private List<Object> values; + private StringBuilder query; + private String consistency; + private String keyspaceName; + private String tableName; + private String operation; + private String primaryKeyValue; + + + /** + * Create PreparedQueryObject + */ + public PreparedQueryObject() { + this.values = new ArrayList<>(); + this.query = new StringBuilder(); + } + + /** + * Create PreparedQueryObject + * @param query query portion of the prepared query + */ + public PreparedQueryObject(String query) { + this.values = new ArrayList<>(); + this.query = new StringBuilder(query); + } + + /** + * Create PreparedQueryObject + * @param query query portion of the prepared query + * @param values to be added to the query string as prepared query + */ + public PreparedQueryObject(String query, Object...values) { + this.query = new StringBuilder(query); + this.values = new ArrayList<>(); + for (Object value: values) { + this.values.add(value); + } + } + + public String getKeyspaceName() { + return keyspaceName; + } + + public void setKeyspaceName(String keyspaceName) { + this.keyspaceName = keyspaceName; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + public String getOperation() { + if (operation!=null) return operation; + if (query.length()==0) return null; + String queryStr = query.toString().toLowerCase(); + String firstOp = null; + int firstOpChar = query.length(); + if (queryStr.indexOf("insert")>-1 && queryStr.indexOf("insert")<firstOpChar) { + firstOp = "insert"; + firstOpChar = queryStr.indexOf("insert"); + } + if (queryStr.indexOf("update")>-1 && queryStr.indexOf("update")<firstOpChar) { + firstOp = "update"; + firstOpChar = queryStr.indexOf("update"); + } + if (queryStr.indexOf("delete")>-1 && queryStr.indexOf("delete")<firstOpChar) { + firstOp = "delete"; + firstOpChar = queryStr.indexOf("delete"); + } + if (queryStr.indexOf("select")>-1 && queryStr.indexOf("select")<firstOpChar) { + firstOp = "select"; + firstOpChar = queryStr.indexOf("select"); + } + return firstOp; + } + + public void setOperation(String operation) { + this.operation = operation; + } + + public String getPrimaryKeyValue() { + return primaryKeyValue; + } + + public void setPrimaryKeyValue(String primaryKeyValue) { + this.primaryKeyValue = primaryKeyValue; + } + + public String getConsistency() { + return consistency; + } + + public void setConsistency(String consistency) { + this.consistency = consistency; + } + + /** + * @return values to be set as part of the prepared query + */ + public List<Object> getValues() { + return values; + } + + /** + * @param o object to be added as a value to the prepared query, in order + */ + public void addValue(Object o) { + this.values.add(o); + } + + /** + * Add values to the preparedQuery + * @param objs ordered list of objects to be added as values to the prepared query + */ + public void addValues(Object... objs) { + for (Object obj: objs) { + this.values.add(obj); + } + } + + /** + * @param s + */ + public void appendQueryString(String s) { + this.query.append(s); + } + public void replaceQueryString(String s) { + this.query.replace(0, query.length(), s); + } + + /** + * @return the query + */ + public String getQuery() { + return this.query.toString(); + } +} diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JSONObject.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JSONObject.java new file mode 100644 index 00000000..a1524cc6 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JSONObject.java @@ -0,0 +1,37 @@ +package org.onap.music.datastore.jsonobjects; +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + + +public class JSONObject { + + private String data; + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + +} diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java new file mode 100644 index 00000000..988ba3a8 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java @@ -0,0 +1,313 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * Modifications Copyright (C) 2019 IBM + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore.jsonobjects; + +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response.Status; + +import org.onap.music.datastore.Condition; +import org.onap.music.datastore.MusicDataStoreHandle; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.MusicUtil; + +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.TableMetadata; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "JsonTable", description = "Json model for delete") +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonDelete { + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonDelete.class); + + private List<String> columns = null; + private Map<String, String> consistencyInfo; + private Map<String, Object> conditions; + private String ttl; + private String timestamp; + private String keyspaceName; + private String tableName; + private StringBuilder rowIdString; + private String primarKeyValue; + + + @ApiModelProperty(value = "Conditions") + public Map<String, Object> getConditions() { + return conditions; + } + + public void setConditions(Map<String, Object> conditions) { + this.conditions = conditions; + } + + @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic") + public Map<String, String> getConsistencyInfo() { + return consistencyInfo; + } + + public void setConsistencyInfo(Map<String, String> consistencyInfo) { + this.consistencyInfo = consistencyInfo; + } + + @ApiModelProperty(value = "Column values") + public List<String> getColumns() { + return columns; + } + + public void setColumns(List<String> columns) { + this.columns = columns; + } + + + @ApiModelProperty(value = "Time to live information") + public String getTtl() { + return ttl; + } + + public void setTtl(String ttl) { + this.ttl = ttl; + } + + @ApiModelProperty(value = "Time stamp") + public String getTimestamp() { + return timestamp; + } + + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } + + public String getKeyspaceName() { + return keyspaceName; + } + + public void setKeyspaceName(String keyspaceName) { + this.keyspaceName = keyspaceName; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + public StringBuilder getRowIdString() { + return rowIdString; + } + + public void setRowIdString(StringBuilder rowIdString) { + this.rowIdString = rowIdString; + } + + public String getPrimarKeyValue() { + return primarKeyValue; + } + + public void setPrimarKeyValue(String primarKeyValue) { + this.primarKeyValue = primarKeyValue; + } + + + public PreparedQueryObject genDeletePreparedQueryObj(MultivaluedMap<String, String> rowParams) throws MusicQueryException { + if (logger.isDebugEnabled()) { + logger.debug("Coming inside genUpdatePreparedQueryObj method " + this.getKeyspaceName()); + logger.debug("Coming inside genUpdatePreparedQueryObj method " + this.getTableName()); + } + + PreparedQueryObject queryObject = new PreparedQueryObject(); + + if((this.getKeyspaceName() == null || this.getKeyspaceName().isEmpty()) + || (this.getTableName() == null || this.getTableName().isEmpty())){ + + + throw new MusicQueryException("one or more path parameters are not set, please check and try again", + Status.BAD_REQUEST.getStatusCode()); + } + + EELFLoggerDelegate.mdcPut("keyspace", "( "+this.getKeyspaceName()+" ) "); + + if(this == null) { + logger.error(EELFLoggerDelegate.errorLogger,"Required HTTP Request body is missing.", AppMessages.MISSINGDATA ,ErrorSeverity.WARN, ErrorTypes.DATAERROR); + + throw new MusicQueryException("Required HTTP Request body is missing.", + Status.BAD_REQUEST.getStatusCode()); + } + StringBuilder columnString = new StringBuilder(); + + int counter = 0; + List<String> columnList = this.getColumns(); + if (columnList != null) { + for (String column : columnList) { + columnString.append(column); + if (counter != columnList.size() - 1) + columnString.append(","); + counter = counter + 1; + } + } + + // get the row specifier + RowIdentifier rowId = null; + try { + rowId = getRowIdentifier(this.getKeyspaceName(), this.getTableName(), rowParams, queryObject); + this.setRowIdString(rowId.rowIdString); + this.setPrimarKeyValue(rowId.primarKeyValue); + if(rowId == null || rowId.primarKeyValue.isEmpty()) { + + throw new MusicQueryException("Mandatory WHERE clause is missing. Please check the input request.", + Status.BAD_REQUEST.getStatusCode()); + } + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes + .GENERALSERVICEERROR, ex); + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();*/ + throw new MusicQueryException(AppMessages.UNKNOWNERROR.toString(), Status.BAD_REQUEST.getStatusCode()); + } + String rowSpec = rowId.rowIdString.toString(); + + if ((columnList != null) && (!rowSpec.isEmpty())) { + queryObject.appendQueryString("DELETE " + columnString + " FROM " + this.getKeyspaceName() + "." + + this.getTableName() + " WHERE " + rowSpec + ";"); + } + + if ((columnList == null) && (!rowSpec.isEmpty())) { + queryObject.appendQueryString("DELETE FROM " + this.getKeyspaceName() + "." + this.getTableName() + " WHERE " + + rowSpec + ";"); + } + + if ((columnList != null) && (rowSpec.isEmpty())) { + queryObject.appendQueryString( + "DELETE " + columnString + " FROM " + this.getKeyspaceName() + "." + rowSpec + ";"); + } + // get the conditional, if any + Condition conditionInfo; + if (this.getConditions() == null) { + conditionInfo = null; + } else { + // to avoid parsing repeatedly, just send the select query to + // obtain row + PreparedQueryObject selectQuery = new PreparedQueryObject(); + selectQuery.appendQueryString("SELECT * FROM " + this.getKeyspaceName() + "." + this.getTableName() + " WHERE " + + rowId.rowIdString + ";"); + selectQuery.addValue(rowId.primarKeyValue); + conditionInfo = new Condition(this.getConditions(), selectQuery); + } + + String consistency = this.getConsistencyInfo().get("type"); + + + if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && this.getConsistencyInfo().get("consistency")!=null) { + if(MusicUtil.isValidConsistency(this.getConsistencyInfo().get("consistency"))) { + queryObject.setConsistency(this.getConsistencyInfo().get("consistency")); + } else { + throw new MusicQueryException("Invalid Consistency type", Status.BAD_REQUEST.getStatusCode()); + } + } + + queryObject.setOperation("delete"); + + return queryObject; + } + + + /** + * + * @param keyspace + * @param tablename + * @param rowParams + * @param queryObject + * @return + * @throws MusicServiceException + */ + private RowIdentifier getRowIdentifier(String keyspace, String tablename, + MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject) + throws MusicServiceException { + StringBuilder rowSpec = new StringBuilder(); + int counter = 0; + TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename); + if (tableInfo == null) { + logger.error(EELFLoggerDelegate.errorLogger, + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); + throw new MusicServiceException( + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); + } + StringBuilder primaryKey = new StringBuilder(); + for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) { + String keyName = entry.getKey(); + List<String> valueList = entry.getValue(); + String indValue = valueList.get(0); + DataType colType = null; + Object formattedValue = null; + try { + colType = tableInfo.getColumn(entry.getKey()).getType(); + formattedValue = MusicUtil.convertToActualDataType(colType, indValue); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e); + } + if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) { + primaryKey.append(indValue); + } + rowSpec.append(keyName + "= ?"); + queryObject.addValue(formattedValue); + if (counter != rowParams.size() - 1) { + rowSpec.append(" AND "); + } + counter = counter + 1; + } + return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject); + } + + private class RowIdentifier { + private String primarKeyValue; + private StringBuilder rowIdString; + @SuppressWarnings("unused") + public PreparedQueryObject queryObject; // the string with all the row + // identifiers separated by AND + + public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString, + PreparedQueryObject queryObject) { + this.primarKeyValue = primaryKeyValue; + this.rowIdString = rowIdString; + this.queryObject = queryObject; + } + } +} diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonIndex.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonIndex.java new file mode 100644 index 00000000..a06e8ea9 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonIndex.java @@ -0,0 +1,120 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (c) 2019 IBM + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.datastore.jsonobjects; + +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@ApiModel(value = "JsonIndex", description = "Index Object") +public class JsonIndex { + + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonIndex.class); + + private String indexName; + private String keyspaceName; + private String tableName; + private String fieldName; + + public JsonIndex(String indexName,String keyspaceName,String tableName,String fieldName) { + this.indexName = indexName; + this.keyspaceName= keyspaceName; + this.tableName = tableName; + this.fieldName = fieldName; + } + + @ApiModelProperty(value = "Index Name") + public String getIndexName() { + return indexName; + } + + public JsonIndex setIndexName(String indexName) { + this.indexName = indexName; + return this; + } + + @ApiModelProperty(value = "Keyspace name") + public String getKeyspaceName() { + return keyspaceName; + } + + public JsonIndex setKeyspaceName(String keyspaceName) { + this.keyspaceName = keyspaceName; + return this; + } + + public JsonIndex setTableName(String tableName) { + this.tableName = tableName; + return this; + } + + @ApiModelProperty(value = "Table name") + public String getTableName() { + return tableName; + } + + public JsonIndex setFieldName(String fieldName) { + this.fieldName = fieldName; + return this; + } + + @ApiModelProperty(value = "Field name") + public String getFieldName() { + return fieldName; + } + + public PreparedQueryObject genCreateIndexQuery() { + + if (logger.isDebugEnabled()) { + logger.debug("Came inside genCreateIndexQuery method"); + } + + logger.info("genCreateIndexQuery indexName ::" + indexName); + logger.info("genCreateIndexQuery keyspaceName ::" + keyspaceName); + logger.info("genCreateIndexQuery tableName ::" + tableName); + logger.info("genCreateIndexQuery fieldName ::" + fieldName); + + long start = System.currentTimeMillis(); + + PreparedQueryObject query = new PreparedQueryObject(); + query.appendQueryString("Create index if not exists " + this.getIndexName() + " on " + this.getKeyspaceName() + "." + + this.getTableName() + " (" + this.getFieldName() + ");"); + + long end = System.currentTimeMillis(); + + logger.info(EELFLoggerDelegate.applicationLogger, + "Time taken for setting up query in create index:" + (end - start)); + + logger.info(EELFLoggerDelegate.applicationLogger, + " create index query :" + query.getQuery()); + + return query; + } + +} diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java new file mode 100644 index 00000000..2f685cfe --- /dev/null +++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java @@ -0,0 +1,415 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * Modifications Copyright (C) 2019 IBM + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore.jsonobjects; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response.Status; + +import org.onap.music.datastore.MusicDataStoreHandle; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.MusicUtil; + +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.TableMetadata; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "InsertTable", description = "Json model for table vlaues insert") +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonInsert implements Serializable { + private static final long serialVersionUID = 1L; + private String keyspaceName; + private String tableName; + private transient Map<String, Object> values; + private String ttl; + private String timestamp; + private transient Map<String, Object> rowSpecification; + private Map<String, String> consistencyInfo; + private Map<String, byte[]> objectMap; + private String primaryKeyVal; + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonInsert.class); + + @ApiModelProperty(value = "objectMap",hidden = true) + public Map<String, byte[]> getObjectMap() { + return objectMap; + } + + public void setObjectMap(Map<String, byte[]> objectMap) { + this.objectMap = objectMap; + } + + @ApiModelProperty(value = "keyspace") + public String getKeyspaceName() { + return keyspaceName; + } + + public void setKeyspaceName(String keyspaceName) { + this.keyspaceName = keyspaceName; + } + + @ApiModelProperty(value = "Table name") + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic") + public Map<String, String> getConsistencyInfo() { + return consistencyInfo; + } + + public void setConsistencyInfo(Map<String, String> consistencyInfo) { + this.consistencyInfo = consistencyInfo; + } + + @ApiModelProperty(value = "Columns and tables support an optional " + + "expiration period called TTL (time-to-live) in seconds.", + notes="TTL precision is one second, which is calculated by the coordinator " + + "node. When using TTL, ensure that all nodes in the cluster have synchronized clocks.",allowEmptyValue = true) + public String getTtl() { + return ttl; + } + + public void setTtl(String ttl) { + this.ttl = ttl; + } + + @ApiModelProperty(value = "Time stamp (epoch_in_microseconds)", + notes = "Marks inserted data (write time) with TIMESTAMP. " + + "Enter the time since epoch (January 1, 1970) in microseconds." + + "By default, the actual time of write is used.", allowEmptyValue = true) + public String getTimestamp() { + return timestamp; + } + + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } + + @ApiModelProperty(value = "Json Object of key/values", notes="Where key is the column name and value is the data value for that column.", + example = "{'emp_id': 'df98a3d40cd6','emp_name': 'john'," + + "'emp_salary': 50,'address':{'street' : '1 Some way','city' : 'New York'}}") + public Map<String, Object> getValues() { + return values; + } + + public void setValues(Map<String, Object> values) { + this.values = values; + } + + @ApiModelProperty(value = "Information for selecting specific rows for insert",hidden = true) + public Map<String, Object> getRowSpecification() { + return rowSpecification; + } + + public void setRowSpecification(Map<String, Object> rowSpecification) { + this.rowSpecification = rowSpecification; + } + + public String getPrimaryKeyVal() { + return primaryKeyVal; + } + + public void setPrimaryKeyVal(String primaryKeyVal) { + this.primaryKeyVal = primaryKeyVal; + } + + public byte[] serialize() { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutput out = null; + try { + out = new ObjectOutputStream(bos); + out.writeObject(this); + } catch (IOException e) { + logger.error(EELFLoggerDelegate.errorLogger, e, AppMessages.IOERROR, ErrorSeverity.ERROR, ErrorTypes.DATAERROR); + } + return bos.toByteArray(); + } + + /** + * Generate TableInsertQuery + * @return + * @throws MusicQueryException + */ + public PreparedQueryObject genInsertPreparedQueryObj() throws MusicQueryException { + PreparedQueryObject queryObject = new PreparedQueryObject(); + TableMetadata tableInfo = null; + try { + tableInfo = MusicDataStoreHandle.returnColumnMetadata(this.getKeyspaceName(), this.getTableName()); + if(tableInfo == null) { + throw new MusicQueryException("Table name doesn't exists. Please check the table name.", + Status.BAD_REQUEST.getStatusCode()); + } + } catch (MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger, e, AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + throw new MusicQueryException(e.getMessage(),Status.BAD_REQUEST.getStatusCode()); + + } + String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName(); + StringBuilder fieldsString = new StringBuilder("(vector_ts,"); + String vectorTs = + String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); + StringBuilder valueString = new StringBuilder("(" + "?" + ","); + queryObject.addValue(vectorTs); + + Map<String, Object> valuesMap = this.getValues(); + if (valuesMap==null) { + throw new MusicQueryException("Nothing to insert. No values provided in request.", + Status.BAD_REQUEST.getStatusCode()); + } + int counter = 0; + String primaryKey = ""; + for (Map.Entry<String, Object> entry : valuesMap.entrySet()) { + fieldsString.append("" + entry.getKey()); + Object valueObj = entry.getValue(); + if (primaryKeyName.equals(entry.getKey())) { + primaryKey = entry.getValue() + ""; + primaryKey = primaryKey.replace("'", "''"); + } + DataType colType = null; + try { + colType = tableInfo.getColumn(entry.getKey()).getType(); + } catch(NullPointerException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() +" Invalid column name : "+entry.getKey + (), AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR, ex); + throw new MusicQueryException("Invalid column name : " + entry.getKey(), + Status.BAD_REQUEST.getStatusCode()); + } + + Object formattedValue = null; + try { + formattedValue = MusicUtil.convertToActualDataType(colType, valueObj); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e); + } + valueString.append("?"); + + queryObject.addValue(formattedValue); + + if (counter == valuesMap.size() - 1) { + fieldsString.append(")"); + valueString.append(")"); + } else { + fieldsString.append(","); + valueString.append(","); + } + counter = counter + 1; + } + + //blobs.. + Map<String, byte[]> objectMap = this.getObjectMap(); + if(objectMap != null) { + for (Map.Entry<String, byte[]> entry : objectMap.entrySet()) { + if(counter > 0) { + fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ","); + valueString.replace(valueString.length()-1, valueString.length(), ","); + } + fieldsString.append("" + entry.getKey()); + byte[] valueObj = entry.getValue(); + if (primaryKeyName.equals(entry.getKey())) { + primaryKey = entry.getValue() + ""; + primaryKey = primaryKey.replace("'", "''"); + } + DataType colType = tableInfo.getColumn(entry.getKey()).getType(); + ByteBuffer formattedValue = null; + if(colType.toString().toLowerCase().contains("blob")) { + formattedValue = MusicUtil.convertToActualDataType(colType, valueObj); + } + valueString.append("?"); + queryObject.addValue(formattedValue); + counter = counter + 1; + fieldsString.append(","); + valueString.append(","); + } + } + this.setPrimaryKeyVal(primaryKey); + if(primaryKey == null || primaryKey.length() <= 0) { + logger.error(EELFLoggerDelegate.errorLogger, "Some required partition key parts are missing: "+primaryKeyName ); + throw new MusicQueryException("Some required partition key parts are missing: " + primaryKeyName, + Status.BAD_REQUEST.getStatusCode()); + } + + fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ")"); + valueString.replace(valueString.length()-1, valueString.length(), ")"); + + queryObject.appendQueryString("INSERT INTO " + this.getKeyspaceName() + "." + this.getTableName() + " " + + fieldsString + " VALUES " + valueString); + + String ttl = this.getTtl(); + String timestamp = this.getTimestamp(); + + if ((ttl != null) && (timestamp != null)) { + logger.info(EELFLoggerDelegate.applicationLogger, "both there"); + queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?"); + queryObject.addValue(Integer.parseInt(ttl)); + queryObject.addValue(Long.parseLong(timestamp)); + } + + if ((ttl != null) && (timestamp == null)) { + logger.info(EELFLoggerDelegate.applicationLogger, "ONLY TTL there"); + queryObject.appendQueryString(" USING TTL ?"); + queryObject.addValue(Integer.parseInt(ttl)); + } + + if ((ttl == null) && (timestamp != null)) { + logger.info(EELFLoggerDelegate.applicationLogger, "ONLY timestamp there"); + queryObject.appendQueryString(" USING TIMESTAMP ?"); + queryObject.addValue(Long.parseLong(timestamp)); + } + + queryObject.appendQueryString(";"); + + String consistency = this.getConsistencyInfo().get("type"); + if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && this.getConsistencyInfo().get("consistency") != null) { + if(MusicUtil.isValidConsistency(this.getConsistencyInfo().get("consistency"))) { + queryObject.setConsistency(this.getConsistencyInfo().get("consistency")); + } else { + throw new MusicQueryException("Invalid Consistency type", Status.BAD_REQUEST.getStatusCode()); + } + } + queryObject.setOperation("insert"); + + logger.info("Data insert Query ::::: " + queryObject.getQuery()); + + return queryObject; + } + + /** + * + * @param rowParams + * @return + * @throws MusicQueryException + */ + public PreparedQueryObject genSelectCriticalPreparedQueryObj(MultivaluedMap<String, String> rowParams) throws MusicQueryException { + + PreparedQueryObject queryObject = new PreparedQueryObject(); + + if((this.getKeyspaceName() == null || this.getKeyspaceName().isEmpty()) + || (this.getTableName() == null || this.getTableName().isEmpty())){ + throw new MusicQueryException("one or more path parameters are not set, please check and try again", + Status.BAD_REQUEST.getStatusCode()); + } + EELFLoggerDelegate.mdcPut("keyspace", "( "+this.getKeyspaceName()+" ) "); + RowIdentifier rowId = null; + try { + rowId = getRowIdentifier(this.getKeyspaceName(), this.getTableName(), rowParams, queryObject); + this.setPrimaryKeyVal(rowId.primarKeyValue); + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes + .GENERALSERVICEERROR, ex); + throw new MusicQueryException(ex.getMessage(), Status.BAD_REQUEST.getStatusCode()); + } + + queryObject.appendQueryString( + "SELECT * FROM " + this.getKeyspaceName() + "." + this.getTableName() + " WHERE " + rowId.rowIdString + ";"); + + return queryObject; + } + + private class RowIdentifier { + public String primarKeyValue; + public StringBuilder rowIdString; + @SuppressWarnings("unused") + public PreparedQueryObject queryObject; // the string with all the row + // identifiers separated by AND + + public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString, + PreparedQueryObject queryObject) { + this.primarKeyValue = primaryKeyValue; + this.rowIdString = rowIdString; + this.queryObject = queryObject; + } + } + + /** + * + * @param keyspace + * @param tablename + * @param rowParams + * @param queryObject + * @return + * @throws MusicServiceException + */ + private RowIdentifier getRowIdentifier(String keyspace, String tablename, + MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject) + throws MusicServiceException { + StringBuilder rowSpec = new StringBuilder(); + int counter = 0; + TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename); + if (tableInfo == null) { + logger.error(EELFLoggerDelegate.errorLogger, + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); + throw new MusicServiceException( + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); + } + StringBuilder primaryKey = new StringBuilder(); + for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) { + String keyName = entry.getKey(); + List<String> valueList = entry.getValue(); + String indValue = valueList.get(0); + DataType colType = null; + Object formattedValue = null; + try { + colType = tableInfo.getColumn(entry.getKey()).getType(); + formattedValue = MusicUtil.convertToActualDataType(colType, indValue); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e); + } + if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) { + primaryKey.append(indValue); + } + rowSpec.append(keyName + "= ?"); + queryObject.addValue(formattedValue); + if (counter != rowParams.size() - 1) { + rowSpec.append(" AND "); + } + counter = counter + 1; + } + return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject); + } + + +} diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonKeySpace.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonKeySpace.java new file mode 100644 index 00000000..cada1c00 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonKeySpace.java @@ -0,0 +1,163 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (C) 2019 IBM + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore.jsonobjects; + +import java.util.Map; + +import javax.ws.rs.core.Response.Status; + +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.main.MusicUtil; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "JsonTable", description = "Json model creating new keyspace") +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonKeySpace { + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonKeySpace.class); + private String keyspaceName; + private Map<String, Object> replicationInfo; + private String durabilityOfWrites; + private Map<String, String> consistencyInfo; + + @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic") + public Map<String, String> getConsistencyInfo() { + return consistencyInfo; + } + + public void setConsistencyInfo(Map<String, String> consistencyInfo) { + this.consistencyInfo = consistencyInfo; + } + + @ApiModelProperty(value = "Replication information") + public Map<String, Object> getReplicationInfo() { + return replicationInfo; + } + + public void setReplicationInfo(Map<String, Object> replicationInfo) { + this.replicationInfo = replicationInfo; + } + + @ApiModelProperty(value = "Durability", allowableValues = "true,false") + public String getDurabilityOfWrites() { + return durabilityOfWrites; + } + + public void setDurabilityOfWrites(String durabilityOfWrites) { + this.durabilityOfWrites = durabilityOfWrites; + } + + @ApiModelProperty(value = "Keyspace name") + public String getKeyspaceName() { + return keyspaceName; + } + + public void setKeyspaceName(String keyspaceName) { + this.keyspaceName = keyspaceName; + } + + /** + * Will generate query to create Keyspacce. + * + * @throws MusicQueryException + */ + @SuppressWarnings("deprecation") + public PreparedQueryObject genCreateKeyspaceQuery() throws MusicQueryException { + + if (logger.isDebugEnabled()) { + logger.debug("Came inside createKeyspace method"); + } + + String keyspaceName = this.getKeyspaceName(); + String durabilityOfWrites = this.getDurabilityOfWrites(); + String consistency = MusicUtil.EVENTUAL; + + logger.info("genCreateKeyspaceQuery keyspaceName ::" + keyspaceName); + logger.info("genCreateKeyspaceQuery class :: " + this.getReplicationInfo().get("class")); + logger.info("genCreateKeyspaceQuery replication_factor :: " + this.getReplicationInfo().get("replication_factor")); + logger.info("genCreateKeyspaceQuery durabilityOfWrites :: " + durabilityOfWrites); + + PreparedQueryObject queryObject = new PreparedQueryObject(); + + if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && this.getConsistencyInfo().get("consistency") != null) { + if(MusicUtil.isValidConsistency(this.getConsistencyInfo().get("consistency"))) { + queryObject.setConsistency(this.getConsistencyInfo().get("consistency")); + }else { + throw new MusicQueryException("Invalid Consistency type",Status.BAD_REQUEST.getStatusCode()); + } + } + + long start = System.currentTimeMillis(); + Map<String, Object> replicationInfo = this.getReplicationInfo(); + String repString = null; + try { + repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}"; + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.MISSINGDATA, + ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); + } + queryObject.appendQueryString("CREATE KEYSPACE " + keyspaceName + " WITH replication = " + repString); + if (this.getDurabilityOfWrites() != null) { + queryObject.appendQueryString(" AND durable_writes = " + this.getDurabilityOfWrites()); + } + queryObject.appendQueryString(";"); + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger, + "Time taken for setting up query in create keyspace:" + (end - start)); + + return queryObject; + } + + /** + * Will generate Query to drop a keyspace. + * + * @return + */ + public PreparedQueryObject genDropKeyspaceQuery() { + if (logger.isDebugEnabled()) { + logger.debug("Coming inside genDropKeyspaceQuery method "+this.getKeyspaceName()); + } + + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString("DROP KEYSPACE " + this.getKeyspaceName() + ";"); + + return queryObject; + } + + @Override + public String toString() { + return "CassaKeyspaceObject [keyspaceName=" + keyspaceName + ", replicationInfo=" + replicationInfo + + "durabilityOfWrites=" + durabilityOfWrites + "]"; + } + +} diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java new file mode 100644 index 00000000..86bbe3dc --- /dev/null +++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java @@ -0,0 +1,44 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore.jsonobjects; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "Json Leasesd Lock", description = "model for leased lock") +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonLeasedLock { + private long leasePeriod; + + @ApiModelProperty(value = "Lease period") + public long getLeasePeriod() { + return leasePeriod; + } + + public void setLeasePeriod(long leasePeriod) { + this.leasePeriod = leasePeriod; + } + +} diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java new file mode 100644 index 00000000..f353c018 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java @@ -0,0 +1,49 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore.jsonobjects; + +import org.onap.music.lockingservice.cassandra.LockType; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "Json Lock Type", description = "Model for Lock Type") +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonLock { + private LockType locktype; + + @ApiModelProperty( + value = "Type of music lock", + name = "lockType", + allowEmptyValue = false, + allowableValues = "READ|WRITE") + public LockType getLocktype() { + return this.locktype; + } + + public void setLockType(LockType locktype) { + this.locktype = locktype; + } +} diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonSelect.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonSelect.java new file mode 100644 index 00000000..e354b4b0 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonSelect.java @@ -0,0 +1,208 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * Modifications Copyright (C) 2019 IBM + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore.jsonobjects; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response.Status; + +import org.onap.music.datastore.MusicDataStoreHandle; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.MusicUtil; + +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.TableMetadata; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonSelect implements Serializable { + private Map<String, String> consistencyInfo; + private String keyspaceName; + private String tableName; + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonSelect.class); + + + + public Map<String, String> getConsistencyInfo() { + return consistencyInfo; + } + + public void setConsistencyInfo(Map<String, String> consistencyInfo) { + this.consistencyInfo = consistencyInfo; + } + + public String getKeyspaceName() { + return keyspaceName; + } + + public void setKeyspaceName(String keyspaceName) { + this.keyspaceName = keyspaceName; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + public byte[] serialize() { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutput out = null; + try { + out = new ObjectOutputStream(bos); + out.writeObject(this); + } catch (IOException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), e); + } + return bos.toByteArray(); + } + + /** + * genSelectQuery + * + * @return + * @throws MusicQueryException + */ + public PreparedQueryObject genSelectQuery(MultivaluedMap<String, String> rowParams) throws MusicQueryException { + + if((this.getKeyspaceName() == null || this.getKeyspaceName().isEmpty()) + || (this.getTableName() == null || this.getTableName().isEmpty())){ + throw new MusicQueryException("one or more path parameters are not set, please check and try again", + Status.BAD_REQUEST.getStatusCode()); + } + EELFLoggerDelegate.mdcPut("keyspace", "( " + this.getKeyspaceName() + " ) "); + PreparedQueryObject queryObject = new PreparedQueryObject(); + + if (rowParams.isEmpty()) { // select all + queryObject.appendQueryString("SELECT * FROM " + this.getKeyspaceName() + "." + this.getTableName() + ";"); + } else { + int limit = -1; // do not limit the number of results + try { + queryObject = selectSpecificQuery(this.getKeyspaceName(), this.getTableName(), rowParams, limit); + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, + ErrorTypes.GENERALSERVICEERROR, ex); + + throw new MusicQueryException(ex.getMessage(), Status.BAD_REQUEST.getStatusCode()); + } + } + + return queryObject; + } + + public PreparedQueryObject selectSpecificQuery(String keyspace, + String tablename, MultivaluedMap<String, String> rowParams, int limit) + throws MusicServiceException { + PreparedQueryObject queryObject = new PreparedQueryObject(); + StringBuilder rowIdString = getRowIdentifier(keyspace, + tablename,rowParams,queryObject).rowIdString; + queryObject.appendQueryString( + "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowIdString); + if (limit != -1) { + queryObject.appendQueryString(" LIMIT " + limit); + } + queryObject.appendQueryString(";"); + return queryObject; + } + + private class RowIdentifier { + public String primarKeyValue; + public StringBuilder rowIdString; + @SuppressWarnings("unused") + public PreparedQueryObject queryObject; // the string with all the row + // identifiers separated by AND + + public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString, + PreparedQueryObject queryObject) { + this.primarKeyValue = primaryKeyValue; + this.rowIdString = rowIdString; + this.queryObject = queryObject; + } + } + + /** + * + * @param keyspace + * @param tablename + * @param rowParams + * @param queryObject + * @return + * @throws MusicServiceException + */ + private RowIdentifier getRowIdentifier(String keyspace, String tablename, + MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject) + throws MusicServiceException { + StringBuilder rowSpec = new StringBuilder(); + int counter = 0; + TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename); + if (tableInfo == null) { + logger.error(EELFLoggerDelegate.errorLogger, + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); + throw new MusicServiceException( + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); + } + StringBuilder primaryKey = new StringBuilder(); + for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) { + String keyName = entry.getKey(); + List<String> valueList = entry.getValue(); + String indValue = valueList.get(0); + DataType colType = null; + Object formattedValue = null; + try { + colType = tableInfo.getColumn(entry.getKey()).getType(); + formattedValue = MusicUtil.convertToActualDataType(colType, indValue); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e); + } + if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) { + primaryKey.append(indValue); + } + rowSpec.append(keyName + "= ?"); + queryObject.addValue(formattedValue); + if (counter != rowParams.size() - 1) { + rowSpec.append(" AND "); + } + counter = counter + 1; + } + return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject); + } + +} diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonTable.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonTable.java new file mode 100644 index 00000000..0ba1a7ef --- /dev/null +++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonTable.java @@ -0,0 +1,363 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (C) 2019 IBM + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore.jsonobjects; + +import java.util.Map; + +import javax.ws.rs.core.Response.Status; + +import org.apache.commons.lang3.StringUtils; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.main.MusicUtil; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "JsonTable", description = "Defines the Json for Creating a new Table.") +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonTable { + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonTable.class); + + private String keyspaceName; + private String tableName; + + private Map<String, String> fields; + private Map<String, Object> properties; + private String primaryKey; + private String partitionKey; + private String clusteringKey; + private String filteringKey; + private String clusteringOrder; + private Map<String, String> consistencyInfo; + + @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic") + public Map<String, String> getConsistencyInfo() { + return consistencyInfo; + } + + public void setConsistencyInfo(Map<String, String> consistencyInfo) { + this.consistencyInfo = consistencyInfo; + } + + @ApiModelProperty(value = "Properties") + public Map<String, Object> getProperties() { + return properties; + } + + public void setProperties(Map<String, Object> properties) { + this.properties = properties; + } + + @ApiModelProperty(value = "Fields") + public Map<String, String> getFields() { + return fields; + } + + public void setFields(Map<String, String> fields) { + this.fields = fields; + } + + @ApiModelProperty(value = "KeySpace Name") + public String getKeyspaceName() { + return keyspaceName; + } + + public void setKeyspaceName(String keyspaceName) { + this.keyspaceName = keyspaceName; + } + + @ApiModelProperty(value = "Table Name") + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + @ApiModelProperty(value = "Clustering Order", notes = "") + public String getClusteringOrder() { + return clusteringOrder; + } + + public void setClusteringOrder(String clusteringOrder) { + this.clusteringOrder = clusteringOrder; + } + + @ApiModelProperty(value = "Primary Key") + public String getPrimaryKey() { + return primaryKey; + } + + public void setPrimaryKey(String primaryKey) { + this.primaryKey = primaryKey; + } + + public String getClusteringKey() { + return clusteringKey; + } + + public void setClusteringKey(String clusteringKey) { + this.clusteringKey = clusteringKey; + } + + public String getFilteringKey() { + return filteringKey; + } + + public void setFilteringKey(String filteringKey) { + this.filteringKey = filteringKey; + } + + public String getPartitionKey() { + return partitionKey; + } + + public void setPartitionKey(String partitionKey) { + this.partitionKey = partitionKey; + } + + public PreparedQueryObject genCreateTableQuery() throws MusicQueryException { + String primaryKey = null; + String partitionKey = this.getPartitionKey(); + String clusterKey = this.getClusteringKey(); + String filteringKey = this.getFilteringKey(); + if (filteringKey != null) { + clusterKey = clusterKey + "," + filteringKey; + } + primaryKey = this.getPrimaryKey(); // get primaryKey if available + + PreparedQueryObject queryObject = new PreparedQueryObject(); + // first read the information about the table fields + Map<String, String> fields = this.getFields(); + if (fields == null) { + throw new MusicQueryException( + "Create Table Error: No fields in request", Status.BAD_REQUEST.getStatusCode()); + } + StringBuilder fieldsString = new StringBuilder("(vector_ts text,"); + int counter = 0; + for (Map.Entry<String, String> entry : fields.entrySet()) { + if (entry.getKey().equals("PRIMARY KEY")) { + primaryKey = entry.getValue(); // replaces primaryKey + primaryKey = primaryKey.trim(); + } + else { + if (counter == 0 ) + fieldsString.append("" + entry.getKey() + " " + entry.getValue() + ""); + else fieldsString.append("," + entry.getKey() + " " + entry.getValue() + ""); + } + + if (counter != (fields.size() - 1) ) { + counter = counter + 1; + } else { + + if((primaryKey != null) && (partitionKey == null)) { + primaryKey = primaryKey.trim(); + int count1 = StringUtils.countMatches(primaryKey, ')'); + int count2 = StringUtils.countMatches(primaryKey, '('); + if (count1 != count2) { + throw new MusicQueryException( + "Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey, + Status.BAD_REQUEST.getStatusCode()); + } + + if ( primaryKey.indexOf('(') == -1 || ( count2 == 1 && (primaryKey.lastIndexOf(')') +1) == primaryKey.length() ) ) { + if (primaryKey.contains(",") ) { + partitionKey= primaryKey.substring(0,primaryKey.indexOf(',')); + partitionKey=partitionKey.replaceAll("[\\(]+",""); + clusterKey=primaryKey.substring(primaryKey.indexOf(',')+1); // make sure index + clusterKey=clusterKey.replaceAll("[)]+", ""); + } else { + partitionKey=primaryKey; + partitionKey=partitionKey.replaceAll("[\\)]+",""); + partitionKey=partitionKey.replaceAll("[\\(]+",""); + clusterKey=""; + } + } else { // not null and has ) before the last char + partitionKey= primaryKey.substring(0,primaryKey.indexOf(')')); + partitionKey=partitionKey.replaceAll("[\\(]+",""); + partitionKey = partitionKey.trim(); + clusterKey= primaryKey.substring(primaryKey.indexOf(')')); + clusterKey=clusterKey.replaceAll("[\\(]+",""); + clusterKey=clusterKey.replaceAll("[\\)]+",""); + clusterKey = clusterKey.trim(); + if (clusterKey.indexOf(',') == 0) { + clusterKey=clusterKey.substring(1); + } + clusterKey = clusterKey.trim(); + if (clusterKey.equals(",") ) + clusterKey=""; // print error if needed ( ... ),) + } + + if (!(partitionKey.isEmpty() || clusterKey.isEmpty()) + && (partitionKey.equalsIgnoreCase(clusterKey) || + clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) { + logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey + " and primary key=" + primaryKey ); + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError( + "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ") of" + + " primary key=" + primaryKey) + .toMap()).build();*/ + throw new MusicQueryException("Create Table primary key error: clusterKey(" + clusterKey + + ") equals/contains/overlaps partitionKey(" + partitionKey + ") of" + " primary key=" + + primaryKey, Status.BAD_REQUEST.getStatusCode()); + + } + + if (partitionKey.isEmpty() ) + primaryKey=""; + else if (clusterKey.isEmpty() ) + primaryKey=" (" + partitionKey + ")"; + else + primaryKey=" (" + partitionKey + ")," + clusterKey; + + + if (primaryKey != null) + fieldsString.append(", PRIMARY KEY (" + primaryKey + " )"); + + } else { // end of length > 0 + + if (!(partitionKey.isEmpty() || clusterKey.isEmpty()) + && (partitionKey.equalsIgnoreCase(clusterKey) || + clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) { + logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey); + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError( + "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ")") + .toMap()).build();*/ + throw new MusicQueryException( + "Create Table primary key error: clusterKey(" + clusterKey + + ") equals/contains/overlaps partitionKey(" + partitionKey + ")", + Status.BAD_REQUEST.getStatusCode()); + } + + if (partitionKey.isEmpty() ) + primaryKey=""; + else if (clusterKey.isEmpty() ) + primaryKey=" (" + partitionKey + ")"; + else + primaryKey=" (" + partitionKey + ")," + clusterKey; + + if (primaryKey != null) + fieldsString.append(", PRIMARY KEY (" + primaryKey + " )"); + } + fieldsString.append(")"); + + } // end of last field check + + } // end of for each + // information about the name-value style properties + Map<String, Object> propertiesMap = this.getProperties(); + StringBuilder propertiesString = new StringBuilder(); + if (propertiesMap != null) { + counter = 0; + for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) { + Object ot = entry.getValue(); + String value = ot + ""; + if (ot instanceof String) { + value = "'" + value + "'"; + } else if (ot instanceof Map) { + @SuppressWarnings("unchecked") + Map<String, Object> otMap = (Map<String, Object>) ot; + try { + value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}"; + } catch (Exception e) { + throw new MusicQueryException(e.getMessage(), + Status.BAD_REQUEST.getStatusCode()); + } + } + + propertiesString.append(entry.getKey() + "=" + value + ""); + if (counter != propertiesMap.size() - 1) + propertiesString.append(" AND "); + + counter = counter + 1; + } + } + + String clusteringOrder = this.getClusteringOrder(); + + if (clusteringOrder != null && !(clusteringOrder.isEmpty())) { + String[] arrayClusterOrder = clusteringOrder.split("[,]+"); + + for (int i = 0; i < arrayClusterOrder.length; i++) { + String[] clusterS = arrayClusterOrder[i].trim().split("[ ]+"); + if ( (clusterS.length ==2) && (clusterS[1].equalsIgnoreCase("ASC") || clusterS[1].equalsIgnoreCase("DESC"))) { + continue; + } else { + /*return response.status(Status.BAD_REQUEST) + .entity(new JsonResponse(ResultType.FAILURE) + .setError("createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"+ clusteringOrder+".") + .toMap()).build();*/ + + throw new MusicQueryException( + "createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:" + + clusteringOrder + ".", + Status.BAD_REQUEST.getStatusCode()); + } + // add validation for column names in cluster key + } + + if (!(clusterKey.isEmpty())) { + clusteringOrder = "CLUSTERING ORDER BY (" +clusteringOrder +")"; + //cjc check if propertiesString.length() >0 instead propertiesMap + if (propertiesMap != null) { + propertiesString.append(" AND "+ clusteringOrder); + } else { + propertiesString.append(clusteringOrder); + } + } else { + logger.warn("Skipping clustering order=("+clusteringOrder+ ") since clustering key is empty "); + } + } //if non empty + + queryObject.appendQueryString( + "CREATE TABLE " + this.getKeyspaceName() + "." + this.getTableName() + " " + fieldsString); + + + if (propertiesString != null && propertiesString.length()>0 ) + queryObject.appendQueryString(" WITH " + propertiesString); + queryObject.appendQueryString(";"); + + return queryObject; + } + + /** + * genDropTableQuery + * + * @return PreparedQueryObject + */ + public PreparedQueryObject genDropTableQuery() { + PreparedQueryObject query = new PreparedQueryObject(); + query.appendQueryString("DROP TABLE " + this.getKeyspaceName() + "." + this.getTableName() + ";"); + logger.info("Delete Query ::::: " + query.getQuery()); + + return query; + } + + +} diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonUpdate.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonUpdate.java new file mode 100644 index 00000000..29fdb1d4 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonUpdate.java @@ -0,0 +1,436 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * Modifications Copyright (C) 2019 IBM + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore.jsonobjects; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response.Status; + +import org.onap.music.datastore.Condition; +import org.onap.music.datastore.MusicDataStoreHandle; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ReturnType; + +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.TableMetadata; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "JsonTable", description = "Json model for table update") +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonUpdate implements Serializable { + private String keyspaceName; + private String tableName; + private transient Map<String, Object> values; + private String ttl; + private String timestamp; + private Map<String, String> consistencyInfo; + private transient Map<String, Object> conditions; + private transient Map<String, Object> rowSpecification; + private String rowIdString; + private String primarKeyValue; + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonUpdate.class); + + @ApiModelProperty(value = "Conditions") + public Map<String, Object> getConditions() { + return conditions; + } + + public void setConditions(Map<String, Object> conditions) { + this.conditions = conditions; + } + + @ApiModelProperty(value = "Information for selecting sepcific rows") + public Map<String, Object> getRow_specification() { + return rowSpecification; + } + + public void setRow_specification(Map<String, Object> rowSpecification) { + this.rowSpecification = rowSpecification; + } + + + @ApiModelProperty(value = "Keyspace name") + public String getKeyspaceName() { + return keyspaceName; + } + + public void setKeyspaceName(String keyspaceName) { + this.keyspaceName = keyspaceName; + } + + @ApiModelProperty(value = "Table name") + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic") + public Map<String, String> getConsistencyInfo() { + return consistencyInfo; + } + + public void setConsistencyInfo(Map<String, String> consistencyInfo) { + this.consistencyInfo = consistencyInfo; + } + + @ApiModelProperty(value = "Time to live value") + public String getTtl() { + return ttl; + } + + public void setTtl(String ttl) { + this.ttl = ttl; + } + + @ApiModelProperty(value = "Time stamp") + public String getTimestamp() { + return timestamp; + } + + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } + + @ApiModelProperty(value = "Column values") + public Map<String, Object> getValues() { + return values; + } + + public void setValues(Map<String, Object> values) { + this.values = values; + } + + public String getRowIdString() { + return rowIdString; + } + + public void setRowIdString(String rowIdString) { + this.rowIdString = rowIdString; + } + + public String getPrimarKeyValue() { + return primarKeyValue; + } + + public void setPrimarKeyValue(String primarKeyValue) { + this.primarKeyValue = primarKeyValue; + } + + public byte[] serialize() { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutput out = null; + try { + out = new ObjectOutputStream(bos); + out.writeObject(this); + } catch (IOException e) { + logger.error(EELFLoggerDelegate.errorLogger, e,AppMessages.IOERROR, ErrorSeverity.ERROR, ErrorTypes.DATAERROR); + } + return bos.toByteArray(); + } + + /** + * Generate TableInsertQuery + * @return + * @throws MusicQueryException + */ + public PreparedQueryObject genUpdatePreparedQueryObj(MultivaluedMap<String, String> rowParams) throws MusicQueryException { + PreparedQueryObject queryObject = new PreparedQueryObject(); + + if((this.getKeyspaceName() == null || this.getKeyspaceName().isEmpty()) || + (this.getTableName() == null || this.getTableName().isEmpty())){ + + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("one or more path parameters are not set, please check and try again") + .toMap()).build();*/ + + throw new MusicQueryException("one or more path parameters are not set, please check and try again", + Status.BAD_REQUEST.getStatusCode()); + } + + EELFLoggerDelegate.mdcPut("keyspace", "( "+this.getKeyspaceName()+" ) "); + String operationId = UUID.randomUUID().toString(); // just for infoging purposes. + String consistency = this.getConsistencyInfo().get("type"); + + logger.info(EELFLoggerDelegate.applicationLogger, "--------------Music " + consistency + + " update-" + operationId + "-------------------------"); + // obtain the field value pairs of the update + + Map<String, Object> valuesMap = this.getValues(); + + TableMetadata tableInfo = getColumnMetadata(this.getKeyspaceName(), this.getTableName()); + + if (tableInfo == null) { + logger.error(EELFLoggerDelegate.errorLogger,"Table information not found. Please check input for table name= "+this.getTableName(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("Table information not found. Please check input for table name= " + + this.getKeyspaceName() + "." + this.getTableName()).toMap()).build();*/ + + throw new MusicQueryException("Table information not found. Please check input for table name= " + + this.getKeyspaceName() + "." + this.getTableName(), Status.BAD_REQUEST.getStatusCode()); + } + + String vectorTs = String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); + StringBuilder fieldValueString = new StringBuilder("vector_ts=?,"); + queryObject.addValue(vectorTs); + int counter = 0; + for (Map.Entry<String, Object> entry : valuesMap.entrySet()) { + Object valueObj = entry.getValue(); + DataType colType = null; + try { + colType = tableInfo.getColumn(entry.getKey()).getType(); + } catch(NullPointerException ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex, "Invalid column name : "+entry.getKey(), ex); + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE). + * setError("Invalid column name : "+entry.getKey()).toMap()).build();*/ + + throw new MusicQueryException("Invalid column name : " + entry.getKey(),Status.BAD_REQUEST.getStatusCode()); + } + Object valueString = null; + try { + valueString = MusicUtil.convertToActualDataType(colType, valueObj); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e); + } + fieldValueString.append(entry.getKey() + "= ?"); + queryObject.addValue(valueString); + if (counter != valuesMap.size() - 1) { + fieldValueString.append(","); + } + counter = counter + 1; + } + String ttl = this.getTtl(); + String timestamp = this.getTimestamp(); + + queryObject.appendQueryString("UPDATE " + this.getKeyspaceName() + "." + this.getTableName() + " "); + if ((ttl != null) && (timestamp != null)) { + logger.info("both there"); + queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?"); + queryObject.addValue(Integer.parseInt(ttl)); + queryObject.addValue(Long.parseLong(timestamp)); + } + + if ((ttl != null) && (timestamp == null)) { + logger.info("ONLY TTL there"); + queryObject.appendQueryString(" USING TTL ?"); + queryObject.addValue(Integer.parseInt(ttl)); + } + + if ((ttl == null) && (timestamp != null)) { + logger.info("ONLY timestamp there"); + queryObject.appendQueryString(" USING TIMESTAMP ?"); + queryObject.addValue(Long.parseLong(timestamp)); + } + + // get the row specifier + RowIdentifier rowId = null; + try { + rowId = getRowIdentifier(this.getKeyspaceName(), this.getTableName(), rowParams, queryObject); + this.setRowIdString(rowId.rowIdString); + this.setPrimarKeyValue(rowId.primarKeyValue); + if(rowId == null || rowId.getPrimaryKeyValue().isEmpty()) { + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("Mandatory WHERE clause is missing. Please check the input request.").toMap()).build();*/ + + throw new MusicQueryException("Mandatory WHERE clause is missing. Please check the input request.", + Status.BAD_REQUEST.getStatusCode()); + } + } catch (MusicQueryException ex) { + throw new MusicQueryException("Mandatory WHERE clause is missing. Please check the input request.", + Status.BAD_REQUEST.getStatusCode()); + + }catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes + .GENERALSERVICEERROR, ex); + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();*/ + + throw new MusicQueryException(ex.getMessage(), Status.BAD_REQUEST.getStatusCode()); + + } + + + + queryObject.appendQueryString( + " SET " + fieldValueString + " WHERE " + rowId.getRowIdString() + ";"); + + + + // get the conditional, if any + Condition conditionInfo; + if (this.getConditions() == null) { + conditionInfo = null; + } else { + // to avoid parsing repeatedly, just send the select query to obtain row + PreparedQueryObject selectQuery = new PreparedQueryObject(); + selectQuery.appendQueryString("SELECT * FROM " + this.getKeyspaceName() + "." + this.getTableName() + " WHERE " + + rowId.getRowIdString() + ";"); + selectQuery.addValue(rowId.primarKeyValue); + conditionInfo = new Condition(this.getConditions(), selectQuery); + } + + if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && this.getConsistencyInfo().get("consistency") != null) { + if(MusicUtil.isValidConsistency(this.getConsistencyInfo().get("consistency"))) { + queryObject.setConsistency(this.getConsistencyInfo().get("consistency")); + } else { + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR) + .setError("Invalid Consistency type").toMap()).build();*/ + + logger.error("Invalid Consistency type"); + throw new MusicQueryException("Invalid Consistency type", Status.BAD_REQUEST.getStatusCode()); + } + } + + queryObject.setOperation("update"); + + return queryObject; + } + + TableMetadata getColumnMetadata(String keyspaceName, String tableName) throws MusicQueryException { + TableMetadata tableInfo; + try { + tableInfo = returnColumnMetadata(keyspaceName, tableName); + } catch (MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes + .GENERALSERVICEERROR, e); + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();*/ + throw new MusicQueryException(e.getMessage(), Status.BAD_REQUEST.getStatusCode()); + }catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e, AppMessages.UNKNOWNERROR, ErrorSeverity.CRITICAL, + ErrorTypes.GENERALSERVICEERROR); + throw new MusicQueryException(e.getMessage(), Status.BAD_REQUEST.getStatusCode()); + } + return tableInfo; + } + + /** wrapper around static method for testing */ + TableMetadata returnColumnMetadata(String keyspace, String tableName) throws MusicServiceException { + return MusicDataStoreHandle.returnColumnMetadata(keyspace, tableName); + } + + class RowIdentifier { + private String primarKeyValue; + private String rowIdString; + @SuppressWarnings("unused") + public PreparedQueryObject queryObject; // the string with all the row + // identifiers separated by AND + + public RowIdentifier(String primaryKeyValue, String rowIdString, + PreparedQueryObject queryObject) { + this.primarKeyValue = primaryKeyValue; + this.rowIdString = rowIdString; + this.queryObject = queryObject; + } + + public String getPrimaryKeyValue() { + return this.primarKeyValue; + } + + public void setPrimaryKeyValue(String primaryKeyValue) { + this.primarKeyValue = primaryKeyValue; + } + + public String getRowIdString() { + return this.rowIdString; + } + + public void setRowIdString(String rowIdString) { + this.rowIdString = rowIdString; + } + + public PreparedQueryObject getQueryObject() { + return this.queryObject; + } + } + + /** + * + * @param keyspace + * @param tablename + * @param rowParams + * @param queryObject + * @return + * @throws MusicServiceException + */ + RowIdentifier getRowIdentifier(String keyspace, String tablename, + MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject) + throws MusicServiceException { + StringBuilder rowSpec = new StringBuilder(); + int counter = 0; + TableMetadata tableInfo = returnColumnMetadata(keyspace, tablename); + if (tableInfo == null) { + logger.error(EELFLoggerDelegate.errorLogger, + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); + throw new MusicServiceException( + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); + } + StringBuilder primaryKey = new StringBuilder(); + for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) { + String keyName = entry.getKey(); + List<String> valueList = entry.getValue(); + String indValue = valueList.get(0); + DataType colType = null; + Object formattedValue = null; + try { + colType = tableInfo.getColumn(entry.getKey()).getType(); + formattedValue = MusicUtil.convertToActualDataType(colType, indValue); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e); + } + if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) { + primaryKey.append(indValue); + } + rowSpec.append(keyName + "= ?"); + queryObject.addValue(formattedValue); + if (counter != rowParams.size() - 1) { + rowSpec.append(" AND "); + } + counter = counter + 1; + } + return new RowIdentifier(primaryKey.toString(), rowSpec.toString(), queryObject); + } + +} diff --git a/music-core/src/main/java/org/onap/music/eelf/healthcheck/MusicHealthCheck.java b/music-core/src/main/java/org/onap/music/eelf/healthcheck/MusicHealthCheck.java new file mode 100644 index 00000000..fbfc0de6 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/eelf/healthcheck/MusicHealthCheck.java @@ -0,0 +1,130 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * + * Modifications Copyright (C) 2019 IBM. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.eelf.healthcheck; + +import java.util.UUID; + +import org.onap.music.datastore.MusicDataStoreHandle; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import org.onap.music.main.MusicCore; + +import com.datastax.driver.core.ConsistencyLevel; + +/** + * @author inam + * + */ +public class MusicHealthCheck { + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicUtil.class); + + private String cassandrHost; + + public String getCassandraStatus(String consistency) { + logger.info(EELFLoggerDelegate.applicationLogger, "Getting Status for Cassandra"); + + boolean result = false; + UUID randomUUID = UUID.randomUUID(); + try { + result = getAdminKeySpace(consistency, randomUUID); + } catch( Exception e) { + if(e.getMessage().toLowerCase().contains("unconfigured table healthcheck")) { + logger.error("Error", e); + logger.debug("Creating table...."); + try { + boolean ksresult = createKeyspace(); + if(ksresult) { + result = getAdminKeySpace(consistency, randomUUID); + } + } catch (MusicServiceException e1) { + logger.error(EELFLoggerDelegate.errorLogger, e1.getMessage(), AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.UNKNOWN, e1); + } catch (MusicQueryException e1) { + logger.error(EELFLoggerDelegate.errorLogger, e1.getMessage(), AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.UNKNOWN,e1); + } + } else { + logger.error("Error", e); + return "One or more nodes are down or not responding."; + } + } + try { + cleanHealthCheckId(randomUUID); + } catch (MusicServiceException | MusicQueryException e) { + logger.error("Error while cleaning healthcheck record id...", e); + } + if (result) { + return "ACTIVE"; + } else { + logger.info(EELFLoggerDelegate.applicationLogger, "Cassandra Service is not responding"); + return "INACTIVE"; + } + } + + private Boolean getAdminKeySpace(String consistency, UUID randomUUID) throws MusicServiceException,MusicQueryException { + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString("insert into admin.healthcheck (id) values (?)"); + pQuery.addValue(randomUUID); + ResultType rs = null; + rs = MusicCore.nonKeyRelatedPut(pQuery, consistency); + logger.info(rs.toString()); + return null != rs; + + } + + private void cleanHealthCheckId(UUID randomUUID) throws MusicServiceException, MusicQueryException { + String cleanQuery = "delete from admin.healthcheck where id = ?"; + PreparedQueryObject deleteQueryObject = new PreparedQueryObject(); + deleteQueryObject.appendQueryString(cleanQuery); + deleteQueryObject.addValue(randomUUID); + MusicDataStoreHandle.getDSHandle().executePut(deleteQueryObject, "eventual"); + logger.info(EELFLoggerDelegate.applicationLogger, "Cassandra healthcheck responded and cleaned up."); + } + + + + private boolean createKeyspace() throws MusicServiceException,MusicQueryException { + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString("CREATE TABLE admin.healthcheck (id uuid PRIMARY KEY)"); + ResultType rs = null ; + rs = MusicCore.nonKeyRelatedPut(pQuery, ConsistencyLevel.ONE.toString()); + return rs != null && rs.getResult().toLowerCase().contains("success"); + } + + public String getCassandrHost() { + return cassandrHost; + } + + public void setCassandrHost(String cassandrHost) { + this.cassandrHost = cassandrHost; + } + +}
\ No newline at end of file diff --git a/music-core/src/main/java/org/onap/music/eelf/logging/EELFLoggerDelegate.java b/music-core/src/main/java/org/onap/music/eelf/logging/EELFLoggerDelegate.java new file mode 100644 index 00000000..a8012c82 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/eelf/logging/EELFLoggerDelegate.java @@ -0,0 +1,381 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.eelf.logging; + +import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN; +import static com.att.eelf.configuration.Configuration.MDC_SERVER_IP_ADDRESS; +import static com.att.eelf.configuration.Configuration.MDC_SERVICE_INSTANCE_ID; +import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME; +import java.net.InetAddress; +import java.text.MessageFormat; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import javax.servlet.http.HttpServletRequest; +import org.slf4j.MDC; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.att.eelf.configuration.SLF4jWrapper; + +public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger { + + public static final EELFLogger errorLogger = EELFManager.getInstance().getErrorLogger(); + public static final EELFLogger applicationLogger = + EELFManager.getInstance().getApplicationLogger(); + public static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger(); + public static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger(); + public static final EELFLogger debugLogger = EELFManager.getInstance().getDebugLogger(); + public static final EELFLogger securityLogger = EELFManager.getInstance().getSecurityLogger(); + + private String className; + private static ConcurrentMap<String, EELFLoggerDelegate> classMap = new ConcurrentHashMap<>(); + + public EELFLoggerDelegate(final String className) { + super(className); + this.className = className; + } + + /** + * Convenience method that gets a logger for the specified class. + * + * @see #getLogger(String) + * + * @param clazz + * @return Instance of EELFLoggerDelegate + */ + public static EELFLoggerDelegate getLogger(Class<?> clazz) { + return getLogger(clazz.getName()); + } + + /** + * Gets a logger for the specified class name. If the logger does not already exist in the map, + * this creates a new logger. + * + * @param className If null or empty, uses EELFLoggerDelegate as the class name. + * @return Instance of EELFLoggerDelegate + */ + public static EELFLoggerDelegate getLogger(final String className) { + String classNameNeverNull = className == null || "".equals(className) + ? EELFLoggerDelegate.class.getName() + : className; + EELFLoggerDelegate delegate = classMap.get(classNameNeverNull); + if (delegate == null) { + delegate = new EELFLoggerDelegate(className); + classMap.put(className, delegate); + } + return delegate; + } + + /** + * Logs a message at the lowest level: trace. + * + * @param logger + * @param msg + */ + public void trace(EELFLogger logger, String msg) { + if (logger.isTraceEnabled()) { + logger.trace(msg); + } + } + + /** + * Logs a message with parameters at the lowest level: trace. + * + * @param logger + * @param msg + * @param arguments + */ + public void trace(EELFLogger logger, String msg, Object... arguments) { + if (logger.isTraceEnabled()) { + logger.trace(msg, arguments); + } + } + + /** + * Logs a message and throwable at the lowest level: trace. + * + * @param logger + * @param msg + * @param th + */ + public void trace(EELFLogger logger, String msg, Throwable th) { + if (logger.isTraceEnabled()) { + logger.trace(msg, th); + } + } + + /** + * Logs a message at the second-lowest level: debug. + * + * @param logger + * @param msg + */ + public void debug(EELFLogger logger, String msg) { + if (logger.isDebugEnabled()) { + logger.debug(msg); + } + } + + /** + * Logs a message with parameters at the second-lowest level: debug. + * + * @param logger + * @param msg + * @param arguments + */ + public void debug(EELFLogger logger, String msg, Object... arguments) { + if (logger.isDebugEnabled()) { + logger.debug(msg, arguments); + } + } + + /** + * Logs a message and throwable at the second-lowest level: debug. + * + * @param logger + * @param msg + * @param th + */ + public void debug(EELFLogger logger, String msg, Throwable th) { + if (logger.isDebugEnabled()) { + logger.debug(msg, th); + } + } + + /** + * Logs a message at info level. + * + * @param logger + * @param msg + */ + public void info(EELFLogger logger, String msg) { + logger.info(className + " - "+msg); + } + + /** + * Logs a message with parameters at info level. + * + * @param logger + * @param msg + * @param arguments + */ + public void info(EELFLogger logger, String msg, Object... arguments) { + logger.info(msg, arguments); + } + + /** + * Logs a message and throwable at info level. + * + * @param logger + * @param msg + * @param th + */ + public void info(EELFLogger logger, String msg, Throwable th) { + logger.info(msg, th); + } + + /** + * Logs a message at warn level. + * + * @param logger + * @param msg + */ + public void warn(EELFLogger logger, String msg) { + logger.warn(msg); + } + + /** + * Logs a message with parameters at warn level. + * + * @param logger + * @param msg + * @param arguments + */ + public void warn(EELFLogger logger, String msg, Object... arguments) { + logger.warn(msg, arguments); + } + + /** + * Logs a message and throwable at warn level. + * + * @param logger + * @param msg + * @param th + */ + public void warn(EELFLogger logger, String msg, Throwable th) { + logger.warn(msg, th); + } + + /** + * Logs a message at error level. + * + * @param logger + * @param msg + * + */ + public void error(EELFLogger logger, String msg) { + logger.error(className+ " - " + msg); + } + + /** + * Logs a message at error level. + * + * @param logger + * @param msg + */ + public void error(EELFLogger logger, Exception e) { + logger.error(className+ " - ", e); + } + + /** + * Logs a message with parameters at error level. + * + * @param logger + * @param msg + * @param arguments + * + */ + public void error(EELFLogger logger, String msg, Object... arguments) { + logger.error(msg, arguments); + } + + /** + * Logs a message with parameters at error level. + * + * @param logger + * @param msg + * @param arguments + */ + public void error(EELFLogger logger, Exception e, Object... arguments) { + logger.error("Exception", e, arguments); + } + + /** + * Logs a message and throwable at error level. + * + * @param logger + * @param msg + * @param th + */ + public void error(EELFLogger logger, String msg, Throwable th) { + logger.error(msg, th); + } + + /** + * Logs a message with the associated alarm severity at error level. + * + * @param logger + * @param msg + * @param severtiy + */ + public void error(EELFLogger logger, String msg, Object /* AlarmSeverityEnum */ severtiy) { + logger.error(msg); + } + + /** + * Initializes the logger context. + */ + public void init() { + setGlobalLoggingContext(); + final String msg = + "############################ Logging is started. ############################"; + // These loggers emit the current date-time without being told. + info(applicationLogger, msg); + error(errorLogger, msg); + debug(debugLogger, msg); + info(auditLogger, msg); + info(metricsLogger, msg); + info(securityLogger, msg); + + } + + /** + * Builds a message using a template string and the arguments. + * + * @param message + * @param args + * @return + */ + private String formatMessage(String message, Object... args) { + StringBuilder sbFormattedMessage = new StringBuilder(); + if (args != null && args.length > 0 && message != null && message != "") { + MessageFormat mf = new MessageFormat(message); + sbFormattedMessage.append(mf.format(args)); + } else { + sbFormattedMessage.append(message); + } + + return sbFormattedMessage.toString(); + } + + /** + * Loads all the default logging fields into the MDC context. + */ + private void setGlobalLoggingContext() { + MDC.put(MDC_SERVICE_INSTANCE_ID, ""); + try { + MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName()); + MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress()); + } catch (Exception e) { + errorLogger.error("setGlobalLoggingContext failed", e); + } + } + + public static void mdcPut(String key, String value) { + MDC.put(key, value); + } + + public static String mdcGet(String key) { + return MDC.get(key); + } + + public static void mdcRemove(String key) { + MDC.remove(key); + } + + /** + * Loads the RequestId/TransactionId into the MDC which it should be receiving with an each + * incoming REST API request. Also, configures few other request based logging fields into the + * MDC context. + * + * @param req + * @param appName + */ + public void setRequestBasedDefaultsIntoGlobalLoggingContext(HttpServletRequest req, + String appName) { + // Load the default fields + setGlobalLoggingContext(); + + // Load the request based fields + if (req != null) { + // Rest Path + MDC.put(MDC_SERVICE_NAME, req.getServletPath()); + + // Client IPAddress i.e. IPAddress of the remote host who is making + // this request. + String clientIPAddress = req.getHeader("X-FORWARDED-FOR"); + if (clientIPAddress == null) { + clientIPAddress = req.getRemoteAddr(); + } + } + } +} diff --git a/music-core/src/main/java/org/onap/music/eelf/logging/format/AppMessages.java b/music-core/src/main/java/org/onap/music/eelf/logging/format/AppMessages.java new file mode 100644 index 00000000..5af3661c --- /dev/null +++ b/music-core/src/main/java/org/onap/music/eelf/logging/format/AppMessages.java @@ -0,0 +1,188 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * Copyright (c) 2019 IBM Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.eelf.logging.format; + +/** + * @author inam + * + */ +public enum AppMessages { + + + + /* + * 100-199 Security/Permission Related - Authentication problems + * [ERR100E] Missing Information + * [ERR101E] Authentication error occured + * + * 200-299 Availability/Timeout Related/IO - connectivity error - connection timeout + * [ERR200E] Connectivity + * [ERR201E] Host not available + * [ERR202E] Error while connecting to Cassandra cluster + * [ERR203E] IO Error has occured + * [ERR204E] Execution Interrupted + * [ERR205E] Session Expired + * [ERR206E] Cache not authenticated + * + * + * 300-399 Data Access/Integrity Related + * [ERR300E] Incorrect data + * + * 400-499 - Cassandra Query Related + * [ERR400E] Error while processing prepared query object + * [ERR401E] Executing Session Failure for Request + * [ERR402E] Ill formed queryObject for the request + * [ERR403E] Error processing Prepared Query Object + * + * 500-599 - Locking Related + * [ERR500E] Invalid lock + * [ERR501E] Locking Error has occured + * [ERR502E] Deprecated + * [ERR503E] Failed to aquire lock store handle + * [ERR504E] Failed to create Lock Reference + * [ERR505E] Lock does not exist + * [ERR506E] Failed to aquire lock + * [ERR507E] Lock not aquired + * [ERR508E] Lock state not set + * [ERR509E] Lock not destroyed + * [ERR510E] Lock not released + * [ERR511E] Lock not deleted + * [ERR512E] Deprecated + * + * + * 600 - 699 - Music Service Errors + * [ERR600E] Error initializing the cache + * + * 700-799 Schema Interface Type/Validation - received Pay-load checksum is + * invalid - received JSON is not valid + * + * 800-899 Business/Flow Processing Related - check out to service is not + * allowed - Roll-back is done - failed to generate heat file + * + * + * 900-999 Unknown Errors - Unexpected exception + * [ERR900E] Unexpected error occured + * [ERR901E] Number format exception + * + * + * 1000-1099 Reserved - do not use + * + */ + + + + + MISSINGINFO("[ERR100E]", "Missing Information ","Details: NA", "Please check application credentials and/or headers"), + AUTHENTICATIONERROR("[ERR101E]", "Authentication error occured ","Details: NA", "Please verify application credentials"), + CONNCECTIVITYERROR("[ERR200E]"," Connectivity error","Details: NA ","Please check connectivity to external resources"), + HOSTUNAVAILABLE("[ERR201E]","Host not available","Details: NA","Please verify the host details"), + CASSANDRACONNECTIVITY("[ERR202E]","Error while connecting to Cassandra cluster",""," Please check cassandra cluster details"), + IOERROR("[ERR203E]","IO Error has occured","","Please check IO"), + EXECUTIONINTERRUPTED("[ERR204E]"," Execution Interrupted","",""), + SESSIONEXPIRED("[ERR205E]"," Session Expired","","Session has expired."), + CACHEAUTHENTICATION("[ERR206E]","Cache not authenticated",""," Cache not authenticated"), + + INCORRECTDATA("[ERR300E]"," Incorrect data",""," Please verify the request payload and try again"), + MULTIPLERECORDS("[ERR301E]"," Multiple records found",""," Please verify the request payload and try again"), + ALREADYEXIST("[ERR302E]"," Record already exist",""," Please verify the request payload and try again"), + MISSINGDATA("[ERR300E]"," Incorrect data",""," Please verify the request payload and try again"), + + QUERYERROR("[ERR400E]","Error while processing prepared query object",""," Please verify the query"), + SESSIONFAILED("[ERR401E]","Executing Session Failure for Request","","Please verify the session and request"), + + INVALIDLOCK("[ERR500E]"," Invalid lock or acquire failed",""," Lock is not valid to aquire"), + LOCKINGERROR("[ERR501E]"," Locking Error has occured",""," Locking Error has occured"), + LOCKHANDLE("[ERR503E]","Failed to aquire lock store handle",""," Failed to aquire lock store handle"), + CREATELOCK("[ERR504E]","Failed to aquire lock store handle ","","Failed to aquire lock store handle "), + LOCKSTATE("[ERR508E]"," Lock state not set",""," Lock state not set"), + DESTROYLOCK("[ERR509E]"," Lock not destroyed",""," Lock not destroyed"), + RELEASELOCK("[ERR510E]"," Lock not released",""," Lock not released"), + DELTELOCK("[ERR511E]",""," Lock not deleted "," Lock not deleted "), + CACHEERROR("[ERR600E]"," Error initializing the cache",""," Error initializing the cache"), + + UNKNOWNERROR("[ERR900E]"," Unexpected error occured",""," Please check logs for details"); + + + + + private ErrorTypes eType; + private ErrorSeverity alarmSeverity; + private ErrorSeverity errorSeverity; + private String errorCode; + private String errorDescription; + private String details; + private String resolution; + + + AppMessages(String errorCode, String errorDescription, String details,String resolution) { + + this.errorCode = errorCode; + this.errorDescription = errorDescription; + this.details = details; + this.resolution = resolution; + } + + + public ErrorTypes getEType() { + return eType; + } + + public ErrorSeverity getAlarmSeverity() { + return alarmSeverity; + } + public ErrorSeverity getErrorSeverity() { + return errorSeverity; + } + + public void setDetails(String details){ this.details=details; } + + public String getDetails() { + return this.details; + } + + public void setResolution(String resolution){ this.resolution=resolution; } + + public String getResolution() { + return this.resolution; + } + + public void setErrorCode(String errorCode){ this.errorCode=errorCode; } + + public String getErrorCode() { + return this.errorCode; + } + + public void setErrorDescription(String errorDescription){ this.errorDescription=errorDescription; } + + public String getErrorDescription() { + return this.errorDescription; + } + + + + + + + +} diff --git a/music-core/src/main/java/org/onap/music/eelf/logging/format/ErrorCodes.java b/music-core/src/main/java/org/onap/music/eelf/logging/format/ErrorCodes.java new file mode 100644 index 00000000..91ee3473 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/eelf/logging/format/ErrorCodes.java @@ -0,0 +1,107 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.eelf.logging.format; + + + +/** + * @author inam + * + */ +public enum ErrorCodes { + + + /* + * 100-199 Security/Permission Related - Authentication problems + * [ERR100E] Missing Information + * [ERR101E] Authentication error occured + * + * 200-299 Availability/Timeout Related/IO - connectivity error - connection timeout + * [ERR200E] Connectivity + * [ERR201E] Host not available + * [ERR202E] Error while connecting to Cassandra cluster + * [ERR203E] IO Error has occured + * [ERR204E] Execution Interrupted + * [ERR205E] Session Expired + * [ERR206E] Cache not authenticated + * + * + * 300-399 Data Access/Integrity Related + * + * 400-499 - Cassandra Query Related + * [ERR400E] Error while processing prepared query object + * [ERR401E] Executing Session Failure for Request + * [ERR402E] Ill formed queryObject for the request + * [ERR403E] Error processing Prepared Query Object + * + * 500-599 - Zookeepr/Locking Related + * [ERR500E] Invalid lock + * [ERR501E] Locking Error has occured + * [ERR502E] Zookeeper error has occured + * [ERR503E] Failed to aquire lock store handle + * [ERR504E] Failed to create Lock Reference + * [ERR505E] Lock does not exist + * [ERR506E] Failed to aquire lock + * [ERR507E] Lock not aquired + * [ERR508E] Lock state not set + * [ERR509E] Lock not destroyed + * [ERR510E] Lock not released + * [ERR511E] Lock not deleted + * [ERR512E] Failed to get Lock Handle + * + * + * 600 - 699 - Music Service Errors + * [ERR600E] Error initializing the cache + * + * 700-799 Schema Interface Type/Validation - received Pay-load checksum is + * invalid - received JSON is not valid + * + * 800-899 Business/Flow Processing Related - check out to service is not + * allowed - Roll-back is done - failed to generate heat file + * + * + * 900-999 Unknown Errors - Unexpected exception + * [ERR900E] Unexpected error occured + * [ERR901E] Number format exception + * + * + * 1000-1099 Reserved - do not use + * + */ + + /*SUCCESS("Success"), FAILURE("Failure"); + + private String result; + + ResultType(String result) { + this.result = result; + } + + public String getResult() { + return result; + } +*/ + + + +} diff --git a/music-core/src/main/java/org/onap/music/eelf/logging/format/ErrorSeverity.java b/music-core/src/main/java/org/onap/music/eelf/logging/format/ErrorSeverity.java new file mode 100644 index 00000000..4e798239 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/eelf/logging/format/ErrorSeverity.java @@ -0,0 +1,38 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.eelf.logging.format; + +/** + * @author inam + * + */ +public enum ErrorSeverity { + INFO, + WARN, + ERROR, + FATAL, + CRITICAL, + MAJOR, + MINOR, + NONE, +} diff --git a/music-core/src/main/java/org/onap/music/eelf/logging/format/ErrorTypes.java b/music-core/src/main/java/org/onap/music/eelf/logging/format/ErrorTypes.java new file mode 100644 index 00000000..9bdbf20f --- /dev/null +++ b/music-core/src/main/java/org/onap/music/eelf/logging/format/ErrorTypes.java @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.eelf.logging.format; + +import com.att.eelf.i18n.EELFResolvableErrorEnum; + +/** + * @author inam + * + */ +public enum ErrorTypes implements EELFResolvableErrorEnum { + + + CONNECTIONERROR, + SESSIONEXPIRED, + AUTHENTICATIONERROR, + CACHEERROR, + SERVICEUNAVAILABLE, + QUERYERROR, + DATAERROR, + GENERALSERVICEERROR, + MUSICSERVICEERROR, + LOCKINGERROR, + UNKNOWN, + +} diff --git a/music-core/src/main/java/org/onap/music/exceptions/MusicDeadlockException.java b/music-core/src/main/java/org/onap/music/exceptions/MusicDeadlockException.java new file mode 100644 index 00000000..7a40ed91 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/exceptions/MusicDeadlockException.java @@ -0,0 +1,75 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.exceptions; + +public class MusicDeadlockException extends MusicLockingException { + + private String owner = null; + private String keyspace = null; + private String table = null; + private String key = null; + + public MusicDeadlockException() { + super(); + } + + public MusicDeadlockException(String message) { + super(message); + } + + public MusicDeadlockException(Throwable cause) { + super(cause); + } + + public MusicDeadlockException(String message, Throwable cause) { + super(message, cause); + } + + public MusicDeadlockException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public void setValues(String owner, String keyspace, String table, String key) { + this.owner = owner; + this.keyspace = keyspace; + this.table = table; + this.key = key; + } + + public String getOwner() { + return owner; + } + + public String getKeyspace() { + return keyspace; + } + + public String getTable() { + return table; + } + + public String getKey() { + return key; + } + + +} diff --git a/music-core/src/main/java/org/onap/music/exceptions/MusicLockingException.java b/music-core/src/main/java/org/onap/music/exceptions/MusicLockingException.java new file mode 100644 index 00000000..ab70c54c --- /dev/null +++ b/music-core/src/main/java/org/onap/music/exceptions/MusicLockingException.java @@ -0,0 +1,75 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.exceptions; + +/** + * @author inam + * + */ +public class MusicLockingException extends Exception { + + /** + * + */ + public MusicLockingException() { + + } + + /** + * @param message + */ + public MusicLockingException(String message) { + super(message); + + } + + /** + * @param cause + */ + public MusicLockingException(Throwable cause) { + super(cause); + + } + + /** + * @param message + * @param cause + */ + public MusicLockingException(String message, Throwable cause) { + super(message, cause); + + } + + /** + * @param message + * @param cause + * @param enableSuppression + * @param writableStackTrace + */ + public MusicLockingException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + + } + +} diff --git a/music-core/src/main/java/org/onap/music/exceptions/MusicPolicyVoilationException.java b/music-core/src/main/java/org/onap/music/exceptions/MusicPolicyVoilationException.java new file mode 100644 index 00000000..f489cd45 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/exceptions/MusicPolicyVoilationException.java @@ -0,0 +1,82 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (c) 2018 IBM + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.exceptions; + +/** + * @author inam + * + */ +public class MusicPolicyVoilationException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * + */ + public MusicPolicyVoilationException() { + + } + + /** + * @param message + */ + public MusicPolicyVoilationException(String message) { + super(message); + + } + + /** + * @param cause + */ + public MusicPolicyVoilationException(Throwable cause) { + super(cause); + + } + + /** + * @param message + * @param cause + */ + public MusicPolicyVoilationException(String message, Throwable cause) { + super(message, cause); + + } + + /** + * @param message + * @param cause + * @param enableSuppression + * @param writableStackTrace + */ + public MusicPolicyVoilationException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + + } + +} diff --git a/music-core/src/main/java/org/onap/music/exceptions/MusicQueryException.java b/music-core/src/main/java/org/onap/music/exceptions/MusicQueryException.java new file mode 100644 index 00000000..803f993f --- /dev/null +++ b/music-core/src/main/java/org/onap/music/exceptions/MusicQueryException.java @@ -0,0 +1,90 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.exceptions; + + + +/** + * @author inam + * + */ +public class MusicQueryException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + private int errorCode; + + + /** + * + */ + public MusicQueryException() { + super(); + } + + /** + * @param message + */ + public MusicQueryException(String message) { + super(message); + } + + + + /** + * @param message + */ + public MusicQueryException(String message, int errorCode) { + super(message); + this.errorCode = errorCode; + } + + /** + * @param cause + */ + public MusicQueryException(Throwable cause) { + super(cause); + } + + /** + * @param message + * @param cause + */ + public MusicQueryException(String message, Throwable cause) { + super(message, cause); + } + + /** + * @param message + * @param cause + * @param enableSuppression + * @param writableStackTrace + */ + public MusicQueryException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + +} diff --git a/music-core/src/main/java/org/onap/music/exceptions/MusicServiceException.java b/music-core/src/main/java/org/onap/music/exceptions/MusicServiceException.java new file mode 100644 index 00000000..76e1f948 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/exceptions/MusicServiceException.java @@ -0,0 +1,88 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (C) 2018 IBM. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.exceptions; + +/** + * @author inam + * + */ +public class MusicServiceException extends Exception { + + + private int errorCode; + private String errorMessage; + + public MusicServiceException() { + super(); + } + + + public MusicServiceException(String message) { + super(message); + + } + + public MusicServiceException(String message, int errorCode) { + super(message); + this.errorCode=errorCode; + } + + public MusicServiceException(String message, int errorCode, String errorMessage) { + super(message); + this.errorCode=errorCode; + this.errorMessage=errorMessage; + } + + public MusicServiceException(Throwable cause) { + super(cause); + + } + + + public MusicServiceException(String message, Throwable cause) { + super(message, cause); + + } + + + public MusicServiceException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + + } + public void setErrorCode(int errorCode) { + this.errorCode=errorCode; + } + + public int getErrorCode() { + return errorCode; + } + public void setErrorMessage(String errorMessage) { + this.errorMessage=errorMessage; + } + public String getErrorMessage() { + return errorMessage; + } +} diff --git a/music-core/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java b/music-core/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java new file mode 100644 index 00000000..9a69a9ba --- /dev/null +++ b/music-core/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java @@ -0,0 +1,613 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * Modifications Copyright (C) 2019 IBM. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.lockingservice.cassandra; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.onap.music.datastore.MusicDataStore; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.exceptions.MusicLockingException; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.DeadlockDetectionUtil; +import org.onap.music.main.DeadlockDetectionUtil.OwnershipType; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import org.onap.music.main.ReturnType; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; + +/* + * This is the lock store that is built on top of Cassandra that is used by MUSIC to maintain lock state. + */ + +public class CassaLockStore { + + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CassaLockStore.class); + public static final String table_prepend_name = "lockQ_"; + private MusicDataStore dsHandle; + + public CassaLockStore() { + dsHandle = new MusicDataStore(); + } + + public CassaLockStore(MusicDataStore dsHandle) { + this.dsHandle=dsHandle; + } + public class LockObject{ + private boolean isLockOwner; + private String lockRef; + private String createTime; + private String acquireTime; + private LockType locktype; + // Owner is the self-declared client which "owns" this row. It is used for deadlock detection. It is not (directly) related to isLockOwner. + private String owner; + public LockObject(boolean isLockOwner, String lockRef, String createTime, String acquireTime, LockType locktype, String owner) { + this.setIsLockOwner(isLockOwner); + this.setLockRef(lockRef); + this.setAcquireTime(acquireTime); + this.setCreateTime(createTime); + this.setLocktype(locktype); + this.setOwner(owner); + } + public boolean getIsLockOwner() { + return isLockOwner; + } + public void setIsLockOwner(boolean isLockOwner) { + this.isLockOwner = isLockOwner; + } + public String getAcquireTime() { + return acquireTime; + } + public void setAcquireTime(String acquireTime) { + this.acquireTime = acquireTime; + } + public String getCreateTime() { + return createTime; + } + public void setCreateTime(String createTime) { + this.createTime = createTime; + } + public String getLockRef() { + return lockRef; + } + public void setLockRef(String lockRef) { + this.lockRef = lockRef; + } + public LockType getLocktype() { + return locktype; + } + public void setLocktype(LockType locktype) { + this.locktype = locktype; + } + public String getOwner() { + return owner; + } + public void setOwner(String owner) { + this.owner = owner; + } + } + + /** + * + * This method creates a shadow locking table for every main table in Cassandra. This table tracks all information regarding locks. + * @param keyspace of the application. + * @param table of the application. + * @return true if the operation was successful. + * @throws MusicServiceException + * @throws MusicQueryException + */ + public boolean createLockQueue(String keyspace, String table) throws MusicServiceException, MusicQueryException { + logger.info(EELFLoggerDelegate.applicationLogger, + "Create lock queue/table for " + keyspace+"."+table); + table = table_prepend_name+table; + String tabQuery = "CREATE TABLE IF NOT EXISTS "+keyspace+"."+table + + " ( key text, lockReference bigint, createTime text, acquireTime text, guard bigint static, " + + "lockType text, leasePeriodTime bigint, owner text, PRIMARY KEY ((key), lockReference) ) " + + "WITH CLUSTERING ORDER BY (lockReference ASC);"; + PreparedQueryObject queryObject = new PreparedQueryObject(); + + queryObject.appendQueryString(tabQuery); + boolean result; + result = dsHandle.executePut(queryObject, "eventual"); + return result; + } + + /** + * This method creates a lock reference for each invocation. The lock references are monotonically increasing timestamps. + * @param keyspace of the locks. + * @param table of the locks. + * @param lockName is the primary key of the lock table + * @param lockType is the type of lock (read/write) + * @param owner is the owner of the lock (optional, for deadlock detection) + * @return the UUID lock reference. + * @throws MusicServiceException + * @throws MusicQueryException + */ + public String genLockRefandEnQueue(String keyspace, String table, String lockName, LockType locktype, String owner) throws MusicServiceException, MusicQueryException, MusicLockingException { + return genLockRefandEnQueue(keyspace, table, lockName, locktype, owner, 0); + } + + private String genLockRefandEnQueue(String keyspace, String table, String lockName, LockType locktype, String owner, int count) throws MusicServiceException, MusicQueryException, MusicLockingException { + logger.info(EELFLoggerDelegate.applicationLogger, + "Create " + locktype + " lock reference for " + keyspace + "." + table + "." + lockName); + String lockTable =""; + lockTable = table_prepend_name+table; + + PreparedQueryObject queryObject = new PreparedQueryObject(); + String selectQuery = "SELECT guard FROM " + keyspace + "." + lockTable + " WHERE key=?;"; + + queryObject.addValue(lockName); + queryObject.appendQueryString(selectQuery); + ResultSet gqResult = dsHandle.executeOneConsistencyGet(queryObject); + List<Row> latestGuardRow = gqResult.all(); + + long prevGuard = 0; + long lockRef = 1; + if (!latestGuardRow.isEmpty()) { + prevGuard = latestGuardRow.get(0).getLong(0); + lockRef = prevGuard + 1; + } + + long lockEpochMillis = System.currentTimeMillis(); + + logger.info(EELFLoggerDelegate.applicationLogger, + "Created lock reference for " + keyspace + "." + lockTable + "." + lockName + ":" + lockRef); + + queryObject = new PreparedQueryObject(); + + String insQuery = "BEGIN BATCH" + + " UPDATE " + keyspace + "." + lockTable + + " SET guard=? WHERE key=? IF guard = " + (prevGuard == 0 ? "NULL" : "?") +";" + + " INSERT INTO " + keyspace + "." + lockTable + + "(key, lockReference, createTime, acquireTime, lockType, owner) VALUES (?,?,?,?,?,?) IF NOT EXISTS; APPLY BATCH;"; + + queryObject.addValue(lockRef); + queryObject.addValue(lockName); + if (prevGuard != 0) + queryObject.addValue(prevGuard); + + queryObject.addValue(lockName); + queryObject.addValue(lockRef); + queryObject.addValue(String.valueOf(lockEpochMillis)); + queryObject.addValue("0"); + queryObject.addValue(locktype); + queryObject.addValue(owner); + queryObject.appendQueryString(insQuery); + boolean pResult = dsHandle.executePut(queryObject, "critical"); + if (!pResult) {// couldn't create lock ref, retry + count++; + if (count > MusicUtil.getRetryCount()) { + logger.warn(EELFLoggerDelegate.applicationLogger, "Unable to create lock reference"); + throw new MusicLockingException("Unable to create lock reference"); + } + return genLockRefandEnQueue(keyspace, table, lockName, locktype, owner, count); + } + return "$" + keyspace + "." + table + "." + lockName + "$" + String.valueOf(lockRef); + } + + /** + * Returns a result set containing the list of clients waiting for a particular lock + * + * @param keyspace + * @param table + * @param key + * @return list of lockrefs in the queue + * @throws MusicServiceException + * @throws MusicQueryException + */ + public List<String> getLockQueue(String keyspace, String table, String key) + throws MusicServiceException, MusicQueryException { + logger.info(EELFLoggerDelegate.applicationLogger, + "Getting the queue for " + keyspace + "." + table + "." + key); + table = table_prepend_name + table; + String selectQuery = "select * from " + keyspace + "." + table + " where key='" + key + "';"; + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString(selectQuery); + ResultSet rs = dsHandle.executeOneConsistencyGet(queryObject); + ArrayList<String> lockQueue = new ArrayList<>(); + for (Row row : rs) { + lockQueue.add(Long.toString(row.getLong("lockReference"))); + } + return lockQueue; + } + + + /** + * Returns a result set containing the list of clients waiting for a particular lock + * + * @param keyspace + * @param table + * @param key + * @return size of lockrefs queue + * @throws MusicServiceException + * @throws MusicQueryException + */ + public long getLockQueueSize(String keyspace, String table, String key) + throws MusicServiceException, MusicQueryException { + logger.info(EELFLoggerDelegate.applicationLogger, + "Getting the queue size for " + keyspace + "." + table + "." + key); + table = table_prepend_name + table; + String selectQuery = "select count(*) from " + keyspace + "." + table + " where key='" + key + "';"; + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString(selectQuery); + ResultSet rs = dsHandle.executeOneConsistencyGet(queryObject); + return rs.one().getLong("count"); + } + + + /** + * This method returns the top of lock table/queue for the key. + * + * @param keyspace of the application. + * @param table of the application. + * @param key is the primary key of the application table + * @return the UUID lock reference. Returns LockObject.isLockOwner=false if there is no owner or the + * lock doesn't exist + * @throws MusicServiceException + * @throws MusicQueryException + */ + public LockObject peekLockQueue(String keyspace, String table, String key) + throws MusicServiceException, MusicQueryException { + logger.info(EELFLoggerDelegate.applicationLogger, + "Peek in lock table for " + keyspace + "." + table + "." + key); + table = table_prepend_name + table; + String selectQuery = "select * from " + keyspace + "." + table + " where key='" + key + "' LIMIT 1;"; + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString(selectQuery); + ResultSet results = dsHandle.executeOneConsistencyGet(queryObject); + Row row = results.one(); + if (row == null || row.isNull("lockReference")) { + return new LockObject(false, null, null, null, null, null); + } + String lockReference = "" + row.getLong("lockReference"); + String createTime = row.getString("createTime"); + String acquireTime = row.getString("acquireTime"); + LockType locktype = row.get("lockType", LockType.class); + String owner = row.getString("owner"); + + return new LockObject(true, lockReference, createTime, acquireTime, locktype, owner); + } + + public List<String> getCurrentLockHolders(String keyspace, String table, String key) + throws MusicServiceException, MusicQueryException { + logger.info(EELFLoggerDelegate.applicationLogger, + "Getting lockholders in lock table for " + keyspace + "." + table + "." + key); + String origTable = table; + table = table_prepend_name + table; + String selectQuery = "select * from " + keyspace + "." + table + " where key=?;"; + List<String> lockHolders = new ArrayList<>(); + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString(selectQuery); + queryObject.addValue(key); + ResultSet rs = dsHandle.executeOneConsistencyGet(queryObject); + boolean topOfQueue = true; + StringBuilder lock = new StringBuilder(). + append("$").append(keyspace).append(".").append(origTable). + append(".").append(key).append("$"); + StringBuilder lockReference = new StringBuilder(); + for (Row row : rs) { + if ( row.isNull("lockReference") ) { + return lockHolders; + } + lockReference.append(lock).append(row.getLong("lockReference")); + if (row.get("lockType", LockType.class)!=LockType.WRITE) { + if (topOfQueue) { + lockHolders.add(lockReference.toString()); + break; + } else { + break; + } + } + // read lock + lockHolders.add(lockReference.toString()); + + topOfQueue = false; + lockReference.delete(0,lockReference.length()); + } + return lockHolders; + } + + /** + * Determine if the lock is a valid current lock holder. + * + * @param keyspace + * @param table + * @param key + * @param lockRef + * @return true if lockRef is a lock owner of key + * @throws MusicServiceException + * @throws MusicQueryException + */ + public boolean isLockOwner(String keyspace, String table, String key, String lockRef) + throws MusicServiceException, MusicQueryException { + logger.info(EELFLoggerDelegate.applicationLogger, + "Checking in lock table for " + keyspace + "." + table + "." + key); + table = table_prepend_name + table; + String selectQuery = + "select * from " + keyspace + "." + table + " where key=?;"; + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString(selectQuery); + queryObject.addValue(key); + ResultSet rs = dsHandle.executeOneConsistencyGet(queryObject); + + boolean topOfQueue = true; + for (Row row : rs) { + String lockReference = "" + row.getLong("lockReference"); + if (row.get("lockType", LockType.class)==LockType.WRITE) { + if (topOfQueue && lockRef.equals(lockReference)) { + return true; + } else { + return false; + } + } + if (lockRef.equals(lockReference)) { + return true; + } + topOfQueue = false; + } + logger.info(EELFLoggerDelegate.applicationLogger, "Could not find " + lockRef + + " in the lock queue. It has expired and no longer exists."); + return false; + } + + /** + * Determine if the lock is a valid current lock holder. + * + * @param keyspace + * @param table + * @param key + * @param lockRef + * @return true if lockRef is a lock owner of key + * @throws MusicServiceException + * @throws MusicQueryException + */ + public LockObject getLockInfo(String keyspace, String table, String key, String lockRef) + throws MusicServiceException, MusicQueryException { + logger.info(EELFLoggerDelegate.applicationLogger, + "Checking in lock table for " + keyspace + "." + table + "." + key); + String lockQ_table = table_prepend_name + table; + String selectQuery = + "select * from " + keyspace + "." + lockQ_table + " where key=? and lockReference=?;"; + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString(selectQuery); + queryObject.addValue(key); + queryObject.addValue(Long.parseLong(lockRef)); + ResultSet rs = dsHandle.executeOneConsistencyGet(queryObject); + Row row = rs.one(); + if (row == null || row.isNull("lockReference")) { + return null; + } + + String lockReference = "" + row.getLong("lockReference"); + String createTime = row.getString("createTime"); + String acquireTime = row.getString("acquireTime"); + LockType locktype = row.get("lockType", LockType.class); + boolean isLockOwner = isLockOwner(keyspace, table, key, lockRef); + String owner = row.getString("owner"); + + return new LockObject(isLockOwner, lockReference, createTime, acquireTime, locktype, owner); + } + + + + /** + * This method removes the lock ref from the lock table/queue for the key. + * + * @param keyspace of the application. + * @param table of the application. + * @param key is the primary key of the application table + * @param lockReference the lock reference that needs to be dequeued. + * @throws MusicServiceException + * @throws MusicQueryException + * @throws MusicLockingException + */ + public void deQueueLockRef(String keyspace, String table, String key, String lockReference, int n) + throws MusicServiceException, MusicQueryException, MusicLockingException { + String prependTable = table_prepend_name + table; + PreparedQueryObject queryObject = new PreparedQueryObject(); + Long lockReferenceL = Long.parseLong(lockReference.substring(lockReference.lastIndexOf("$") + 1)); + String deleteQuery = "delete from " + keyspace + "." + prependTable + " where key='" + key + + "' AND lockReference =" + lockReferenceL + " IF EXISTS;"; + queryObject.appendQueryString(deleteQuery); + logger.info(EELFLoggerDelegate.applicationLogger, "Removing lock for key: "+key+ " and reference: "+lockReference); + try { + dsHandle.executePut(queryObject, "critical"); + logger.info(EELFLoggerDelegate.applicationLogger, + "Lock removed for key: " + key + " and reference: " + lockReference); + } catch (MusicServiceException ex) { + logger.error(logger, ex.getMessage(), ex); + logger.error(EELFLoggerDelegate.applicationLogger, + "Exception while deQueueLockRef for lockname: " + key + " reference:" + lockReference); + if (n > 1) { + logger.info(EELFLoggerDelegate.applicationLogger, "Trying again..."); + deQueueLockRef(keyspace, table, key, lockReference, n - 1); + } else { + logger.error(EELFLoggerDelegate.applicationLogger, + "deQueueLockRef failed for lockname: " + key + " reference:" + lockReference); + logger.error(logger, ex.getMessage(), ex); + throw new MusicLockingException("Error while deQueueLockRef: " + ex.getMessage()); + } + } + } + + + public void updateLockAcquireTime(String keyspace, String table, String key, String lockReference) { + table = table_prepend_name + table; + Long lockReferenceL = Long.parseLong(lockReference); + String updateQuery = "update " + keyspace + "." + table + " set acquireTime='" + System.currentTimeMillis() + + "' where key='" + key + "' AND lockReference = " + lockReferenceL + " IF EXISTS;"; + + //cannot use executePut because we need to ignore music timestamp adjustments for lock store + dsHandle.getSession().execute(updateQuery); + } + + public boolean checkForDeadlock(String keyspace, String table, String lockName, LockType locktype, String owner, boolean forAcquire) throws MusicServiceException, MusicQueryException { + if (locktype.equals(LockType.READ)) + return false; + if (owner==null || owner.length()==0) + return false; + + String lockTable = table_prepend_name + table; + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString("SELECT key, acquiretime, owner FROM " + keyspace + "." + lockTable); + queryObject.appendQueryString(" WHERE lockType = ? ALLOW FILTERING"); + queryObject.addValue(LockType.WRITE); + + DeadlockDetectionUtil ddu = getDeadlockDetectionUtil(); + + ResultSet rs = dsHandle.executeLocalQuorumConsistencyGet(queryObject); + logger.debug("rs has " + rs.getAvailableWithoutFetching() + (rs.isFullyFetched()?"":" (or more!)") ); + Iterator<Row> it = rs.iterator(); + while (it.hasNext()) { + Row row = it.next(); + logger.debug("key = " + row.getString("key") + ", time = " + row.getString("acquiretime") + ", owner = " + row.getString("owner") ); + ddu.setExisting(row.getString("key"), row.getString("owner"), ("0".equals(row.getString("acquiretime")))?OwnershipType.CREATED:OwnershipType.ACQUIRED); + } + boolean deadlock = ddu.checkForDeadlock(lockName, owner, forAcquire?OwnershipType.ACQUIRED:OwnershipType.CREATED); + if (deadlock) + logger.warn("Deadlock detected when " + owner + " tried to create lock on " + keyspace + "." + lockTable + "." + lockName); + return deadlock; + } + + /** + * This is used for testing purpose + * @return new DeadlockDetectionUtil object + */ + DeadlockDetectionUtil getDeadlockDetectionUtil() { + return new DeadlockDetectionUtil(); + } + + public List<String> getAllLocksForOwner(String ownerId, String keyspace, String table) throws MusicServiceException, MusicQueryException { + List<String> toRet = new ArrayList<>(); + String lockTable = table_prepend_name + table; + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString("SELECT key, lockreference FROM " + keyspace + "." + lockTable); + queryObject.appendQueryString(" WHERE owner = '" + ownerId + "' ALLOW FILTERING"); + + ResultSet rs = dsHandle.executeQuorumConsistencyGet(queryObject); + Iterator<Row> it = rs.iterator(); + while (it.hasNext()) { + Row row = it.next(); + toRet.add(row.getString("key") + "$" + row.getLong("lockreference")); + } + return toRet; + } + + public ReturnType promoteLock(String keyspace, String table, String key, String lockRef) + throws MusicServiceException, MusicQueryException { + String lockqtable = table_prepend_name + table; + String selectQuery = "select * from " + keyspace + "." + lockqtable + " where key=?;"; + + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString(selectQuery); + queryObject.addValue(key); + ResultSet rs = dsHandle.executeOneConsistencyGet(queryObject); + + long refToPromote = Long.parseLong(lockRef); + + boolean topOfQueue = true; + boolean readBlock = false; + boolean seenLockToPromote = false; + boolean promotionOngoing = false; + long readBlockStart = 0; + long readBlockEnd = 0; + + + for (Row row : rs) { + long ref = row.getLong("lockreference"); + LockType lockType = row.get("lockType", LockType.class); + + if (refToPromote==ref) { + if (promotionOngoing) { + return new ReturnType(ResultType.FAILURE, "Can't promote, already promoting another lockref."); + } + seenLockToPromote = true; + if (!topOfQueue) { + readBlockStart = ref; + readBlockEnd = ref; + break; + } + } else if (!seenLockToPromote && refToPromote<ref) { + return new ReturnType(ResultType.FAILURE, "Lockref does not exist."); + } + + if (lockType==LockType.READ || lockType==LockType.PROMOTING) { + if (!readBlock) { + readBlockStart = ref; + readBlock = true; + } + if (readBlock) { + readBlockEnd = ref; + } + if (lockType==LockType.PROMOTING) { + promotionOngoing = true; + } + } + + if (lockType==LockType.WRITE) { + if (refToPromote==ref) { + return new ReturnType(ResultType.FAILURE, "Lockref is already write."); + } + if (readBlock) { + readBlock = false; + promotionOngoing = false; + if (seenLockToPromote) { + break; + } + //can no longer be lock holder after this + topOfQueue = false; + } + } + } + + if (readBlockStart<=refToPromote && refToPromote<=readBlockEnd) { + if (readBlockStart==refToPromote && refToPromote==readBlockEnd) { + promoteLockTo(keyspace, lockqtable, key, lockRef, LockType.WRITE); + return new ReturnType(ResultType.SUCCESS, "Lock has successfully been upgraded."); + } + promoteLockTo(keyspace, lockqtable, key, lockRef, LockType.PROMOTING); + return new ReturnType(ResultType.FAILURE, "Your lock upgrade is in progress. Check again to see if successful."); + } + + //shouldn't reach here? + return new ReturnType(ResultType.FAILURE,"Promotion failed."); + } + + private void promoteLockTo(String keyspace, String table, String key, String lockRef, LockType newLockType) + throws MusicServiceException, MusicQueryException { + PreparedQueryObject queryObject = + new PreparedQueryObject("UPDATE " + keyspace + "." + table + " SET lockType=? WHERE key='" + key + + "' AND lockReference = " + lockRef + " IF EXISTS;", newLockType); + + //cannot use executePut because we need to ignore music timestamp adjustments for lock store + dsHandle.executePut(queryObject, MusicUtil.QUORUM); + } + + + +} diff --git a/music-core/src/main/java/org/onap/music/lockingservice/cassandra/LockCleanUpDaemon.java b/music-core/src/main/java/org/onap/music/lockingservice/cassandra/LockCleanUpDaemon.java new file mode 100644 index 00000000..623a07c7 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/lockingservice/cassandra/LockCleanUpDaemon.java @@ -0,0 +1,133 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.lockingservice.cassandra; + +import java.util.HashSet; +import java.util.Set; +import org.onap.music.datastore.MusicDataStoreHandle; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; + +public class LockCleanUpDaemon extends Thread { + + boolean terminated = false; + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(LockCleanUpDaemon.class); + + + public LockCleanUpDaemon() { + } + + @Override + public void run() { + if (MusicUtil.getLockDaemonSleepTimeMs()<0) { + terminate(); + } + while (!terminated) { + try { + cleanupStaleLocks(); + } catch (MusicServiceException e) { + logger.warn(EELFLoggerDelegate.applicationLogger, "Unable to clean up locks", e); + } + try { + Thread.sleep(MusicUtil.getLockDaemonSleepTimeMs()); + } catch (InterruptedException e) { + logger.warn(EELFLoggerDelegate.applicationLogger, "Interrupted exception", e); + + } + } + } + + private void cleanupStaleLocks() throws MusicServiceException { + Set<String> lockQTables = getLockQTables(); + logger.info(EELFLoggerDelegate.applicationLogger, "Lock q tables found: " + lockQTables); + for(String lockTable: lockQTables) { + try { + cleanUpLocksFromTable(lockTable); + } catch (MusicServiceException e) { + logger.warn(EELFLoggerDelegate.applicationLogger, "Unable to clear locks on table " + lockTable, e); + } + } + } + + + private Set<String> getLockQTables() throws MusicServiceException { + Set<String> keyspacesToCleanUp = MusicUtil.getKeyspacesToCleanLocks(); + Set<String> lockQTables = new HashSet<>(); + + PreparedQueryObject query = new PreparedQueryObject(); + query.appendQueryString("SELECT keyspace_name, table_name FROM system_schema.tables;"); + ResultSet results = MusicCore.get(query); + + for (Row row: results) { + if (keyspacesToCleanUp.contains(row.getString("keyspace_name")) + && row.getString("table_name").toLowerCase().startsWith(CassaLockStore.table_prepend_name.toLowerCase()) ) { + lockQTables.add(row.getString("keyspace_name") + "." + row.getString("table_name")); + } + } + return lockQTables; + } + + private void cleanUpLocksFromTable(String lockTable) throws MusicServiceException { + PreparedQueryObject query = new PreparedQueryObject(); + query.appendQueryString("SELECT * from " + lockTable); + ResultSet results = MusicCore.get(query); + for (Row lock: results) { + if (!lock.isNull("lockreference")) { + try { + deleteLockIfStale(lockTable, lock); + } catch (MusicServiceException e) { + logger.warn(EELFLoggerDelegate.applicationLogger, "Unable to delete a potentially stale lock " + lock, e); + } + } + } + } + + + private void deleteLockIfStale(String lockTable, Row lock) throws MusicServiceException { + final String CREATETIME="createtime"; + final String ACQUIRETIME="acquiretime"; + if (lock.isNull(CREATETIME) && lock.isNull("acquiretime")) { + return; + } + + long createTime = lock.isNull(CREATETIME) ? 0 : Long.parseLong(lock.getString(CREATETIME)); + long acquireTime = lock.isNull(ACQUIRETIME) ? 0 : Long.parseLong(lock.getString(ACQUIRETIME)); + long row_access_time = Math.max(createTime, acquireTime); + if (System.currentTimeMillis() > row_access_time + MusicUtil.getDefaultLockLeasePeriod()) { + logger.info(EELFLoggerDelegate.applicationLogger, "Stale lock detected and being removed: " + lock); + PreparedQueryObject query = new PreparedQueryObject(); + query.appendQueryString("DELETE FROM " + lockTable + " WHERE key='" + lock.getString("key") + "' AND " + + "lockreference=" + lock.getLong("lockreference") + " IF EXISTS;"); + MusicDataStoreHandle.getDSHandle().getSession().execute(query.getQuery()); + } + } + + public void terminate() { + terminated = true; + } +} diff --git a/music-core/src/main/java/org/onap/music/lockingservice/cassandra/LockType.java b/music-core/src/main/java/org/onap/music/lockingservice/cassandra/LockType.java new file mode 100644 index 00000000..432b1c51 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/lockingservice/cassandra/LockType.java @@ -0,0 +1,30 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + + +package org.onap.music.lockingservice.cassandra; + + +public enum LockType { + WRITE, READ, PROMOTING; +} + diff --git a/music-core/src/main/java/org/onap/music/lockingservice/cassandra/MusicLockState.java b/music-core/src/main/java/org/onap/music/lockingservice/cassandra/MusicLockState.java new file mode 100644 index 00000000..14fb8135 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/lockingservice/cassandra/MusicLockState.java @@ -0,0 +1,144 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.lockingservice.cassandra; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectInputStream; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; + +// the state variable that will be stored in the locking service, capturing the transitions of +public class MusicLockState implements Serializable { + // captures the state of the lock + public enum LockStatus { + UNLOCKED, BEING_LOCKED, LOCKED + } + + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicLockState.class); + private LockStatus lockStatus; + private boolean needToSyncQuorum = false; + private String lockHolder; + private long leasePeriod = Long.MAX_VALUE; + private long leaseStartTime = -1; + private String errorMessage = null; + + public MusicLockState(String errorMessage) { + this.errorMessage = errorMessage; + } + + public MusicLockState(LockStatus lockStatus, String lockHolder) { + this.lockStatus = lockStatus; + this.lockHolder = lockHolder; + } + + public MusicLockState(LockStatus lockStatus, String lockHolder, boolean needToSyncQuorum) { + this.lockStatus = lockStatus; + this.lockHolder = lockHolder; + this.needToSyncQuorum = needToSyncQuorum; + } + + + public long getLeasePeriod() { + return leasePeriod; + } + + public boolean isNeedToSyncQuorum() { + return needToSyncQuorum; + } + + + + public void setLeasePeriod(long leasePeriod) { + this.leasePeriod = leasePeriod; + } + + + public long getLeaseStartTime() { + return leaseStartTime; + } + + + public void setLeaseStartTime(long leaseStartTime) { + this.leaseStartTime = leaseStartTime; + } + + + + public LockStatus getLockStatus() { + return lockStatus; + } + + public void setLockStatus(LockStatus lockStatus) { + this.lockStatus = lockStatus; + } + + public String getLockHolder() { + return lockHolder; + } + + public void setLockHolder(String lockHolder) { + this.lockHolder = lockHolder; + } + + public String getErrorMessage() { + return errorMessage; + } + + public byte[] serialize() { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutput out = null; + try { + out = new ObjectOutputStream(bos); + out.writeObject(this); + } catch (IOException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.IOERROR, ErrorSeverity.ERROR, + ErrorTypes.CONNECTIONERROR, e); + } + return bos.toByteArray(); + } + + public static MusicLockState deSerialize(byte[] data) { + ByteArrayInputStream bis = new ByteArrayInputStream(data); + Object o = null; + ObjectInput in = null; + try { + in = new ObjectInputStream(bis); + o = in.readObject(); + } catch (ClassNotFoundException | IOException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity + .ERROR, ErrorTypes.UNKNOWN, e); + } + return (MusicLockState) o; + } +} diff --git a/music-core/src/main/java/org/onap/music/main/CipherUtil.java b/music-core/src/main/java/org/onap/music/main/CipherUtil.java new file mode 100644 index 00000000..9a8ff69d --- /dev/null +++ b/music-core/src/main/java/org/onap/music/main/CipherUtil.java @@ -0,0 +1,279 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modification Copyright (c) 2019 IBM + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.main; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.UnsupportedEncodingException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Scanner; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang3.ArrayUtils; +import org.onap.music.eelf.logging.EELFLoggerDelegate; + +public class CipherUtil { + + + /** + * Default key. + */ + private static String keyString = MusicUtil.getCipherEncKey(); + + private static final String ALGORITHM = "AES"; + private static final String ALGORYTHM_DETAILS = ALGORITHM + "/CBC/PKCS5PADDING"; + private static final int BLOCK_SIZE = 128; + @SuppressWarnings("unused") + private static SecretKeySpec secretKeySpec; + private static IvParameterSpec ivspec; + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CipherUtil.class); + /** + * @deprecated Please use {@link #encryptPKC(String)} to encrypt the text. + * + * Encrypts the text using the specified secret key. + * + * @param plainText + * Text to encrypt + * @param secretKey + * Key to use for encryption + * @return encrypted version of plain text. + * @ + * if any encryption step fails + * + */ + @Deprecated + public static String encrypt(String plainText, String secretKey) { + String encryptedString = null; + try { + byte[] encryptText = plainText.getBytes("UTF-8"); + byte[] rawKey = Base64.decodeBase64(secretKey); + SecretKeySpec sKeySpec = new SecretKeySpec(rawKey, "AES"); + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.ENCRYPT_MODE, sKeySpec); + encryptedString = Base64.encodeBase64String(cipher.doFinal(encryptText)); + } catch (BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchAlgorithmException + | NoSuchPaddingException | UnsupportedEncodingException ex) { + } + return encryptedString; + } + + /** + * @deprecated Please use {@link #encryptPKC(String)} to encrypt the text. + * Encrypts the text using the secret key in key.properties file. + * + * @param plainText + * Text to encrypt + * @return Encrypted Text + * @ + * if any decryption step fails + */ + @Deprecated + public static String encrypt(String plainText) { + return CipherUtil.encrypt(plainText, keyString); + } + + /** + * Encrypts the text using a secret key. + * + * @param plainText + * Text to encrypt + * @return Encrypted Text + * @ + * if any decryption step fails + */ + public static String encryptPKC(String plainText) { + return CipherUtil.encryptPKC(plainText, keyString); + } + + /** + * + * @deprecated Please use {@link #decryptPKC(String)} to Decryption the text. + * + * Decrypts the text using the specified secret key. + * + * @param encryptedText + * Text to decrypt + * @param secretKey + * Key to use for decryption + * @return plain text version of encrypted text + * @ + * if any decryption step fails + * + */ + @Deprecated + public static String decrypt(String encryptedText, String secretKey) { + String encryptedString = null; + try { + byte[] rawKey = Base64.decodeBase64(secretKey); + SecretKeySpec sKeySpec = new SecretKeySpec(rawKey, "AES"); + byte[] encryptText = Base64.decodeBase64(encryptedText.getBytes("UTF-8")); + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.DECRYPT_MODE, sKeySpec); + encryptedString = new String(cipher.doFinal(encryptText)); + } catch (BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchAlgorithmException + | NoSuchPaddingException | UnsupportedEncodingException ex) { + } + return encryptedString; + } + + private static SecretKeySpec getSecretKeySpec() { + byte[] key = Base64.decodeBase64(keyString); + return new SecretKeySpec(key, ALGORITHM); + } + + private static SecretKeySpec getSecretKeySpec(String keyString) { + byte[] key = Base64.decodeBase64(keyString); + return new SecretKeySpec(key, ALGORITHM); + } + + /** + * Encrypt the text using the secret key in key.properties file + * + * @param value + * @return The encrypted string + * @throws BadPaddingException + * @ + * In case of issue with the encryption + */ + public static String encryptPKC(String value, String skey) { + Cipher cipher = null; + byte[] iv = null; + byte[] finalByte = null; + + try { + cipher = Cipher.getInstance(ALGORYTHM_DETAILS, "SunJCE"); + + SecureRandom r = SecureRandom.getInstance("SHA1PRNG"); + iv = new byte[BLOCK_SIZE / 8]; + r.nextBytes(iv); + ivspec = new IvParameterSpec(iv); + cipher.init(Cipher.ENCRYPT_MODE, getSecretKeySpec(skey), ivspec); + finalByte = cipher.doFinal(value.getBytes()); + + } catch (Exception ex) { + + } + return Base64.encodeBase64String(ArrayUtils.addAll(iv, finalByte)); + } + + /** + * Decrypts the text using the secret key in key.properties file. + * + * @param message + * The encrypted string that must be decrypted using the ecomp + * Encryption Key + * @return The String decrypted + * @ + * if any decryption step fails + */ + public static String decryptPKC(String message, String skey) { + byte[] encryptedMessage = Base64.decodeBase64(message); + Cipher cipher; + byte[] decrypted = null; + try { + cipher = Cipher.getInstance(ALGORYTHM_DETAILS, "SunJCE"); + ivspec = new IvParameterSpec(ArrayUtils.subarray(encryptedMessage, 0, BLOCK_SIZE / 8)); + byte[] realData = ArrayUtils.subarray(encryptedMessage, BLOCK_SIZE / 8, encryptedMessage.length); + cipher.init(Cipher.DECRYPT_MODE, getSecretKeySpec(skey), ivspec); + decrypted = cipher.doFinal(realData); + + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger, "Error in decryptPKC", ex); + + } + + return new String(decrypted); + } + + /** + * @deprecated Please use {@link #decryptPKC(String)} to Decrypt the text. + * + * Decrypts the text using the secret key in key.properties file. + * + * @param encryptedText + * Text to decrypt + * @return Decrypted text + * @ + * if any decryption step fails + */ + @Deprecated + public static String decrypt(String encryptedText) { + return CipherUtil.decrypt(encryptedText, keyString); + } + + /** + * + * Decrypts the text using the secret key in key.properties file. + * + * @param encryptedText + * Text to decrypt + * @return Decrypted text + * @ + * if any decryption step fails + */ + public static String decryptPKC(String encryptedText) { + return CipherUtil.decryptPKC(encryptedText, keyString); + } + + + public static void readAndSetKeyString() { + try (Scanner in = new Scanner(new FileReader("/opt/app/music/etc/properties.txt"))) { + + StringBuilder sb = new StringBuilder(); + while(in.hasNext()) { + sb.append(in.next()); + } + keyString = sb.toString(); + } catch (FileNotFoundException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + } + } + + public static void main(String[] args) { + + if (args.length < 2) { + System.out.println("Usage: java -jar CipherUtil <key> <password>"); + return; + } + + keyString = args[0]; + String password = args[1]; + + String enc = encryptPKC(password); + System.out.println("Encrypted password: " + enc); + + System.out.println("Decrypted password (to verify): " + decryptPKC(enc)); + } + +} diff --git a/music-core/src/main/java/org/onap/music/main/CorePropertiesLoader.java b/music-core/src/main/java/org/onap/music/main/CorePropertiesLoader.java new file mode 100644 index 00000000..2e5ca689 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/main/CorePropertiesLoader.java @@ -0,0 +1,120 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.main; + +import java.util.Properties; + +public class CorePropertiesLoader { + + public static void loadProperties(Properties properties) { + if (properties.getProperty("cassandra.host")!=null) { + MusicUtil.setMyCassaHost(properties.getProperty("cassandra.host")); + } + + if (properties.getProperty("cassandra.port")!=null) { + MusicUtil.setCassandraPort(Integer.parseInt(properties.getProperty("cassandra.port"))); + } + + if (properties.getProperty("cassandra.user")!=null) { + MusicUtil.setCassName(properties.getProperty("cassandra.user")); + } + + if (properties.getProperty("cassandra.password")!=null) { + MusicUtil.setCassPwd(properties.getProperty("cassandra.password")); + } + + if (properties.getProperty("music.properties")!=null) { + MusicUtil.setMusicPropertiesFilePath(properties.getProperty("music.properties")); + } + + if (properties.getProperty("debug")!=null) { + MusicUtil.setDebug(Boolean.parseBoolean(properties.getProperty("debug"))); + } + + if (properties.getProperty("version")!=null) { + MusicUtil.setVersion(properties.getProperty("version")); + } + + if (properties.getProperty("build")!=null) { + MusicUtil.setBuild(properties.getProperty("build")); + } + + if (properties.getProperty("lock.lease.period")!=null) { + MusicUtil.setDefaultLockLeasePeriod(Long.parseLong(properties.getProperty("lock.lease.period"))); + } + + if (properties.getProperty("cadi")!=null) { + MusicUtil.setIsCadi(Boolean.parseBoolean(properties.getProperty("cadi"))); + } + + if (properties.getProperty("keyspace.active")!=null) { + MusicUtil.setKeyspaceActive(Boolean.parseBoolean(properties.getProperty("keyspace.active"))); + } + + if (properties.getProperty("retry.count")!=null) { + MusicUtil.setRetryCount(Integer.parseInt(properties.getProperty("retry.count"))); + } + + if (properties.getProperty("transId.header.prefix")!=null) { + MusicUtil.setTransIdPrefix(properties.getProperty("transId.header.prefix")); + } + + if (properties.getProperty("conversation.header.prefix")!=null) { + MusicUtil.setConversationIdPrefix(properties.getProperty("conversation.header.prefix")); + } + + if (properties.getProperty("clientId.header.prefix")!=null) { + MusicUtil.setClientIdPrefix(properties.getProperty("clientId.header.prefix")); + } + + if (properties.getProperty("messageId.header.prefix")!=null) { + MusicUtil.setMessageIdPrefix(properties.getProperty("messageId.header.prefix")); + } + + if (properties.getProperty("transId.header.required")!=null) { + MusicUtil.setTransIdRequired(Boolean.parseBoolean(properties.getProperty("transId.header.required"))); + } + + if (properties.getProperty("conversation.header.required")!=null) { + MusicUtil.setConversationIdRequired(Boolean.parseBoolean(properties.getProperty("conversation.header.required"))); + } + + if (properties.getProperty("clientId.header.required")!=null) { + MusicUtil.setClientIdRequired(Boolean.parseBoolean(properties.getProperty("clientId.header.required"))); + } + + if (properties.getProperty("messageId.header.required")!=null) { + MusicUtil.setMessageIdRequired(Boolean.parseBoolean(properties.getProperty("messageId.header.required"))); + } + + if (properties.getProperty("music.aaf.ns")!=null) { + MusicUtil.setMusicAafNs(properties.getProperty("music.aaf.ns")); + } + + if (properties.getProperty("cipher.enc.key")!=null) { + MusicUtil.setCipherEncKey(properties.getProperty("cipher.enc.key")); + } + + } + +} diff --git a/music-core/src/main/java/org/onap/music/main/DeadlockDetectionUtil.java b/music-core/src/main/java/org/onap/music/main/DeadlockDetectionUtil.java new file mode 100644 index 00000000..004bd550 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/main/DeadlockDetectionUtil.java @@ -0,0 +1,152 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.main; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class DeadlockDetectionUtil { + private Map<String, Node> nodeList = null; + public enum OwnershipType {NONE, CREATED, ACQUIRED}; + + private class Node implements Comparable<Node> { + private String id; + private List<Node> links; + private boolean visited = false; + private boolean onStack = false; + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + for (Node link : links) + sb.append(link.id); + return "Node [id=" + id + ", links=" + sb.toString() + ", visited=" + visited + ", onStack=" + onStack + "]"; + } + + public Node(String id) { + super(); + this.id = id; + this.links = new ArrayList<>(); + } + + public List<Node> getLinks() { + return links; + } + + public void addLink(Node link) { + this.links.add(link); + } + + public void removeLink(Node link) { + this.links.remove(link); + } + + public boolean isVisited() { + return visited; + } + + public boolean isOnStack() { + return onStack; + } + + public void setVisited(boolean visited) { + this.visited = visited; + } + + public void setOnStack(boolean onStack) { + this.onStack = onStack; + } + + @Override + public int compareTo(Node arg0) { + return id.compareTo(arg0.id); + } + } + + public DeadlockDetectionUtil() { + this.nodeList = new HashMap<>(); + } + + public void listAllNodes() { + System.out.println("In DeadlockDetectionUtil: "); + for (String key : nodeList.keySet()) { + System.out.println(" " + key + " : " + nodeList.get(key)); + } + } + + public boolean checkForDeadlock(String resource, String owner, OwnershipType operation) { + setExisting(resource, owner, operation); + + Node currentNode = null; + if (operation.equals(OwnershipType.ACQUIRED)) { + currentNode = nodeList.get("r" + resource); + } else if (operation.equals(OwnershipType.CREATED)) { + currentNode = nodeList.get("o" + owner); + } + + return findCycle(currentNode); + } + + private boolean findCycle(Node currentNode) { + if (currentNode==null) + return false; + if (currentNode.isOnStack()) + return true; + if (currentNode.isVisited()) + return false; + currentNode.setOnStack(true); + currentNode.setVisited(true); + for (Node childNode : currentNode.getLinks()) { + if (findCycle(childNode)) + return true; + } + currentNode.setOnStack(false); + return false; + } + + public void setExisting(String resource, String owner, OwnershipType operation) { + String resourceKey = "r" + resource; + Node resourceNode = nodeList.get(resourceKey); + if (resourceNode==null) { + resourceNode = new Node(resourceKey); + nodeList.put(resourceKey, resourceNode); + } + + String ownerKey = "o" + owner; + Node ownerNode = nodeList.get(ownerKey); + if (ownerNode==null) { + ownerNode = new Node(ownerKey); + nodeList.put(ownerKey, ownerNode); + } + + if (operation.equals(OwnershipType.ACQUIRED)) { + resourceNode.addLink(ownerNode); + ownerNode.removeLink(resourceNode); + } else if (operation.equals(OwnershipType.CREATED)) { + ownerNode.addLink(resourceNode); + resourceNode.removeLink(ownerNode); + } + } + +} diff --git a/music-core/src/main/java/org/onap/music/main/MusicCore.java b/music-core/src/main/java/org/onap/music/main/MusicCore.java new file mode 100644 index 00000000..30d2bc47 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/main/MusicCore.java @@ -0,0 +1,264 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.main; + +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.MultivaluedMap; + +import org.onap.music.datastore.Condition; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonDelete; +import org.onap.music.datastore.jsonobjects.JsonIndex; +import org.onap.music.datastore.jsonobjects.JsonInsert; +import org.onap.music.datastore.jsonobjects.JsonKeySpace; +import org.onap.music.datastore.jsonobjects.JsonSelect; +import org.onap.music.datastore.jsonobjects.JsonTable; +import org.onap.music.datastore.jsonobjects.JsonUpdate; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.exceptions.MusicLockingException; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.lockingservice.cassandra.CassaLockStore; +import org.onap.music.lockingservice.cassandra.LockType; +import org.onap.music.lockingservice.cassandra.MusicLockState; +import org.onap.music.service.MusicCoreService; + +import com.datastax.driver.core.ResultSet; + +public class MusicCore { + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicCore.class); + private static MusicCoreService musicCore = MusicUtil.getMusicCoreService(); + private static CassaLockStore mLockHandle; + + public static CassaLockStore getmLockHandle() { + return mLockHandle; + } + + public static void setmLockHandle(CassaLockStore mLockHandleIn) { + mLockHandle = mLockHandleIn; + } + + /** + * Acquire lock + * + * @param fullyQualifiedKey DO NOT RELY ON THIS KEY WORKING. INCLUDE THE KEY IN THE LOCKID. + * @param lockId - the full lock id (key + lockRef) + * @return + * @throws MusicLockingException + * @throws MusicQueryException + * @throws MusicServiceException + */ + public static ReturnType acquireLock(String fullyQualifiedKey, String lockId) + throws MusicLockingException, MusicQueryException, MusicServiceException { + return musicCore.acquireLock(fullyQualifiedKey, lockId); + } + + public static ReturnType acquireLockWithLease(String key, String lockId, long leasePeriod) + throws MusicLockingException, MusicQueryException, MusicServiceException { + return musicCore.acquireLockWithLease(key, lockId, leasePeriod); + } + + public static String createLockReferenceAtomic(String fullyQualifiedKey) throws MusicLockingException { + return musicCore.createLockReferenceAtomic(fullyQualifiedKey); + } + + public static String createLockReference(String fullyQualifiedKey, String owner) throws MusicLockingException { + return musicCore.createLockReference(fullyQualifiedKey, owner); + } + + public static String createLockReferenceAtomic(String fullyQualifiedKey, LockType locktype) throws MusicLockingException { + return musicCore.createLockReferenceAtomic(fullyQualifiedKey, locktype); + } + + public static String createLockReference(String fullyQualifiedKey, LockType locktype, String owner) throws MusicLockingException { + return musicCore.createLockReference(fullyQualifiedKey, locktype, owner); + } + + public static ResultType createTable(String keyspace, String table, PreparedQueryObject tableQueryObject, + String consistency) throws MusicServiceException { + return musicCore.createTable(keyspace, table, tableQueryObject, consistency); + } + + public static ResultSet quorumGet(PreparedQueryObject query) { + return musicCore.quorumGet(query); + } + + /** + * Gets the top of queue for fullyQualifiedKey + * + * @param fullyQualifiedKey + * @return + */ + public static String whoseTurnIsIt(String fullyQualifiedKey) { + return musicCore.whoseTurnIsIt(fullyQualifiedKey); + } + + /** + * Gets the current lockholder(s) for fullyQualifiedKey + * + * @param fullyQualifiedKey + * @return + */ + public static List<String> getCurrentLockHolders(String fullyQualifiedKey) { + return musicCore.getCurrentLockHolders(fullyQualifiedKey); + } + + public static ReturnType promoteLock(String lockIdToPromote) throws MusicLockingException { + return musicCore.promoteLock(lockIdToPromote); + } + + public static void destroyLockRef(String lockId) throws MusicLockingException { + musicCore.destroyLockRef(lockId); + } + + public static ReturnType eventualPut(PreparedQueryObject queryObject) { + return musicCore.eventualPut(queryObject); + } + + public static ReturnType eventualPut_nb(PreparedQueryObject queryObject, String keyspace, String tablename, + String primaryKey) { + return musicCore.eventualPut_nb(queryObject, keyspace, tablename, primaryKey); + } + + public static ReturnType criticalPut(String keyspace, String table, String primaryKeyValue, + PreparedQueryObject queryObject, String lockReference, Condition conditionInfo) { + return musicCore.criticalPut(keyspace, table, primaryKeyValue, queryObject, lockReference, conditionInfo); + } + + public static ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) + throws MusicServiceException,MusicQueryException { + return musicCore.nonKeyRelatedPut(queryObject, consistency); + } + + public static ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException { + return musicCore.get(queryObject); + } + + public static ResultSet criticalGet(String keyspace, String table, String primaryKeyValue, + PreparedQueryObject queryObject, String lockReference) throws MusicServiceException { + return musicCore.criticalGet(keyspace, table, primaryKeyValue, queryObject, lockReference); + } + + public static ReturnType atomicPut(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject, Condition conditionInfo) + throws MusicLockingException, MusicQueryException, MusicServiceException { + return musicCore.atomicPut(keyspaceName, tableName, primaryKey, queryObject, conditionInfo); + } + + public static ResultSet atomicGet(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException, MusicQueryException { + return musicCore.atomicGet(keyspaceName, tableName, primaryKey, queryObject); + } + + public static List<String> getLockQueue(String fullyQualifiedKey) + throws MusicServiceException, MusicQueryException, MusicLockingException { + return musicCore.getLockQueue(fullyQualifiedKey); + } + + public static long getLockQueueSize(String fullyQualifiedKey) + throws MusicServiceException, MusicQueryException, MusicLockingException { + return musicCore.getLockQueueSize(fullyQualifiedKey); + } + + public static void deleteLock(String lockName) throws MusicLockingException { + musicCore.deleteLock(lockName); + } + + public static ReturnType atomicPutWithDeleteLock(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException { + return musicCore.atomicPutWithDeleteLock(keyspaceName, tableName, primaryKey, queryObject, conditionInfo); + } + + public static ResultSet atomicGetWithDeleteLock(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException { + return musicCore.atomicGetWithDeleteLock(keyspaceName, tableName, primaryKey, queryObject); + } + + public static Map<String, Object> validateLock(String lockName) { + return musicCore.validateLock(lockName); + } + + public static MusicLockState releaseLock(String lockId, boolean voluntaryRelease) throws MusicLockingException { + return musicCore.releaseLock(lockId, voluntaryRelease); + } + + public static List<String> releaseAllLocksForOwner(String ownerId, String keyspace, String table) throws MusicLockingException, MusicServiceException, MusicQueryException { + return musicCore.releaseAllLocksForOwner(ownerId, keyspace, table); + } + + //Added changes for orm implementation. + + public static ResultType createKeyspace(JsonKeySpace jsonKeySpaceObject, String consistencyInfo) + throws MusicServiceException, MusicQueryException { + return musicCore.createKeyspace(jsonKeySpaceObject,consistencyInfo); + } + + public static ResultType dropKeyspace(JsonKeySpace josnKeyspaceObject, String consistencyInfo) + throws MusicServiceException,MusicQueryException { + return musicCore.dropKeyspace(josnKeyspaceObject, consistencyInfo); + } + + public static ResultType createTable(JsonTable jsonTableObject,String consistencyInfo) + throws MusicServiceException,MusicQueryException { + return musicCore.createTable(jsonTableObject, consistencyInfo); + } + + public static ResultType dropTable(JsonTable jsonTableObject, String consistencyInfo) + throws MusicServiceException, MusicQueryException { + return musicCore.dropTable(jsonTableObject, consistencyInfo); + } + + public static ResultType createIndex(JsonIndex jsonIndexObject, String consistencyInfo) + throws MusicServiceException,MusicQueryException { + return musicCore.createIndex(jsonIndexObject, consistencyInfo); + } + + public static ResultSet select(JsonSelect jsonSelect, MultivaluedMap<String, String> rowParams) + throws MusicServiceException, MusicQueryException{ + return musicCore.select(jsonSelect, rowParams); + } + + public static ResultSet selectCritical(JsonInsert jsonInsertObj, MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException{ + return musicCore.selectCritical(jsonInsertObj, rowParams); + } + + + public static ReturnType insertIntoTable(JsonInsert jsonInsert) throws MusicLockingException, MusicQueryException, MusicServiceException{ + return musicCore.insertIntoTable(jsonInsert); + } + + public static ReturnType updateTable(JsonUpdate jsonUpdateObj,MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException{ + return musicCore.updateTable(jsonUpdateObj, rowParams); + } + + public static ReturnType deleteFromTable(JsonDelete jsonDeleteObj,MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException{ + return musicCore.deleteFromTable(jsonDeleteObj,rowParams); + } + +} diff --git a/music-core/src/main/java/org/onap/music/main/MusicUtil.java b/music-core/src/main/java/org/onap/music/main/MusicUtil.java new file mode 100644 index 00000000..4b8b1059 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/main/MusicUtil.java @@ -0,0 +1,881 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (c) 2019 IBM. + * Modifications Copyright (c) 2019 Samsung. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.main; + +import com.datastax.driver.core.ColumnDefinitions; +import com.datastax.driver.core.ColumnDefinitions.Definition; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import java.io.File; +import java.io.FileNotFoundException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Scanner; +import java.util.Set; +import java.util.UUID; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import org.onap.music.datastore.MusicDataStoreHandle; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.service.MusicCoreService; +import org.onap.music.service.impl.MusicCassaCore; + +import com.datastax.driver.core.ConsistencyLevel; +import com.datastax.driver.core.DataType; + +/** + * @author nelson24 + * + * Properties This will take Properties and load them into MusicUtil. + * This is a hack for now. Eventually it would bebest to do this in + * another way. + * + */ +public class MusicUtil { + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicUtil.class); + + // Consistancy Constants + public static final String ATOMIC = "atomic"; + public static final String EVENTUAL = "eventual"; + public static final String CRITICAL = "critical"; + public static final String EVENTUAL_NB = "eventual_nb"; + public static final String ALL = "all"; + public static final String QUORUM = "quorum"; + public static final String LOCAL_QUORUM = "local_quorum"; + public static final String ONE = "one"; + public static final String ATOMICDELETELOCK = "atomic_delete_lock"; + + // Header Constants + private static final String XLATESTVERSION = "X-latestVersion"; + private static final String XMINORVERSION = "X-minorVersion"; + private static final String XPATCHVERSION = "X-patchVersion"; + public static final String AUTHORIZATION = "Authorization"; + + // CQL Constants + public static final String SELECT = "select"; + public static final String INSERT = "insert"; + public static final String UPDATE = "update"; + public static final String UPSERT = "upsert"; + public static final String USERID = "userId"; + public static final String PASSWORD = ""; + public static final String CASSANDRA = "cassandra"; + + private static final String LOCALHOST = "localhost"; + private static final String PROPERTIES_FILE = "/opt/app/music/etc/music.properties"; + public static final String DEFAULTKEYSPACENAME = "TBD"; + + private static long defaultLockLeasePeriod = 6000; + // Amount of times to retry to delete a lock in atomic. + private static int retryCount = 3; + private static String lockUsing = MusicUtil.CASSANDRA; + // Cadi OnOff + private static boolean isCadi = false; + // Keyspace Creation on/off + private static boolean isKeyspaceActive = false; + private static boolean debug = true; + private static String version = "0.0.0"; + private static String build = ""; + private static long lockDaemonSleepms = 1000; + private static Set<String> keyspacesToCleanLocks = new HashSet<>(); + + private static String musicPropertiesFilePath = PROPERTIES_FILE; + // private static final String[] propKeys = new String[] { MusicUtil.class.getDeclaredMethod(arg0, )"build","cassandra.host", "debug", + // "version", "music.properties", "lock.lease.period", "cassandra.user", + // "cassandra.password", "aaf.endpoint.url","admin.username","admin.password", + // "music.namespace","admin.aaf.role","cassandra.port","lock.using","retry.count", + // "transId.header.required","conversation.header.required","clientId.header.required", + // "messageId.header.required","transId.header.prefix","conversation.header.prefix", + // "clientId.header.prefix","messageId.header.prefix"}; + // Consistency Constants and variables. + private static final String[] cosistencyLevel = new String[] { + "ALL","EACH_QUORUM","QUORUM","LOCAL_QUORUM","ONE","TWO", + "THREE","LOCAL_ONE","ANY","SERIAL","LOCAL_SERIAL"}; + private static final Map<String,ConsistencyLevel> consistencyName = new HashMap<>(); + static { + consistencyName.put("ONE",ConsistencyLevel.ONE); + consistencyName.put("TWO",ConsistencyLevel.TWO); + consistencyName.put("THREE",ConsistencyLevel.THREE); + consistencyName.put("SERIAL",ConsistencyLevel.SERIAL); + consistencyName.put("ALL",ConsistencyLevel.ALL); + consistencyName.put("EACH_QUORUM",ConsistencyLevel.EACH_QUORUM); + consistencyName.put("QUORUM",ConsistencyLevel.QUORUM); + consistencyName.put("LOCAL_QUORUM",ConsistencyLevel.LOCAL_QUORUM); + consistencyName.put("LOCAL_ONE",ConsistencyLevel.LOCAL_ONE); + consistencyName.put("LOCAL_SERIAL",ConsistencyLevel.LOCAL_SERIAL); + } + + // Cassandra Values + private static String cassName = "cassandra"; + private static String cassPwd; + private static String myCassaHost = LOCALHOST; + private static int cassandraPort = 9042; + private static int cassandraConnectTimeOutMS; + private static int cassandraReadTimeOutMS; + + // AAF + private static String musicAafNs = "org.onap.music.cadi"; + + // Locking + public static final long MusicEternityEpochMillis = 1533081600000L; // Wednesday, August 1, 2018 12:00:00 AM + public static final long MaxLockReferenceTimePart = 1000000000000L; // millis after eternity (eq sometime in 2050) + public static final long MaxCriticalSectionDurationMillis = 1L * 24 * 60 * 60 * 1000; // 1 day + + // Response/Request tracking headers + private static String transIdPrefix = "false"; + private static String conversationIdPrefix = "false"; + private static String clientIdPrefix = "false"; + private static String messageIdPrefix = "false"; + private static Boolean transIdRequired = false; + private static Boolean conversationIdRequired = false; + private static Boolean clientIdRequired = false; + private static Boolean messageIdRequired = false; + private static String cipherEncKey = ""; + + private static long createLockWaitPeriod = 300; + private static int createLockWaitIncrement = 50; + + public static long getCreateLockWaitPeriod() { + return createLockWaitPeriod; + } + + public static void setCreateLockWaitPeriod(long createLockWaitPeriod) { + MusicUtil.createLockWaitPeriod = createLockWaitPeriod; + } + + public static int getCreateLockWaitIncrement() { + return createLockWaitIncrement; + } + + public static void setCreateLockWaitIncrement(int createLockWaitIncrement) { + MusicUtil.createLockWaitIncrement = createLockWaitIncrement; + } + + public MusicUtil() { + throw new IllegalStateException("Utility Class"); + } + + public static String getLockUsing() { + return lockUsing; + } + + public static void setLockUsing(String lockUsing) { + MusicUtil.lockUsing = lockUsing; + } + + /** + * + * @return cassandra port + */ + public static int getCassandraPort() { + return cassandraPort; + } + + /** + * set cassandra port + * @param cassandraPort + */ + public static void setCassandraPort(int cassandraPort) { + MusicUtil.cassandraPort = cassandraPort; + } + /** + * @return the cassName + */ + public static String getCassName() { + return cassName; + } + + /** + * @return the cassPwd + */ + public static String getCassPwd() { + return cassPwd; + } + + public static int getCassandraConnectTimeOutMS() { + return cassandraConnectTimeOutMS; + } + + public static void setCassandraConnectTimeOutMS(int cassandraConnectTimeOutMS) { + MusicUtil.cassandraConnectTimeOutMS = cassandraConnectTimeOutMS; + } + + public static int getCassandraReadTimeOutMS() { + return cassandraReadTimeOutMS; + } + + public static void setCassandraReadTimeOutMS(int cassandraReadTimeOutMS) { + MusicUtil.cassandraReadTimeOutMS = cassandraReadTimeOutMS; + } + + /** + * Returns An array of property names that should be in the Properties + * files. + * +// * @return +// */ + // public static String[] getPropkeys() { + // return propKeys.clone(); + // } + + /** + * Get MusicPropertiesFilePath - Default = /opt/music/music.properties + * property file value - music.properties + * + * @return + */ + public static String getMusicPropertiesFilePath() { + return musicPropertiesFilePath; + } + + /** + * Set MusicPropertiesFilePath + * + * @param musicPropertiesFilePath + */ + public static void setMusicPropertiesFilePath(String musicPropertiesFilePath) { + MusicUtil.musicPropertiesFilePath = musicPropertiesFilePath; + } + + /** + * Get DefaultLockLeasePeriod - Default = 6000 property file value - + * lock.lease.period + * + * @return + */ + public static long getDefaultLockLeasePeriod() { + return defaultLockLeasePeriod; + } + + /** + * Set DefaultLockLeasePeriod + * + * @param defaultLockLeasePeriod + */ + public static void setDefaultLockLeasePeriod(long defaultLockLeasePeriod) { + MusicUtil.defaultLockLeasePeriod = defaultLockLeasePeriod; + } + + /** + * Set Debug + * + * @param debug + */ + public static void setDebug(boolean debug) { + MusicUtil.debug = debug; + } + + /** + * Is Debug - Default = true property file value - debug + * + * @return + */ + public static boolean isDebug() { + return debug; + } + + /** + * Set Version + * + * @param version + */ + public static void setVersion(String version) { + MusicUtil.version = version; + } + + /** + * Return the version property file value - version. + * + * @return + */ + public static String getVersion() { + return version; + } + + /** + * Set the build of project which is a combination of the + * version and the date. + * + * @param build - version-date. + */ + public static void setBuild(String build) { + MusicUtil.build = build; + } + + /** + * Return the build version-date. + */ + public static String getBuild() { + return build; + } + + /** + * Get MyCassHost - Cassandra Hostname - Default = localhost property file + * value - cassandra.host + * + * @return + */ + public static String getMyCassaHost() { + return myCassaHost; + } + + /** + * Set MyCassHost - Cassandra Hostname + * + * @param myCassaHost . + */ + public static void setMyCassaHost(String myCassaHost) { + MusicUtil.myCassaHost = myCassaHost; + } + + /** + * Gey default retry count + * @return + */ + public static int getRetryCount() { + return retryCount; + } + + /** + * Set retry count + * @param retryCount . + */ + public static void setRetryCount(int retryCount) { + MusicUtil.retryCount = retryCount; + } + + + /** + * This is used to turn keyspace creation api on/off. + * + */ + public static void setKeyspaceActive(Boolean keyspaceActive) { + MusicUtil.isKeyspaceActive = keyspaceActive; + } + + /** + * This is used to turn keyspace creation api on/off. + * @return boolean isKeyspaceActive + */ + public static boolean isKeyspaceActive() { + return isKeyspaceActive; + } + + /** + * This method depricated as its not used or needed. + * + * @return String + */ + @Deprecated + public static String getTestType() { + String testType = ""; + try { + Scanner fileScanner = new Scanner(new File("")); + testType = fileScanner.next();// ignore the my id line + @SuppressWarnings("unused") + String batchSize = fileScanner.next();// ignore the my public ip line + fileScanner.close(); + } catch (FileNotFoundException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), e); + } + return testType; + + } + + /** + * Method to do a Thread Sleep. + * Used for adding a delay. + * + * @param time + */ + public static void sleep(long time) { + try { + Thread.sleep(time); + } catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), e); + Thread.currentThread().interrupt(); + } + } + + /** + * Utility function to check if the query object is valid. + * + * @param withparams + * @param queryObject + * @return + */ + public static boolean isValidQueryObject(boolean withparams, PreparedQueryObject queryObject) { + if (withparams) { + int noOfValues = queryObject.getValues().size(); + int noOfParams = 0; + char[] temp = queryObject.getQuery().toCharArray(); + for (int i = 0; i < temp.length; i++) { + if (temp[i] == '?') + noOfParams++; + } + return (noOfValues == noOfParams); + } else { + return !queryObject.getQuery().isEmpty(); + } + + } + + public static void setCassName(String cassName) { + MusicUtil.cassName = cassName; + } + + public static void setCassPwd(String cassPwd) { + MusicUtil.cassPwd = cassPwd; + } + + @SuppressWarnings("unchecked") + public static String convertToCQLDataType(DataType type, Object valueObj) throws Exception { + + String value = ""; + switch (type.getName()) { + case UUID: + value = valueObj + ""; + break; + case TEXT: + case VARCHAR: + String valueString = valueObj + ""; + valueString = valueString.replace("'", "''"); + value = "'" + valueString + "'"; + break; + case MAP: { + Map<String, Object> otMap = (Map<String, Object>) valueObj; + value = "{" + jsonMaptoSqlString(otMap, ",") + "}"; + break; + } + default: + value = valueObj + ""; + break; + } + return value; + } + + /** + * + * @param colType + * @param valueObj + * @return + * @throws MusicTypeConversionException + * @throws Exception + */ + @SuppressWarnings("unchecked") + public static Object convertToActualDataType(DataType colType, Object valueObj) throws Exception { + String valueObjString = valueObj + ""; + switch (colType.getName()) { + case UUID: + return UUID.fromString(valueObjString); + case VARINT: + return BigInteger.valueOf(Long.parseLong(valueObjString)); + case BIGINT: + return Long.parseLong(valueObjString); + case INT: + return Integer.parseInt(valueObjString); + case FLOAT: + return Float.parseFloat(valueObjString); + case DOUBLE: + return Double.parseDouble(valueObjString); + case BOOLEAN: + return Boolean.parseBoolean(valueObjString); + case MAP: + return (Map<String, Object>) valueObj; + case LIST: + return valueObj; + case BLOB: + + default: + return valueObjString; + } + } + + public static ByteBuffer convertToActualDataType(DataType colType, byte[] valueObj) { + + return ByteBuffer.wrap(valueObj); + } + + /** + * + * Utility function to parse json map into sql like string + * + * @param jMap + * @param lineDelimiter + * @return + */ + + public static String jsonMaptoSqlString(Map<String, Object> jMap, String lineDelimiter) throws Exception{ + StringBuilder sqlString = new StringBuilder(); + int counter = 0; + for (Map.Entry<String, Object> entry : jMap.entrySet()) { + Object ot = entry.getValue(); + String value = ot + ""; + if (ot instanceof String) { + value = "'" + value.replace("'", "''") + "'"; + } + sqlString.append("'" + entry.getKey() + "':" + value); + if (counter != jMap.size() - 1) + sqlString.append(lineDelimiter); + counter = counter + 1; + } + return sqlString.toString(); + } + + @SuppressWarnings("unused") + public static String buildVersion(String major, String minor, String patch) { + if (minor != null) { + major += "." + minor; + if (patch != null) { + major += "." + patch; + } + } + return major; + } + + /** + * Currently this will build a header with X-latestVersion, X-minorVersion and X-pathcVersion + * X-latestVerstion will be equal to the latest full version. + * X-minorVersion - will be equal to the latest minor version. + * X-pathVersion - will be equal to the latest patch version. + * Future plans will change this. + * @param response + * @param major + * @param minor + * @param patch + * @return + */ + public static ResponseBuilder buildVersionResponse(String major, String minor, String patch) { + ResponseBuilder response = Response.noContent(); + String versionIn = buildVersion(major,minor,patch); + String version = MusicUtil.getVersion(); + String[] verArray = version.split("\\.",3); + if ( minor != null ) { + response.header(XMINORVERSION,minor); + } else { + response.header(XMINORVERSION,verArray[1]); + } + if ( patch != null ) { + response.header(XPATCHVERSION,patch); + } else { + response.header(XPATCHVERSION,verArray[2]); + } + response.header(XLATESTVERSION,version); + logger.info(EELFLoggerDelegate.auditLogger,"Version In:" + versionIn); + return response; + } + + public static boolean isValidConsistency(String consistency) { + for (String string : cosistencyLevel) { + if (string.equalsIgnoreCase(consistency)) + return true; + } + return false; + + } + + public static ConsistencyLevel getConsistencyLevel(String consistency) { + return consistencyName.get(consistency.toUpperCase()); + } + + /** + * Given the time of write for an update in a critical section, this method provides a transformed timestamp + * that ensures that a previous lock holder who is still alive can never corrupt a later critical section. + * The main idea is to us the lock reference to clearly demarcate the timestamps across critical sections. + * @param the UUID lock reference associated with the write. + * @param the long timeOfWrite which is the actual time at which the write took place + * @throws MusicServiceException + * @throws MusicQueryException + */ + public static long v2sTimeStampInMicroseconds(long ordinal, long timeOfWrite) throws MusicServiceException, MusicQueryException{ + // TODO: use acquire time instead of music eternity epoch + return ordinal * MaxLockReferenceTimePart + (timeOfWrite - MusicEternityEpochMillis); + } + + public static MusicCoreService getMusicCoreService() { + if(getLockUsing().equals(MusicUtil.CASSANDRA)) + return MusicCassaCore.getInstance(); + else + return MusicCassaCore.getInstance(); + } + + /** + * @param lockName + * @return + */ + public static Map<String, Object> validateLock(String lockName) { + Map<String, Object> resultMap = new HashMap<>(); + String[] locks = lockName.split("\\."); + if(locks.length < 3) { + resultMap.put("Error", "Invalid lock. Please make sure lock is of the type keyspaceName.tableName.primaryKey"); + return resultMap; + } + String keyspace= locks[0]; + if(keyspace.startsWith("$")) + keyspace = keyspace.substring(1); + resultMap.put("keyspace",keyspace); + return resultMap; + } + + + public static void setIsCadi(boolean isCadi) { + MusicUtil.isCadi = isCadi; + } + + public static void writeBackToQuorum(PreparedQueryObject selectQuery, String primaryKeyName, + PreparedQueryObject updateQuery, String keyspace, String table, + Object cqlFormattedPrimaryKeyValue) + throws Exception { + try { + ResultSet results = MusicDataStoreHandle.getDSHandle().executeQuorumConsistencyGet(selectQuery); + // write it back to a quorum + Row row = results.one(); + ColumnDefinitions colInfo = row.getColumnDefinitions(); + int totalColumns = colInfo.size(); + int counter = 1; + StringBuilder fieldValueString = new StringBuilder(""); + for (Definition definition : colInfo) { + String colName = definition.getName(); + if (colName.equals(primaryKeyName)) + continue; + DataType colType = definition.getType(); + Object valueObj = MusicDataStoreHandle.getDSHandle().getColValue(row, colName, colType); + Object valueString = MusicUtil.convertToActualDataType(colType, valueObj); + fieldValueString.append(colName + " = ?"); + updateQuery.addValue(valueString); + if (counter != (totalColumns - 1)) + fieldValueString.append(","); + counter = counter + 1; + } + updateQuery.appendQueryString("UPDATE " + keyspace + "." + table + " SET " + + fieldValueString + " WHERE " + primaryKeyName + "= ? " + ";"); + updateQuery.addValue(cqlFormattedPrimaryKeyValue); + + MusicDataStoreHandle.getDSHandle().executePut(updateQuery, "critical"); + } catch (MusicServiceException | MusicQueryException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.QUERYERROR +""+updateQuery , + ErrorSeverity.MAJOR, ErrorTypes.QUERYERROR, e); + } + } + + public static boolean getIsCadi() { + return MusicUtil.isCadi; + } + + + /** + * @return a random uuid + */ + public static String generateUUID() { + String uuid = UUID.randomUUID().toString(); + logger.info(EELFLoggerDelegate.applicationLogger,"New AID generated: "+uuid); + return uuid; + } + + private static String checkPrefix(String prefix){ + if (prefix == null || "".equals(prefix) || prefix.endsWith("-")) { + return prefix; + } else { + return prefix + "-"; + } + } + + /** + * @return the transIdPrefix + */ + public static String getTransIdPrefix() { + return transIdPrefix; + } + + /** + * @param transIdPrefix the transIdPrefix to set + */ + public static void setTransIdPrefix(String transIdPrefix) { + MusicUtil.transIdPrefix = checkPrefix(transIdPrefix); + } + + /** + * @return the conversationIdPrefix + */ + public static String getConversationIdPrefix() { + return conversationIdPrefix; + } + + /** + * @param conversationIdPrefix the conversationIdPrefix to set + */ + public static void setConversationIdPrefix(String conversationIdPrefix) { + MusicUtil.conversationIdPrefix = checkPrefix(conversationIdPrefix); + } + + /** + * @return the clientIdPrefix + */ + public static String getClientIdPrefix() { + return clientIdPrefix; + } + + /** + * @param clientIdPrefix the clientIdPrefix to set + */ + public static void setClientIdPrefix(String clientIdPrefix) { + MusicUtil.clientIdPrefix = checkPrefix(clientIdPrefix); + } + + /** + * @return the messageIdPrefix + */ + public static String getMessageIdPrefix() { + return messageIdPrefix; + } + + /** + * @param messageIdPrefix the messageIdPrefix to set + */ + public static void setMessageIdPrefix(String messageIdPrefix) { + MusicUtil.messageIdPrefix = checkPrefix(messageIdPrefix); + } + + /** + * @return the transIdRequired + */ + public static Boolean getTransIdRequired() { + return transIdRequired; + } + + + /** + * @param transIdRequired the transIdRequired to set + */ + public static void setTransIdRequired(Boolean transIdRequired) { + MusicUtil.transIdRequired = transIdRequired; + } + + + /** + * @return the conversationIdRequired + */ + public static Boolean getConversationIdRequired() { + return conversationIdRequired; + } + + + /** + * @param conversationIdRequired the conversationIdRequired to set + */ + public static void setConversationIdRequired(Boolean conversationIdRequired) { + MusicUtil.conversationIdRequired = conversationIdRequired; + } + + + /** + * @return the clientIdRequired + */ + public static Boolean getClientIdRequired() { + return clientIdRequired; + } + + + /** + * @param clientIdRequired the clientIdRequired to set + */ + public static void setClientIdRequired(Boolean clientIdRequired) { + MusicUtil.clientIdRequired = clientIdRequired; + } + + + /** + * @return the messageIdRequired + */ + public static Boolean getMessageIdRequired() { + return messageIdRequired; + } + + /** + * @param messageIdRequired the messageIdRequired to set + */ + public static void setMessageIdRequired(Boolean messageIdRequired) { + MusicUtil.messageIdRequired = messageIdRequired; + } + + /** + * @return the sleep time, in milliseconds, for the lock cleanup daemon + */ + public static long getLockDaemonSleepTimeMs() { + return lockDaemonSleepms; + } + + /** + * set the sleep time, in milliseconds, for the lock cleanup daemon + */ + public static void setLockDaemonSleepTimeMs(long timeoutms) { + MusicUtil.lockDaemonSleepms = timeoutms; + } + + public static Set<String> getKeyspacesToCleanLocks() { + return keyspacesToCleanLocks; + } + + public static void setKeyspacesToCleanLocks(Set<String> keyspaces) { + MusicUtil.keyspacesToCleanLocks = keyspaces; + } + + public static String getCipherEncKey() { + return MusicUtil.cipherEncKey; + } + + + public static void setCipherEncKey(String cipherEncKey) { + MusicUtil.cipherEncKey = cipherEncKey; + if ( null == cipherEncKey || cipherEncKey.equals("") || + cipherEncKey.equals("nothing to see here")) { + logger.error(EELFLoggerDelegate.errorLogger, "Missing Cipher Encryption Key."); + } + } + + public static String getMusicAafNs() { + return MusicUtil.musicAafNs; + } + + + public static void setMusicAafNs(String musicAafNs) { + MusicUtil.musicAafNs = musicAafNs; + } + + + +} + diff --git a/music-core/src/main/java/org/onap/music/main/ResultType.java b/music-core/src/main/java/org/onap/music/main/ResultType.java new file mode 100644 index 00000000..f5ef2070 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/main/ResultType.java @@ -0,0 +1,42 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.main; + +public enum ResultType { + SUCCESS("Success"), FAILURE("Failure"), + SYNTAXERROR("SyntaxError"), EXCEPTION("Exception"), + BODYMISSING("Incomplete Request body. Please correct your input request and retry."); + + private String result; + + ResultType(String result) { + this.result = result; + } + + public String getResult() { + return result; + } + +} + + diff --git a/music-core/src/main/java/org/onap/music/main/ReturnType.java b/music-core/src/main/java/org/onap/music/main/ReturnType.java new file mode 100644 index 00000000..f02dabbf --- /dev/null +++ b/music-core/src/main/java/org/onap/music/main/ReturnType.java @@ -0,0 +1,75 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.main; + +import java.util.HashMap; +import java.util.Map; + +public class ReturnType { + private ResultType result; + private String message; + + private String timingInfo; + + public ReturnType(ResultType result, String message) { + super(); + this.result = result; + this.message = message; + } + + public String getTimingInfo() { + return timingInfo; + } + + public void setTimingInfo(String timingInfo) { + this.timingInfo = timingInfo; + } + + public ResultType getResult() { + return result; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String toJson() { + return "{ \"result\":\"" + result.getResult() + "\", \"message\":\"" + message + "\"}"; + } + + public String toString() { + return result + " | " + message; + } + + public Map<String, Object> toMap() { + Map<String, Object> newMap = new HashMap<>(); + newMap.put("result", result.getResult()); + newMap.put("message", message); + return newMap; + } + +} diff --git a/music-core/src/main/java/org/onap/music/service/MusicCoreService.java b/music-core/src/main/java/org/onap/music/service/MusicCoreService.java new file mode 100644 index 00000000..753d9b28 --- /dev/null +++ b/music-core/src/main/java/org/onap/music/service/MusicCoreService.java @@ -0,0 +1,189 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.service; + +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.MultivaluedMap; + +import org.onap.music.datastore.Condition; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonDelete; +import org.onap.music.datastore.jsonobjects.JsonIndex; +import org.onap.music.datastore.jsonobjects.JsonInsert; +import org.onap.music.datastore.jsonobjects.JsonKeySpace; +import org.onap.music.datastore.jsonobjects.JsonSelect; +import org.onap.music.datastore.jsonobjects.JsonTable; +import org.onap.music.datastore.jsonobjects.JsonUpdate; +import org.onap.music.exceptions.MusicLockingException; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.lockingservice.cassandra.LockType; +import org.onap.music.lockingservice.cassandra.MusicLockState; +import org.onap.music.main.ResultType; +import org.onap.music.main.ReturnType; + +import com.datastax.driver.core.ResultSet; + +public interface MusicCoreService { + + + // Core Music Database Methods + + + public ReturnType eventualPut(PreparedQueryObject queryObject); + + public ReturnType eventualPut_nb(PreparedQueryObject queryObject,String keyspace,String tablename,String primaryKey); + + public ReturnType criticalPut(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject, String lockId, Condition conditionInfo); + + public ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) + throws MusicServiceException,MusicQueryException; + + public ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException; + + public ResultSet atomicGet(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException, MusicQueryException; + + public ReturnType atomicPutWithDeleteLock(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException; + + public ResultSet atomicGetWithDeleteLock(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException; + + public ReturnType atomicPut(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject, Condition conditionInfo) + throws MusicLockingException, MusicQueryException, MusicServiceException; + + public ResultSet criticalGet(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject, String lockId) throws MusicServiceException; + + // Core Music Locking Service Methods + + /** + * Create a lock ref in the music lock store. + * Default is write as this is the safest semantically + * + * @param fullyQualifiedKey the key to create a lock on + * @see {@link #creatLockReference(String, LockType)} + */ + public String createLockReferenceAtomic(String fullyQualifiedKey) throws MusicLockingException; // lock name + + /** + * Create a lock ref in the music lock store + * @param fullyQualifiedKey the key to create a lock on + * @param owner the owner of the lock, for deadlock prevention + */ + public String createLockReference(String fullyQualifiedKey, String owner) throws MusicLockingException; + + /** + * Create a lock ref in the music lock store + * @param fullyQualifiedKey the key to create a lock on + * @param locktype the type of lock create, see {@link LockType} + */ + public String createLockReferenceAtomic(String fullyQualifiedKey, LockType locktype) throws MusicLockingException; + + /** + * Create a lock ref in the music lock store + * @param fullyQualifiedKey the key to create a lock on + * @param locktype the type of lock create, see {@link LockType} + * @param owner the owner of the lock, for deadlock prevention + */ + public String createLockReference(String fullyQualifiedKey, LockType locktype, String owner) throws MusicLockingException; + + public ReturnType acquireLockWithLease(String key, String lockReference, long leasePeriod) + throws MusicLockingException, MusicQueryException, MusicServiceException; // key,lock id,time + + public ReturnType acquireLock(String key, String lockReference) + throws MusicLockingException, MusicQueryException, MusicServiceException; // key,lock id + + public ResultType createTable(String keyspace, String table, PreparedQueryObject tableQueryObject, + String consistency) throws MusicServiceException; + + public ResultSet quorumGet(PreparedQueryObject query); + + /** + * Gets top of queue for fullyQualifiedKey + * @param fullyQualifiedKey + * @return + */ + public String whoseTurnIsIt(String fullyQualifiedKey);// lock name + + /** + * Gets the current lockholder(s) for lockName + * @param lockName + * @return + */ + public List<String> getCurrentLockHolders(String fullyQualifiedKey); + + public void destroyLockRef(String lockId) throws MusicLockingException; + + public void deleteLock(String lockName) throws MusicLockingException; + + public ReturnType promoteLock(String lockIdToPromote) throws MusicLockingException; + + public List<String> getLockQueue(String fullyQualifiedKey) + throws MusicServiceException, MusicQueryException, MusicLockingException; + + public long getLockQueueSize(String fullyQualifiedKey) + throws MusicServiceException, MusicQueryException, MusicLockingException; + + public Map<String, Object> validateLock(String lockName); + + public MusicLockState releaseLock(String lockId, boolean voluntaryRelease) throws MusicLockingException; + + public List<String> releaseAllLocksForOwner(String ownerId, String keyspace, String table) throws MusicLockingException, MusicServiceException, MusicQueryException; + + + //Methods added for orm + + + public ResultType createTable(JsonTable jsonTableObject, String consistencyInfo) throws MusicServiceException,MusicQueryException; + + public ResultType dropTable(JsonTable jsonTableObject, String consistencyInfo) + throws MusicServiceException,MusicQueryException; + + public ResultType createKeyspace(JsonKeySpace jsonKeySpaceObject,String consistencyInfo) throws MusicServiceException,MusicQueryException; + + public ResultType dropKeyspace(JsonKeySpace jsonKeySpaceObject, String consistencyInfo) + throws MusicServiceException,MusicQueryException; + + public ResultType createIndex(JsonIndex jsonIndexObject, String consistencyInfo) throws MusicServiceException,MusicQueryException; + + public ResultSet select(JsonSelect jsonSelect, MultivaluedMap<String, String> rowParams) throws MusicServiceException, MusicQueryException; + + public ResultSet selectCritical(JsonInsert jsonInsertObj, MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException; + + public ReturnType insertIntoTable(JsonInsert jsonInsert) throws MusicLockingException, MusicQueryException, MusicServiceException; + + public ReturnType updateTable(JsonUpdate jsonUpdateObj,MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException; + + public ReturnType deleteFromTable(JsonDelete jsonDeleteObj,MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException; + + +} diff --git a/music-core/src/main/java/org/onap/music/service/impl/MusicCassaCore.java b/music-core/src/main/java/org/onap/music/service/impl/MusicCassaCore.java new file mode 100644 index 00000000..8055a48d --- /dev/null +++ b/music-core/src/main/java/org/onap/music/service/impl/MusicCassaCore.java @@ -0,0 +1,1236 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * Modifications Copyright (c) 2018 IBM. + * =================================================================== + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.service.impl; + +import java.io.StringWriter; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.concurrent.atomic.AtomicInteger; +import javax.ws.rs.core.MultivaluedMap; + +import org.onap.music.datastore.Condition; +import org.onap.music.datastore.MusicDataStore; +import org.onap.music.datastore.MusicDataStoreHandle; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonDelete; +import org.onap.music.datastore.jsonobjects.JsonIndex; +import org.onap.music.datastore.jsonobjects.JsonInsert; +import org.onap.music.datastore.jsonobjects.JsonKeySpace; +import org.onap.music.datastore.jsonobjects.JsonSelect; +import org.onap.music.datastore.jsonobjects.JsonTable; +import org.onap.music.datastore.jsonobjects.JsonUpdate; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicDeadlockException; +import org.onap.music.exceptions.MusicLockingException; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.lockingservice.cassandra.CassaLockStore; +import org.onap.music.lockingservice.cassandra.CassaLockStore.LockObject; +import org.onap.music.lockingservice.cassandra.LockType; +import org.onap.music.lockingservice.cassandra.MusicLockState; +import org.onap.music.lockingservice.cassandra.MusicLockState.LockStatus; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import org.onap.music.main.ReturnType; +import org.onap.music.service.MusicCoreService; + +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.TableMetadata; + +public class MusicCassaCore implements MusicCoreService { + + private static CassaLockStore mLockHandle = null; + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicCassaCore.class); + private static MusicCassaCore musicCassaCoreInstance = null; + private static Set<String> set = Collections.synchronizedSet(new HashSet<String>()); + HashMap<String, Integer> map = new HashMap<>(); + AtomicInteger wait = new AtomicInteger(0); + + private MusicCassaCore() { + // not going to happen + } + + public static CassaLockStore getmLockHandle() { + return mLockHandle; + } + + //for unit testing purposes + static void setmLockHandle(CassaLockStore mLockHandle) { + MusicCassaCore.mLockHandle = mLockHandle; + } + + public static MusicCassaCore getInstance() { + + if(musicCassaCoreInstance == null) { + musicCassaCoreInstance = new MusicCassaCore(); + } + return musicCassaCoreInstance; + } + + public static CassaLockStore getLockingServiceHandle() throws MusicLockingException { + logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring lock store handle"); + long start = System.currentTimeMillis(); + + if (mLockHandle == null) { + try { + mLockHandle = new CassaLockStore(MusicDataStoreHandle.getDSHandle()); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKHANDLE,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + throw new MusicLockingException("Failed to aquire Locl store handle " + e); + } + } + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire lock store handle:" + (end - start) + " ms"); + return mLockHandle; + } + + public String createLockReferenceAtomic(String fullyQualifiedKey) throws MusicLockingException { + return createLockReferenceAtomic(fullyQualifiedKey, LockType.WRITE); + } + public String createLockReference(String fullyQualifiedKey, String owner) throws MusicLockingException { + return createLockReference(fullyQualifiedKey, LockType.WRITE, owner); + } + + + /** + * This will be called for Atomic calls + * it ensures that only one thread tries to create a lock on each key at a time + */ + public String createLockReferenceAtomic(String fullyQualifiedKey, LockType locktype) throws MusicLockingException { + String[] splitString = fullyQualifiedKey.split("\\."); + if (splitString.length < 3) { + throw new MusicLockingException("Missing or incorrect lock details. Check table or key name."); + } + String keyspace = splitString[0]; + String table = splitString[1]; + String lockName = splitString[2]; + + logger.info(EELFLoggerDelegate.applicationLogger,"Creating lock reference for lock name:" + lockName); + long start = 0L; + long end = 0L; + String lockReference = null; + LockObject peek = null; + + /** Lets check for an existing lock. + * This will allow us to limit the amount of requests going forward. + */ + start = System.currentTimeMillis(); + try { + peek = getLockingServiceHandle().peekLockQueue(keyspace, table, lockName); + } catch (MusicServiceException | MusicQueryException e) { + //logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(),e); + throw new MusicLockingException("Error getting lockholder info for key [" + lockName +"]:" + e.getMessage()); + } + + if(peek!=null && (peek.getLocktype()!=null && peek.getLocktype().equals(LockType.WRITE)) && peek.getAcquireTime()!=null && peek.getLockRef()!=null) { + long currentTime = System.currentTimeMillis(); + if((currentTime-Long.parseLong(peek.getAcquireTime()))<MusicUtil.getDefaultLockLeasePeriod()){ + //logger.info(EELFLoggerDelegate.applicationLogger,"Lock holder exists and lease not expired. Please try again for key="+lockName); + throw new MusicLockingException("Unable to create lock reference for key [" + lockName + "]. Please try again."); + } + } + end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to check for lock reference for key [" + lockName + "]:" + (end - start) + " ms"); + + start = System.currentTimeMillis(); + /* We are Creating a Thread safe set and adding the key to the set. + * if a key exists then it wil be passed over and not go to the lock creation. + * If a key doesn't exist then it will set the value in the set and continue to create a lock. + * + * This will ensure that no 2 threads using the same key will be able to try to create a lock + * This wil in turn squash the amout of LWT Chatter in Cassandra an reduce the amount of + * WriteTimeoutExceptions being experiences on single keys. + */ + if ( set.add(fullyQualifiedKey)) { + try { + lockReference = "" + getLockingServiceHandle().genLockRefandEnQueue(keyspace, table, lockName, locktype,null); + set.remove(fullyQualifiedKey); + } catch (MusicLockingException | MusicServiceException | MusicQueryException e) { + set.remove(fullyQualifiedKey); + throw new MusicLockingException(e.getMessage()); + } catch (Exception e) { + set.remove(fullyQualifiedKey); + e.printStackTrace(); + logger.error(EELFLoggerDelegate.applicationLogger,"Exception in creatLockEnforced:"+ e.getMessage(),e); + throw new MusicLockingException("Unable to create lock reference for key [" + lockName + "]. " + e.getMessage()); + } + } else { + throw new MusicLockingException("Unable to create lock reference for key [" + lockName + "]. Please try again."); + } + end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.debugLogger,"### Set = " + set); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to create lock reference for key [" + lockName + "]:" + (end - start) + " ms"); + return lockReference; + + //return createLockReference(fullyQualifiedKey, locktype, null); + } + + public String createLockReference(String fullyQualifiedKey, LockType locktype, String owner) throws MusicLockingException { + String[] splitString = fullyQualifiedKey.split("\\."); + if (splitString.length < 3) { + throw new MusicLockingException("Missing or incorrect lock details. Check table or key name."); + } + String keyspace = splitString[0]; + String table = splitString[1]; + String lockName = splitString[2]; + + logger.info(EELFLoggerDelegate.applicationLogger,"Creating lock reference for lock name:" + lockName); + long start = 0L; + long end = 0L; + String lockReference = null; + + /* Check for a Deadlock */ + try { + boolean deadlock = getLockingServiceHandle().checkForDeadlock(keyspace, table, lockName, locktype, owner, false); + if (deadlock) { + MusicDeadlockException e = new MusicDeadlockException("Deadlock detected when " + owner + " tried to create lock on " + keyspace + "." + table + "." + lockName); + e.setValues(owner, keyspace, table, lockName); + throw e; + } + } catch (MusicDeadlockException e) { + //just threw this, no need to wrap it + throw e; + } catch (MusicServiceException | MusicQueryException e) { + logger.error(EELFLoggerDelegate.applicationLogger, e); + throw new MusicLockingException("Unable to check for deadlock. " + e.getMessage(), e); + } + end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to check for deadlock for key [" + lockName + "]:" + (end - start) + " ms"); + + start = System.currentTimeMillis(); + try { + lockReference = "" + getLockingServiceHandle().genLockRefandEnQueue(keyspace, table, lockName, locktype, owner); + } catch (MusicLockingException | MusicServiceException | MusicQueryException e) { + logger.info(EELFLoggerDelegate.applicationLogger,e.getMessage(),e); + throw new MusicLockingException("Unable to create lock reference for key [" + lockName + "]. Please try again: " + e.getMessage()); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.applicationLogger,e.getMessage(),e); + throw new MusicLockingException("Unable to create lock reference. " + e.getMessage(), e); + } + end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to create lock reference for key [" + lockName + "]:" + (end - start) + " ms"); + return lockReference; + } + + public ReturnType promoteLock(String lockId) throws MusicLockingException { + String[] splitString = lockId.split("\\."); + String keyspace = splitString[0].substring(1);//remove '$' + String table = splitString[1]; + String primaryKeyValue = splitString[2].substring(0, splitString[2].lastIndexOf("$")); + String lockRef = lockId.substring(lockId.lastIndexOf("$")+1); //lockRef is "$" to end + + logger.info(EELFLoggerDelegate.applicationLogger,"Attempting to promote lock " + lockId); + + try { + return getLockingServiceHandle().promoteLock(keyspace, table, primaryKeyValue, lockRef); + } catch (MusicServiceException e) { + throw new MusicLockingException("Unable to promote lock. ", e); + } catch (MusicQueryException e) { + throw new MusicLockingException("Unable to promote lock. ", e); + } + + } + + + public ReturnType acquireLockWithLease(String fullyQualifiedKey, String lockReference, long leasePeriod) + throws MusicLockingException, MusicQueryException, MusicServiceException { + evictExpiredLockHolder(fullyQualifiedKey,leasePeriod); + return acquireLock(fullyQualifiedKey, lockReference); + } + + private void evictExpiredLockHolder(String fullyQualifiedKey, long leasePeriod) + throws MusicLockingException, MusicQueryException, MusicServiceException { + String[] splitString = fullyQualifiedKey.split("\\."); + String keyspace = splitString[0]; + String table = splitString[1]; + String primaryKeyValue = splitString[2]; + + LockObject currentLockHolderObject = getLockingServiceHandle().peekLockQueue(keyspace, table, primaryKeyValue); + + if (!currentLockHolderObject.getIsLockOwner()) { // no lock holder + return; + } + /* + * Release the lock of the previous holder if it has expired. if the update to the acquire time has + * not reached due to network delays, simply use the create time as the reference + */ + long referenceTime = Math.max(Long.parseLong(currentLockHolderObject.getAcquireTime()), + Long.parseLong(currentLockHolderObject.getCreateTime())); + if ((System.currentTimeMillis() - referenceTime) > leasePeriod) { + forciblyReleaseLock(fullyQualifiedKey, currentLockHolderObject.getLockRef() + ""); + logger.info(EELFLoggerDelegate.applicationLogger, currentLockHolderObject.getLockRef() + " forcibly released"); + } + } + + public ReturnType acquireLock(String fullyQualifiedKey, String lockId) + throws MusicLockingException, MusicQueryException, MusicServiceException { + String[] splitString = lockId.split("\\."); + String keyspace = splitString[0].substring(1);//remove '$' + String table = splitString[1]; + String primaryKeyValue = splitString[2].substring(0, splitString[2].lastIndexOf("$")); + String localFullyQualifiedKey = lockId.substring(1, lockId.lastIndexOf("$")); + String lockRef = lockId.substring(lockId.lastIndexOf("$")+1); //lockRef is "$" to end + + LockObject lockInfo = getLockingServiceHandle().getLockInfo(keyspace, table, primaryKeyValue, lockRef); + + if (!lockInfo.getIsLockOwner()) { + return new ReturnType(ResultType.FAILURE, lockId + " is not a lock holder");//not top of the lock store q + } + + if (getLockingServiceHandle().checkForDeadlock(keyspace, table, primaryKeyValue, lockInfo.getLocktype(), lockInfo.getOwner(), true)) { + MusicDeadlockException e = new MusicDeadlockException("Deadlock detected when " + lockInfo.getOwner() + " tried to create lock on " + keyspace + "." + table + "." + primaryKeyValue); + e.setValues(lockInfo.getOwner(), keyspace, table, primaryKeyValue); + throw e; + } + + //check to see if the value of the key has to be synced in case there was a forceful release + String syncTable = keyspace+".unsyncedKeys_"+table; + String query = "select * from "+syncTable+" where key='"+localFullyQualifiedKey+"';"; + PreparedQueryObject readQueryObject = new PreparedQueryObject(); + readQueryObject.appendQueryString(query); + ResultSet results = MusicDataStoreHandle.getDSHandle().executeQuorumConsistencyGet(readQueryObject); + if (!results.all().isEmpty()) { + logger.info("In acquire lock: Since there was a forcible release, need to sync quorum!"); + try { + syncQuorum(keyspace, table, primaryKeyValue); + } catch (Exception e) { + StringWriter sw = new StringWriter(); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR506E] Failed to aquire lock ", + ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR, e); + String exceptionAsString = sw.toString(); + return new ReturnType(ResultType.FAILURE, "Exception thrown while syncing key:\n" + exceptionAsString); + } + String cleanQuery = "delete from " + syncTable + " where key='"+localFullyQualifiedKey+"';"; + PreparedQueryObject deleteQueryObject = new PreparedQueryObject(); + deleteQueryObject.appendQueryString(cleanQuery); + MusicDataStoreHandle.getDSHandle().executePut(deleteQueryObject, "critical"); + } + + getLockingServiceHandle().updateLockAcquireTime(keyspace, table, primaryKeyValue, lockRef); + + return new ReturnType(ResultType.SUCCESS, lockRef+" is the lock holder for the key"); + } + + + + /** + * + * @param tableQueryObject + * @param consistency + * @return Boolean Indicates success or failure + * @throws MusicServiceException + * + */ + public ResultType createTable(String keyspace, String table, PreparedQueryObject tableQueryObject, + String consistency) throws MusicServiceException { + boolean result = false; + + try { + // create shadow locking table + result = getLockingServiceHandle().createLockQueue(keyspace, table); + if (result == false) { + return ResultType.FAILURE; + } + result = false; + + // create table to track unsynced_keys + table = "unsyncedKeys_" + table; + + String tabQuery = + "CREATE TABLE IF NOT EXISTS " + keyspace + "." + table + " ( key text,PRIMARY KEY (key) );"; + PreparedQueryObject queryObject = new PreparedQueryObject(); + + queryObject.appendQueryString(tabQuery); + result = MusicDataStoreHandle.getDSHandle().executePut(queryObject, "eventual"); + if (result == false) { + return ResultType.FAILURE; + } + result = false; + + // create actual table + result = MusicDataStoreHandle.getDSHandle().executePut(tableQueryObject, consistency); + } catch (MusicQueryException | MusicServiceException | MusicLockingException ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.UNKNOWNERROR, ErrorSeverity.WARN, + ErrorTypes.MUSICSERVICEERROR); + throw new MusicServiceException(ex.getMessage()); + } + return result ? ResultType.SUCCESS : ResultType.FAILURE; + } + + private static void syncQuorum(String keyspace, String table, String primaryKeyValue) throws Exception { + logger.info(EELFLoggerDelegate.applicationLogger,"Performing sync operation---"); + PreparedQueryObject selectQuery = new PreparedQueryObject(); + PreparedQueryObject updateQuery = new PreparedQueryObject(); + + // get the primary key d + TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, table); + String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName(); // we only support single + // primary key + DataType primaryKeyType = tableInfo.getPrimaryKey().get(0).getType(); + Object cqlFormattedPrimaryKeyValue = + MusicUtil.convertToActualDataType(primaryKeyType, primaryKeyValue); + + // get the row of data from a quorum + selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + table + " WHERE " + + primaryKeyName + "= ?" + ";"); + selectQuery.addValue(cqlFormattedPrimaryKeyValue); + MusicUtil.writeBackToQuorum(selectQuery, primaryKeyName, updateQuery, keyspace, table, + cqlFormattedPrimaryKeyValue); + } + + /** + * + * @param query + * @return ResultSet + */ + public ResultSet quorumGet(PreparedQueryObject query) { + ResultSet results = null; + try { + results = MusicDataStoreHandle.getDSHandle().executeQuorumConsistencyGet(query); + } catch (MusicServiceException | MusicQueryException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR, + ErrorSeverity.MAJOR, ErrorTypes.GENERALSERVICEERROR, e); + + } + return results; + } + + public String whoseTurnIsIt(String fullyQualifiedKey) { + String[] splitString = fullyQualifiedKey.split("\\."); + String keyspace = splitString[0]; + String table = splitString[1]; + String primaryKeyValue = splitString[2]; + try { + LockObject lockOwner = getLockingServiceHandle().peekLockQueue(keyspace, table, primaryKeyValue); + if (!lockOwner.getIsLockOwner()) { + return null; + } + return "$" + fullyQualifiedKey + "$" + lockOwner.getLockRef(); + } catch (MusicLockingException | MusicServiceException | MusicQueryException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.LOCKINGERROR + fullyQualifiedKey, + ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + } + return null; + } + + public List<String> getCurrentLockHolders(String fullyQualifiedKey) { + String[] splitString = fullyQualifiedKey.split("\\."); + String keyspace = splitString[0]; + String table = splitString[1]; + String primaryKeyValue = splitString[2]; + try { + return getLockingServiceHandle().getCurrentLockHolders(keyspace, table, primaryKeyValue); + } catch (MusicLockingException | MusicServiceException | MusicQueryException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKINGERROR+fullyQualifiedKey ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + } + return null; + } + + /** + * + * @param lockReference + * @return + */ + public static String getLockNameFromId(String lockReference) { + StringTokenizer st = new StringTokenizer(lockReference); + return st.nextToken("$"); + } + + @Override + public void destroyLockRef(String lockId) throws MusicLockingException { + long start = System.currentTimeMillis(); + String fullyQualifiedKey = lockId.substring(1, lockId.lastIndexOf("$")); + String lockRef = lockId.substring(lockId.lastIndexOf('$')+1); + String[] splitString = fullyQualifiedKey.split("\\."); + String keyspace = splitString[0]; + String table = splitString[1]; + String primaryKeyValue = splitString[2]; + try { + getLockingServiceHandle().deQueueLockRef(keyspace, table, primaryKeyValue, lockRef,MusicUtil.getRetryCount()); + } catch (MusicLockingException | MusicServiceException | MusicQueryException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DESTROYLOCK+lockRef, + ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR, e); + throw new MusicLockingException(e.getMessage()); + } + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to destroy lock reference:" + (end - start) + " ms"); + } + + public MusicLockState destroyLockRef(String fullyQualifiedKey, String lockReference) throws MusicLockingException { + long start = System.currentTimeMillis(); + String[] splitString = fullyQualifiedKey.split("\\."); + String keyspace = splitString[0]; + String table = splitString[1]; + String primaryKeyValue = splitString[2]; + try { + getLockingServiceHandle().deQueueLockRef(keyspace, table, primaryKeyValue, lockReference,MusicUtil.getRetryCount()); + } catch (MusicLockingException | MusicServiceException | MusicQueryException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DESTROYLOCK + lockReference, + ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR,e); + throw new MusicLockingException(e.getMessage()); + } + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to destroy lock reference:" + (end - start) + " ms"); + return new MusicLockState(LockStatus.UNLOCKED, ""); + } + + @Override + public MusicLockState releaseLock(String lockId, boolean voluntaryRelease) throws MusicLockingException { + String fullyQualifiedKey = lockId.substring(1, lockId.lastIndexOf("$")); + String lockRef = lockId.substring(lockId.lastIndexOf('$')+1); + if (voluntaryRelease) { + return voluntaryReleaseLock(fullyQualifiedKey, lockRef); + } else { + return forciblyReleaseLock(fullyQualifiedKey, lockRef); + } + } + + public MusicLockState voluntaryReleaseLock(String fullyQualifiedKey, String lockReference) + throws MusicLockingException { + MusicLockState result = null; + try { + result = destroyLockRef(fullyQualifiedKey, lockReference); + } catch (Exception ex) { + logger.info(EELFLoggerDelegate.applicationLogger, + "Exception in voluntaryReleaseLock() for " + fullyQualifiedKey + "ref: " + lockReference); + throw new MusicLockingException(ex.getMessage()); + } + return result; + } + + public MusicLockState forciblyReleaseLock(String fullyQualifiedKey, String lockReference) throws MusicLockingException { + String[] splitString = fullyQualifiedKey.split("\\."); + String keyspace = splitString[0]; + String table = splitString[1]; + + //leave a signal that this key could potentially be unsynchronized + String syncTable = keyspace+".unsyncedKeys_"+table; + PreparedQueryObject queryObject = new PreparedQueryObject(); + String values = "(?)"; + queryObject.addValue(fullyQualifiedKey); + String insQuery = "insert into "+syncTable+" (key) values "+values+";"; + queryObject.appendQueryString(insQuery); + try { + MusicDataStoreHandle.getDSHandle().executePut(queryObject, "critical"); + } catch (Exception e) { + logger.error("Cannot forcibly release lock: " + fullyQualifiedKey + " " + lockReference + ". " + + e.getMessage(), e); + } + + //now release the lock + return destroyLockRef(fullyQualifiedKey, lockReference); + } + + @Override + public List<String> releaseAllLocksForOwner(String ownerId, String keyspace, String table) throws MusicLockingException, MusicServiceException, MusicQueryException { +// System.out.println("IN RELEASEALLLOCKSFOROWNER, "); + + List<String> lockIds = getLockingServiceHandle().getAllLocksForOwner(ownerId, keyspace, table); + for (String lockId : lockIds) { +// System.out.println(" LOCKID = " + lockId); + //return "$" + keyspace + "." + table + "." + lockName + "$" + String.valueOf(lockRef); + releaseLock("$" + keyspace + "." + table + "." + lockId, true); + } + return lockIds; + } + + /** + * + * @param lockName + * @throws MusicLockingException + */ + @Deprecated + public void deleteLock(String lockName) throws MusicLockingException { + throw new MusicLockingException("Depreciated Method Delete Lock"); + } + + // Prepared Query Additions. + + /** + * + * @param queryObject + * @return ReturnType + * @throws MusicServiceException + */ + public ReturnType eventualPut(PreparedQueryObject queryObject) { + boolean result = false; + try { + result = MusicDataStoreHandle.getDSHandle().executePut(queryObject, MusicUtil.EVENTUAL); + } catch (MusicServiceException | MusicQueryException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), "[ERR512E] Failed to get Lock Handle " ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() + " " + ex.getCause() + " " + ex); + return new ReturnType(ResultType.FAILURE, ex.getMessage()); + } + if (result) { + return new ReturnType(ResultType.SUCCESS, "Eventual Operation Successfully performed"); + } else { + return new ReturnType(ResultType.FAILURE, "Eventual Operation failed to perform"); + } + } + + /** + * + * @param queryObject + * @return ReturnType + * @throws MusicServiceException + */ + public ReturnType eventualPut_nb(PreparedQueryObject queryObject,String keyspace,String tablename,String primaryKey) { + boolean result = false; + long guard = 0; + PreparedQueryObject getGaurd = new PreparedQueryObject(); + getGaurd.appendQueryString("SELECT guard FROM "+keyspace+".lockq_"+tablename+ " WHERE key = ? ;"); + getGaurd.addValue(primaryKey); + try { + ResultSet getGaurdResult = MusicDataStoreHandle.getDSHandle().executeQuorumConsistencyGet(getGaurd); + Row row = getGaurdResult.one(); + if (row != null) { + guard = row.getLong("guard"); + long timeOfWrite = System.currentTimeMillis(); + long ts = MusicUtil.v2sTimeStampInMicroseconds(guard, timeOfWrite); + String query = queryObject.getQuery(); + if (!queryObject.getQuery().contains("USING TIMESTAMP")) { + if (queryObject.getOperation().equalsIgnoreCase("delete")) + query = query.replaceFirst("WHERE", " USING TIMESTAMP " + ts + " WHERE "); + else + query = query.replaceFirst("SET", "USING TIMESTAMP " + ts + " SET"); + } + queryObject.replaceQueryString(query); + } + + } catch (MusicServiceException | MusicQueryException e) { + logger.error(EELFLoggerDelegate.applicationLogger,e.getMessage(), e); + } + try { + result = MusicDataStoreHandle.getDSHandle().executePut(queryObject, MusicUtil.EVENTUAL); + } catch (MusicServiceException | MusicQueryException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(),"[ERR512E] Failed to get Lock Handle ", + ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() + " " + ex.getCause() + " ", ex); + return new ReturnType(ResultType.FAILURE, ex.getMessage()); + } + if (result) { + return new ReturnType(ResultType.SUCCESS, "Eventual Operation Successfully performed"); + } else { + return new ReturnType(ResultType.FAILURE, "Eventual Operation failed to perform"); + } + } + + /** + * + * @param keyspace + * @param table + * @param primaryKeyValue + * @param queryObject + * @param lockId + * @return + */ + public ReturnType criticalPut(String keyspace, String table, String primaryKeyValue, + PreparedQueryObject queryObject, String lockId, Condition conditionInfo) { + long start = System.currentTimeMillis(); + try { + String keyLock = lockId.substring(lockId.lastIndexOf(".") + 1,lockId.lastIndexOf("$")); + if (lockId.contains(".") && !keyLock.equals(primaryKeyValue)) { + return new ReturnType(ResultType.FAILURE,"Lock value '" + keyLock + "' and key value '" + + primaryKeyValue + "' not match. Please check your values: " + + lockId + " ."); + } + LockObject lockObject = getLockingServiceHandle().getLockInfo(keyspace, table, primaryKeyValue, + lockId.substring(lockId.lastIndexOf("$") + 1)); + + if ( lockObject == null ) { + return new ReturnType(ResultType.FAILURE, lockId + " does not exist."); + } else if (!lockObject.getIsLockOwner()) { + return new ReturnType(ResultType.FAILURE, lockId + " is not the lock holder"); + } else if (lockObject.getLocktype() != LockType.WRITE) { + return new ReturnType(ResultType.FAILURE, + "Attempting to do write operation, but " + lockId + " is a read lock"); + } + + if (conditionInfo != null) { + try { + if (conditionInfo.testCondition() == false) + return new ReturnType(ResultType.FAILURE, "Lock acquired but the condition is not true"); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e); + return new ReturnType(ResultType.FAILURE, + "Exception thrown while checking the condition, check its sanctity:\n" + e.getMessage()); + } + } + String query = queryObject.getQuery(); + long timeOfWrite = System.currentTimeMillis(); + long lockOrdinal = Long.parseLong(lockId.substring(lockId.lastIndexOf("$") + 1)); + long ts = MusicUtil.v2sTimeStampInMicroseconds(lockOrdinal, timeOfWrite); + // TODO: use Statement instead of modifying query + if (!queryObject.getQuery().contains("USING TIMESTAMP")) { + if (queryObject.getOperation().equalsIgnoreCase("delete")) + query = query.replaceFirst("WHERE", " USING TIMESTAMP " + ts + " WHERE "); + else if (queryObject.getOperation().equalsIgnoreCase("insert")) + query = query.replaceFirst(";", " USING TIMESTAMP " + ts + " ; "); + else + query = query.replaceFirst("SET", "USING TIMESTAMP " + ts + " SET"); + } + queryObject.replaceQueryString(query); + MusicDataStore dsHandle = MusicDataStoreHandle.getDSHandle(); + dsHandle.executePut(queryObject, MusicUtil.CRITICAL); + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the critical put:" + (end - start) + " ms"); + } catch (MusicQueryException | MusicServiceException | MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), e); + return new ReturnType(ResultType.FAILURE, + "Exception thrown while doing the critical put: " + + e.getMessage()); + } + return new ReturnType(ResultType.SUCCESS, "Update performed"); + } + + + /** + * + * @param queryObject + * @param consistency + * @return Boolean Indicates success or failure + * @throws MusicServiceException + * + * + */ + public ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) throws MusicServiceException,MusicQueryException { + // this is mainly for some functions like keyspace creation etc which does not + // really need the bells and whistles of Music locking. + boolean result = false; +// try { + result = MusicDataStoreHandle.getDSHandle().executePut(queryObject, consistency); +// } catch (MusicQueryException | MusicServiceException ex) { + // logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.UNKNOWNERROR, + // ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR, ex); +// throw new MusicServiceException(ex.getMessage(),ex); +// } + return result ? ResultType.SUCCESS : ResultType.FAILURE; + } + + /** + * This method performs DDL operation on cassandra. + * + * @param queryObject query object containing prepared query and values + * @return ResultSet + * @throws MusicServiceException + */ + public ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException { + ResultSet results = null; + try { + results = MusicDataStoreHandle.getDSHandle().executeOneConsistencyGet(queryObject); + } catch (MusicQueryException | MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), e); + throw new MusicServiceException(e.getMessage()); + } + return results; + } + + /** + * This method performs DDL operations on cassandra, if the the resource is available. Lock ID + * is used to check if the resource is free. + * + * @param keyspace name of the keyspace + * @param table name of the table + * @param primaryKeyValue primary key value + * @param queryObject query object containing prepared query and values + * @param lockId lock ID to check if the resource is free to perform the operation. + * @return ResultSet + */ + public ResultSet criticalGet(String keyspace, String table, String primaryKeyValue, + PreparedQueryObject queryObject, String lockId) throws MusicServiceException { + ResultSet results = null; + String keyLock = lockId.substring(lockId.lastIndexOf(".") + 1,lockId.lastIndexOf("$")); + try { + if (lockId.contains(".") && !keyLock.equals(primaryKeyValue)) { + throw new MusicLockingException("Lock value '" + keyLock + "' and key value '" + + primaryKeyValue + "' do not match. Please check your values: " + + lockId + " ."); + } + LockObject lockObject = getLockingServiceHandle().getLockInfo(keyspace, table, primaryKeyValue, + lockId.substring(lockId.lastIndexOf("$") + 1)); + if (null == lockObject) { + throw new MusicLockingException("No Lock Object. Please check if lock name or key is correct." + + lockId + " ."); + } + if ( !lockObject.getIsLockOwner()) { + return null;// not top of the lock store q + } + results = MusicDataStoreHandle.getDSHandle().executeQuorumConsistencyGet(queryObject); + } catch ( MusicLockingException e ) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity + .WARN, ErrorTypes.MUSICSERVICEERROR); + throw new MusicServiceException( + "Cannot perform critical get for key: " + primaryKeyValue + " : " + e.getMessage()); + } catch (MusicQueryException | MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity + .WARN, ErrorTypes.MUSICSERVICEERROR, e); + throw new MusicServiceException( + "Cannot perform critical get for key: " + primaryKeyValue + " : " + e.getMessage()); + } + return results; + } + + /** + * This method performs DML operation on cassandra, when the lock of the dd is acquired. + * + * @param keyspaceName name of the keyspace + * @param tableName name of the table + * @param primaryKey primary key value + * @param queryObject query object containing prepared query and values + * @return ReturnType + * @throws MusicLockingException + * @throws MusicServiceException + * @throws MusicQueryException + */ + public ReturnType atomicPut(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject, Condition conditionInfo) + throws MusicLockingException, MusicQueryException, MusicServiceException { + long start = System.currentTimeMillis(); + String fullyQualifiedKey = keyspaceName + "." + tableName + "." + primaryKey; + String lockId = createLockReferenceAtomic(fullyQualifiedKey, LockType.WRITE); + long lockCreationTime = System.currentTimeMillis(); + ReturnType lockAcqResult = null; + logger.info(EELFLoggerDelegate.applicationLogger, + "***Acquiring lock for atomicPut() query : " + queryObject.getQuery() + " : " + primaryKey); + logger.info(EELFLoggerDelegate.applicationLogger, + "***Acquiring lock for atomicPut() values: " + queryObject.getValues().toString()); + if (conditionInfo != null) { + logger.info(EELFLoggerDelegate.applicationLogger, + "***Acquiring lock for atomicPut() conditions: " + conditionInfo.toString()); + } + try { + lockAcqResult = acquireLockWithLease(fullyQualifiedKey, lockId, MusicUtil.getDefaultLockLeasePeriod()); + } catch (MusicLockingException ex) { + logger.error(EELFLoggerDelegate.errorLogger, + "Exception while acquireLockWithLease() in atomic put for key: " + primaryKey); + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage()); + throw new MusicServiceException( + "Cannot perform atomic put for key: " + primaryKey + " : " + ex.getMessage()); + } + long lockAcqTime = System.currentTimeMillis(); + + /* + * if (!lockAcqResult.getResult().equals(ResultType.SUCCESS)) { logger.info(EELFLoggerDelegate. + * applicationLogger,"unable to acquire lock, id " + lockId); + * voluntaryReleaseLock(fullyQualifiedKey,lockId); return lockAcqResult; } + */ + + logger.info(EELFLoggerDelegate.applicationLogger, "acquired lock with id " + lockId); + String lockRef = lockId.substring(lockId.lastIndexOf("$")); + ReturnType criticalPutResult = null; + if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) { + criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey, queryObject, lockRef, conditionInfo); + long criticalPutTime = System.currentTimeMillis(); + long lockDeleteTime = System.currentTimeMillis(); + String timingInfo = "|lock creation time:" + (lockCreationTime - start) + "|lock accquire time:" + + (lockAcqTime - lockCreationTime) + "|critical put time:" + (criticalPutTime - lockAcqTime) + + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|"; + criticalPutResult.setTimingInfo(timingInfo); + } else { + logger.info(EELFLoggerDelegate.applicationLogger, "unable to acquire lock, id " + lockId); + criticalPutResult = lockAcqResult; + } + try { + voluntaryReleaseLock(fullyQualifiedKey, lockId); + } catch (MusicLockingException ex) { + logger.info(EELFLoggerDelegate.applicationLogger, + "Exception occured while deleting lock after atomic put for key: " + primaryKey); + criticalPutResult.setMessage(criticalPutResult.getMessage() + "Lock release failed"); + } + return criticalPutResult; + } + + + + /** + * This method performs DDL operation on cassasndra, when the lock for the resource is acquired. + * + * @param keyspaceName name of the keyspace + * @param tableName name of the table + * @param primaryKey primary key value + * @param queryObject query object containing prepared query and values + * @return ResultSet + * @throws MusicServiceException + * @throws MusicLockingException + * @throws MusicQueryException + */ + public ResultSet atomicGet(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException, MusicQueryException { + String fullyQualifiedKey = keyspaceName + "." + tableName + "." + primaryKey; + String lockId = createLockReferenceAtomic(fullyQualifiedKey, LockType.READ); + ReturnType lockAcqResult = null; + ResultSet result = null; + logger.info(EELFLoggerDelegate.applicationLogger, "Acquiring lock for atomicGet() : " + queryObject.getQuery()); + try { + lockAcqResult = acquireLockWithLease(fullyQualifiedKey, lockId, MusicUtil.getDefaultLockLeasePeriod()); + } catch (MusicLockingException ex) { + logger.error(EELFLoggerDelegate.errorLogger, + "Exception while acquireLockWithLease() in atomic get for key: " + primaryKey); + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage()); + throw new MusicServiceException( + "Cannot perform atomic get for key: " + primaryKey + " : " + ex.getMessage()); + } + if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) { + logger.info(EELFLoggerDelegate.applicationLogger, "acquired lock with id " + lockId); + String lockRef = lockId.substring(lockId.lastIndexOf("$")); + result = criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockRef); + } else { + logger.info(EELFLoggerDelegate.applicationLogger, "unable to acquire lock, id " + lockId); + } + try { + voluntaryReleaseLock(fullyQualifiedKey, lockId); + } catch (MusicLockingException ex) { + logger.info(EELFLoggerDelegate.applicationLogger, + "Exception occured while deleting lock after atomic put for key: " + primaryKey); + throw new MusicLockingException(ex.getMessage()); + } + + return result; + } + + + + /** + * @param lockName + * @return + */ + public Map<String, Object> validateLock(String lockName) { + return MusicUtil.validateLock(lockName); + } + + @Override + @Deprecated + public ReturnType atomicPutWithDeleteLock(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException { + return null; + } + + @Override + public List<String> getLockQueue(String fullyQualifiedKey) + throws MusicServiceException, MusicQueryException, MusicLockingException { + String[] splitString = fullyQualifiedKey.split("\\."); + String keyspace = splitString[0]; + String table = splitString[1]; + String primaryKeyValue = splitString[2]; + + return getLockingServiceHandle().getLockQueue(keyspace, table, primaryKeyValue); + } + @Override + public long getLockQueueSize(String fullyQualifiedKey) + throws MusicServiceException, MusicQueryException, MusicLockingException { + String[] splitString = fullyQualifiedKey.split("\\."); + String keyspace = splitString[0]; + String table = splitString[1]; + String primaryKeyValue = splitString[2]; + + return getLockingServiceHandle().getLockQueueSize(keyspace, table, primaryKeyValue); + } + + @Override + @Deprecated + public ResultSet atomicGetWithDeleteLock(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException { + //deprecated + return null; + } + + //Methods added for ORM changes + + public ResultType createKeyspace(JsonKeySpace jsonKeySpaceObject,String consistencyInfo) + throws MusicServiceException,MusicQueryException { + ResultType result = nonKeyRelatedPut(jsonKeySpaceObject.genCreateKeyspaceQuery(), consistencyInfo); + logger.info(EELFLoggerDelegate.applicationLogger, " Keyspace Creation Process completed successfully"); + + return result; + } + + public ResultType dropKeyspace(JsonKeySpace jsonKeySpaceObject, String consistencyInfo) + throws MusicServiceException,MusicQueryException { + ResultType result = nonKeyRelatedPut(jsonKeySpaceObject.genDropKeyspaceQuery(), + consistencyInfo); + logger.info(EELFLoggerDelegate.applicationLogger, " Keyspace deletion Process completed successfully"); + return result; + } + + public ResultType createTable(JsonTable jsonTableObject, String consistencyInfo) + throws MusicServiceException, MusicQueryException { + ResultType result = null; + try { + result = createTable(jsonTableObject.getKeyspaceName(), + jsonTableObject.getTableName(), jsonTableObject.genCreateTableQuery(), consistencyInfo); + + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.UNKNOWNERROR, ErrorSeverity.WARN, + ErrorTypes.MUSICSERVICEERROR); + throw new MusicServiceException(ex.getMessage()); + } + logger.info(EELFLoggerDelegate.applicationLogger, " Table Creation Process completed successfully "); + return result; + } + + public ResultType dropTable(JsonTable jsonTableObject,String consistencyInfo) + throws MusicServiceException,MusicQueryException { + ResultType result = nonKeyRelatedPut(jsonTableObject.genDropTableQuery(), + consistencyInfo); + logger.info(EELFLoggerDelegate.applicationLogger, " Table deletion Process completed successfully "); + + return result; + } + + @Override + public ResultType createIndex(JsonIndex jsonIndexObject, String consistencyInfo) + throws MusicServiceException, MusicQueryException{ + ResultType result = nonKeyRelatedPut(jsonIndexObject.genCreateIndexQuery(), + consistencyInfo); + + logger.info(EELFLoggerDelegate.applicationLogger, " Index creation Process completed successfully "); + return result; + } + + /** + * This method performs DDL operation on cassandra. + * + * @param queryObject query object containing prepared query and values + * @return ResultSet + * @throws MusicServiceException + */ + public ResultSet select(JsonSelect jsonSelect, MultivaluedMap<String, String> rowParams) + throws MusicServiceException, MusicQueryException { + ResultSet results = null; + try { + results = get(jsonSelect.genSelectQuery(rowParams)); + } catch (MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + throw new MusicServiceException(e.getMessage()); + } + return results; + } + + /** + * Select Critical + */ + public ResultSet selectCritical(JsonInsert jsonInsertObj, MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException { + + ResultSet results = null; + String consistency = ""; + if(null != jsonInsertObj && null != jsonInsertObj.getConsistencyInfo()) { + consistency = jsonInsertObj.getConsistencyInfo().get("type"); + } + + String lockId = jsonInsertObj.getConsistencyInfo().get("lockId"); + + PreparedQueryObject queryObject = jsonInsertObj.genSelectCriticalPreparedQueryObj(rowParams); + + if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + results = criticalGet(jsonInsertObj.getKeyspaceName(), jsonInsertObj.getTableName(), + jsonInsertObj.getPrimaryKeyVal(), queryObject,lockId); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + results = atomicGet(jsonInsertObj.getKeyspaceName(), jsonInsertObj.getTableName(), + jsonInsertObj.getPrimaryKeyVal(), queryObject); + } + + return results; + } + + /** + * this is insert row into Table + */ + public ReturnType insertIntoTable(JsonInsert jsonInsertObj) + throws MusicLockingException, MusicQueryException, MusicServiceException { + + String consistency = ""; + if(null != jsonInsertObj && null != jsonInsertObj.getConsistencyInfo()) { + consistency = jsonInsertObj.getConsistencyInfo().get("type"); + } + + ReturnType result = null; + + try { + + PreparedQueryObject queryObj = null; + queryObj = jsonInsertObj.genInsertPreparedQueryObj(); + + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) { + result = eventualPut(jsonInsertObj.genInsertPreparedQueryObj()); + } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = jsonInsertObj.getConsistencyInfo().get("lockId"); + if(lockId == null) { + logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); + return new ReturnType(ResultType.FAILURE, "LockId cannot be null. Create lock " + + "and acquire lock or use ATOMIC instead of CRITICAL"); + } + result = criticalPut(jsonInsertObj.getKeyspaceName(), + jsonInsertObj.getTableName(), jsonInsertObj.getPrimaryKeyVal(), jsonInsertObj.genInsertPreparedQueryObj(), lockId,null); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + result = atomicPut(jsonInsertObj.getKeyspaceName(), jsonInsertObj.getTableName(), + jsonInsertObj.getPrimaryKeyVal(), jsonInsertObj.genInsertPreparedQueryObj(), null); + } + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity + .WARN, ErrorTypes.MUSICSERVICEERROR, ex); + return new ReturnType(ResultType.FAILURE, ex.getMessage()); + } + + return result; + } + + /** + * This is insert row into Table + */ + public ReturnType updateTable(JsonUpdate jsonUpdateObj, MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException { + + ReturnType result = null; + String consistency = ""; + if(null != jsonUpdateObj && null != jsonUpdateObj.getConsistencyInfo()) { + consistency = jsonUpdateObj.getConsistencyInfo().get("type"); + } + PreparedQueryObject queryObject = jsonUpdateObj.genUpdatePreparedQueryObj(rowParams); + + Condition conditionInfo; + if (jsonUpdateObj.getConditions() == null) { + conditionInfo = null; + } else { + // to avoid parsing repeatedly, just send the select query to obtain row + PreparedQueryObject selectQuery = new PreparedQueryObject(); + selectQuery.appendQueryString("SELECT * FROM " + jsonUpdateObj.getKeyspaceName() + "." + jsonUpdateObj.getTableName() + " WHERE " + + jsonUpdateObj.getRowIdString() + ";"); + selectQuery.addValue(jsonUpdateObj.getPrimarKeyValue()); + conditionInfo = new Condition(jsonUpdateObj.getConditions(), selectQuery); + } + + + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) { + result = eventualPut(queryObject); + } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = jsonUpdateObj.getConsistencyInfo().get("lockId"); + if(lockId == null) { + logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); + + return new ReturnType(ResultType.FAILURE, "LockId cannot be null. Create lock " + + "and acquire lock or use ATOMIC instead of CRITICAL"); + } + result = criticalPut(jsonUpdateObj.getKeyspaceName(), jsonUpdateObj.getTableName(), jsonUpdateObj.getPrimarKeyValue(), + queryObject, lockId, conditionInfo); + } else if (consistency.equalsIgnoreCase("atomic_delete_lock")) { + // this function is mainly for the benchmarks + try { + result = atomicPutWithDeleteLock(jsonUpdateObj.getKeyspaceName(), jsonUpdateObj.getTableName(), + jsonUpdateObj.getPrimarKeyValue(), queryObject, conditionInfo); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, + ErrorTypes.GENERALSERVICEERROR, e); + throw new MusicLockingException(AppMessages.UNKNOWNERROR.toString()); + + } + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + try { + result = atomicPut(jsonUpdateObj.getKeyspaceName(), jsonUpdateObj.getTableName(), jsonUpdateObj.getPrimarKeyValue(), + queryObject, conditionInfo); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR, e); + throw new MusicLockingException(AppMessages.UNKNOWNERROR.toString()); + } + } else if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) { + try { + result = eventualPut_nb(queryObject, jsonUpdateObj.getKeyspaceName(), + jsonUpdateObj.getTableName(), jsonUpdateObj.getPrimarKeyValue()); + }catch (Exception e) { + return new ReturnType(ResultType.FAILURE, e.getMessage()); + } + + } + + return result; + } + + /** + * This method is for Delete From Table + */ + public ReturnType deleteFromTable(JsonDelete jsonDeleteObj, MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException { + + ReturnType result = null; + String consistency = ""; + if(null != jsonDeleteObj && null != jsonDeleteObj.getConsistencyInfo()) { + consistency = jsonDeleteObj.getConsistencyInfo().get("type"); + } + PreparedQueryObject queryObject = jsonDeleteObj.genDeletePreparedQueryObj(rowParams); + + // get the conditional, if any + Condition conditionInfo; + if (jsonDeleteObj.getConditions() == null) { + conditionInfo = null; + } else { + // to avoid parsing repeatedly, just send the select query to obtain row + PreparedQueryObject selectQuery = new PreparedQueryObject(); + selectQuery.appendQueryString("SELECT * FROM " + jsonDeleteObj.getKeyspaceName() + "." + jsonDeleteObj.getTableName() + " WHERE " + + jsonDeleteObj.getRowIdString() + ";"); + selectQuery.addValue(jsonDeleteObj.getPrimarKeyValue()); + conditionInfo = new Condition(jsonDeleteObj.getConditions(), selectQuery); + } + + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) + result = eventualPut(queryObject); + else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = jsonDeleteObj.getConsistencyInfo().get("lockId"); + if(lockId == null) { + logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); + + return new ReturnType(ResultType.FAILURE, "LockId cannot be null. Create lock " + + "and acquire lock or use ATOMIC instead of CRITICAL"); + } + result = criticalPut(jsonDeleteObj.getKeyspaceName(), + jsonDeleteObj.getTableName(), jsonDeleteObj.getPrimarKeyValue(), + queryObject, lockId, conditionInfo); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + result = atomicPut(jsonDeleteObj.getKeyspaceName(), + jsonDeleteObj.getTableName(), jsonDeleteObj.getPrimarKeyValue(), + queryObject, conditionInfo); + } else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) { + result = eventualPut_nb(queryObject, jsonDeleteObj.getKeyspaceName(), + jsonDeleteObj.getTableName(), jsonDeleteObj.getPrimarKeyValue()); + } + + return result; + } + + +} diff --git a/music-core/src/main/resources/LICENSE.txt b/music-core/src/main/resources/LICENSE.txt new file mode 100644 index 00000000..cc6cdea5 --- /dev/null +++ b/music-core/src/main/resources/LICENSE.txt @@ -0,0 +1,24 @@ + +The following license applies to all files in this and sub-directories. Licenses +are included in individual source files where appropriate, and if it differs +from this text, it supersedes this. Any file that does not have license text +defaults to being covered by this text; not all files support the addition of +licenses. +# +# ------------------------------------------------------------------------- +# Copyright (c) 2017 AT&T Intellectual Property +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------- +#
\ No newline at end of file diff --git a/music-core/src/main/resources/Resources.properties b/music-core/src/main/resources/Resources.properties new file mode 100644 index 00000000..72269cb8 --- /dev/null +++ b/music-core/src/main/resources/Resources.properties @@ -0,0 +1,50 @@ +#============LICENSE_START========================================== +#org.onap.music +#=================================================================== +# Copyright (c) 2017 AT&T Intellectual Property +#=================================================================== +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +#============LICENSE_END============================================= +#==================================================================== +#Resource key=Error Code|Message text|Resolution text |Description text +LOADING_DEFAULT_LOG_CONFIGURATION=\ + EELF0001I|\ + Loading default logging configuration from system resource file "{0}"|\ + No external logging configurations were defined or found, So verify the default logging configuration from system resource file (../logback.xml). |\ + Loading default logging configuration from system resource file +LOADING_LOG_CONFIGURATION=EELF0002I|\ + Loading logging configuration from file "{0}"|\ + Verify the correct logging configuration file is loaded. |\ + Loading logging configuration for specific file +LOGGING_ALREADY_INITIALIZED=\ + EELF0003W|\ + Logging has already been initialized, check the container logging definitions to ensure they represent your desired logging configuration.|\ + Verify the container logging definitions to ensure they represent your desired logging configuration. |\ + Logging has already been initialized, check the container logging definitions to ensure they represent your desired logging configuration. +NO_LOG_CONFIGURATION=\ + EELF0004E|\ + No log configuration could be found or defaulted!|\ + No external and default logging configuration file. |\ + No log configuration could be found or defaulted! +SEARCHING_LOG_CONFIGURATION=\ + EELF0005I|\ + Searching path "{0}" for log configuration file "{1}"|\ + Verify the correct Path({user.home};etc;../etc) and filename (eelf.logging.file).|\ + Searching path for specific log configuration file. +UNSUPPORTED_LOGGING_FRAMEWORK=\ + EELF0006E|\ + An unsupported logging framework is bound to SLF4J. |\ + Verify your logging frameworks.|\ + An unsupported logging framework is bound to SLF4J. + diff --git a/music-core/src/main/resources/logback.xml b/music-core/src/main/resources/logback.xml new file mode 100644 index 00000000..69d59ca3 --- /dev/null +++ b/music-core/src/main/resources/logback.xml @@ -0,0 +1,273 @@ +<!-- + ============LICENSE_START========================================== + org.onap.music + =================================================================== + Copyright (c) 2017 AT&T Intellectual Property + =================================================================== + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + ============LICENSE_END============================================= + ==================================================================== +--> +<configuration scan="true" scanPeriod="3 seconds"> + <!--<jmxConfigurator /> --> + <!-- directory path for all other type logs --> + <property name="logDir" value="/opt/app/music/logs" /> + + <!-- directory path for debugging type logs --> + <property name="debugDir" value="debug-logs" /> + + <!-- specify the component name --> + <!-- <property name="componentName" value="EELF"></property> --> + <property name="componentName" value="MUSIC"></property> + + <!-- log file names --> + <property name="generalLogName" value="music" /> + <property name="securityLogName" value="security" /> + <property name="errorLogName" value="error" /> + <property name="metricsLogName" value="metrics" /> + <property name="auditLogName" value="audit" /> + <property name="debugLogName" value="debug" /> + <property name="defaultPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n" /> + <!-- <property name="applicationLoggerPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %msg%n" /> --> + <property name="applicationLoggerPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5level %X{keyspace} [transactionId:%X{transactionId}] - %msg%n" /> + <property name="auditLoggerPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{VirtualServerName}|%X{ServiceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}|%X{Unused}|%X{ProcessKey}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}| %msg%n" /> + <property name="metricsLoggerPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{VirtualServerName}|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}|%X{Unused}|%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}| %msg%n" /> + <!-- <property name="errorLoggerPattern" value= "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %msg%n " /> --> + <property name="errorLoggerPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5level %X{keyspace} - %msg%n" /> + <property name="debugLoggerPattern" value="%date{ISO8601,UTC}|%X{RequestId}| %msg%n" ></property> + <property name="logDirectory" value="${logDir}/${componentName}" /> + <property name="debugLogDirectory" value="${debugDir}/${componentName}" /> + <!-- Example evaluator filter applied against console appender --> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <!-- <encoder> + <pattern>${defaultPattern}</pattern> + </encoder> --> + <layout class=""> + <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> + </layout> + </appender> + + <!-- ============================================================================ --> + <!-- EELF Appenders --> + <!-- ============================================================================ --> + <!-- <appender name="EELF" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${generalLogName}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${generalLogName}.%i.log.zip</fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>100MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${applicationLoggerPattern}</pattern> + </encoder> + </appender> --> + + <!-- <appender name="EELF" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${generalLogName}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + daily rollover + <fileNamePattern>${logDirectory}/${generalLogName}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern> + <maxFileSize>1GB</maxFileSize> + <maxHistory>5</maxHistory> + <totalSizeCap>5GB</totalSizeCap> + </rollingPolicy> + <encoder> + <pattern>${applicationLoggerPattern}</pattern> + </encoder> + </appender> --> + + + <appender name="EELF" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${generalLogName}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <!-- daily rollover --> + <fileNamePattern>${logDirectory}/${generalLogName}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern> + <maxFileSize>1GB</maxFileSize> + <maxHistory>5</maxHistory> + <totalSizeCap>5GB</totalSizeCap> + </rollingPolicy> + <encoder> + <pattern>${applicationLoggerPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELF" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <includeCallerData>true</includeCallerData> + <appender-ref ref="EELF" /> + </appender> + + <!-- EELF Security Appender. This appender is used to record security events + to the security log file. Security events are separate from other loggers + in EELF so that security log records can be captured and managed in a secure + way separate from the other logs. This appender is set to never discard any + events. --> + <appender name="EELFSecurity" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${securityLogName}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${securityLogName}.%i.log.zip</fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n </pattern> + </encoder> + </appender> + + <appender name="asyncEELFSecurity" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <discardingThreshold>0</discardingThreshold> + <appender-ref ref="EELFSecurity" /> + </appender> + + + + + <!-- EELF Audit Appender. This appender is used to record audit engine + related logging events. The audit logger and appender are specializations + of the EELF application root logger and appender. This can be used to segregate + Policy engine events from other components, or it can be eliminated to record + these events as part of the application root log. --> + + <appender name="EELFAudit" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${auditLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${auditLogName}.%i.log.zip</fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${auditLoggerPattern}</pattern> + </encoder> + </appender> + <appender name="asyncEELFAudit" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFAudit" /> + </appender> + + <appender name="EELFMetrics" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${metricsLogName}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${metricsLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <!-- <pattern>"%d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - %msg%n"</pattern> --> + <pattern>${metricsLoggerPattern}</pattern> + </encoder> + </appender> + + + <appender name="asyncEELFMetrics" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFMetrics"/> + </appender> + + <appender name="EELFError" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${errorLogName}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${errorLogName}.%i.log.zip</fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${errorLoggerPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELFError" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFError"/> + </appender> + + <appender name="EELFDebug" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${debugLogDirectory}/${debugLogName}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${debugLogDirectory}/${debugLogName}.%i.log.zip</fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${debugLoggerPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELFDebug" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFDebug" /> + <includeCallerData>true</includeCallerData> + </appender> + + + <!-- ============================================================================ --> + <!-- EELF loggers --> + <!-- ============================================================================ --> + <logger name="com.att.eelf" level="info" additivity="false"> + <appender-ref ref="asyncEELF" /> + </logger> + + <logger name="com.att.eelf.security" level="info" additivity="false"> + <appender-ref ref="asyncEELFSecurity" /> + </logger> + + + <logger name="com.att.eelf.audit" level="info" additivity="false"> + <appender-ref ref="asyncEELFAudit" /> + </logger> + + <logger name="com.att.eelf.metrics" level="info" additivity="false"> + <appender-ref ref="asyncEELFMetrics" /> + </logger> + + + <logger name="com.att.eelf.error" level="error" additivity="false"> + <appender-ref ref="asyncEELFError" /> + </logger> + + <logger name="com.att.eelf.debug" level="debug" additivity="false"> + <appender-ref ref="asyncEELFDebug" /> + + </logger> + + <root level="INFO"> + <appender-ref ref="asyncEELF" /> + <appender-ref ref="STDOUT" /> + </root> + + <!-- Conductor Specific additions to squash WARNING and INFO --> + <logger name="com.datastax.driver.core.Cluster" level="ERROR"/> + <logger name="org.onap.music.main.MusicCore" level="ERROR"/> + +</configuration> diff --git a/music-core/src/main/resources/project.properties b/music-core/src/main/resources/project.properties new file mode 100644 index 00000000..69b99adc --- /dev/null +++ b/music-core/src/main/resources/project.properties @@ -0,0 +1,5 @@ +version=${project.version} +artifactId=${project.artifactId} +build=${project.version}-${timestamp} +music.properties=/opt/app/music/etc/music.properties + diff --git a/music-core/src/main/webapp/WEB-INF/.gitignore b/music-core/src/main/webapp/WEB-INF/.gitignore new file mode 100644 index 00000000..840e7d31 --- /dev/null +++ b/music-core/src/main/webapp/WEB-INF/.gitignore @@ -0,0 +1 @@ +/classes/ diff --git a/music-core/src/test/java/LICENSE.txt b/music-core/src/test/java/LICENSE.txt new file mode 100644 index 00000000..cc6cdea5 --- /dev/null +++ b/music-core/src/test/java/LICENSE.txt @@ -0,0 +1,24 @@ + +The following license applies to all files in this and sub-directories. Licenses +are included in individual source files where appropriate, and if it differs +from this text, it supersedes this. Any file that does not have license text +defaults to being covered by this text; not all files support the addition of +licenses. +# +# ------------------------------------------------------------------------- +# Copyright (c) 2017 AT&T Intellectual Property +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------- +#
\ No newline at end of file diff --git a/music-core/src/test/java/org/onap/music/cassandra/MusicUtilTest.java b/music-core/src/test/java/org/onap/music/cassandra/MusicUtilTest.java new file mode 100644 index 00000000..b7245d78 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/cassandra/MusicUtilTest.java @@ -0,0 +1,345 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * Modifications Copyright (C) 2019 IBM. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.cassandra; + +import static org.junit.Assert.*; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.junit.Test; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.main.MusicUtil; +//import org.onap.music.main.CorePropertiesLoader; +import org.onap.music.service.MusicCoreService; + +import com.datastax.driver.core.ConsistencyLevel; +import com.datastax.driver.core.DataType; + +public class MusicUtilTest { + + private static final String XLATESTVERSION = "X-latestVersion"; + private static final String XMINORVERSION = "X-minorVersion"; + private static final String XPATCHVERSION = "X-patchVersion"; + + @Test + public void testGetCassName() { + MusicUtil.setCassName("Cassandra"); + assertTrue(MusicUtil.getCassName().equals("Cassandra")); + } + + @Test + public void testGetCassPwd() { + MusicUtil.setCassPwd("Cassandra"); + assertTrue(MusicUtil.getCassPwd().equals("Cassandra")); + } + + @Test + public void testMusicAafNs() { + MusicUtil.setMusicAafNs("ns"); + assertTrue("ns".equals(MusicUtil.getMusicAafNs())); + } + + @Test + public void testMusicCoreService() { + MusicUtil.setLockUsing(MusicUtil.CASSANDRA); + MusicCoreService mc = null; + mc = MusicUtil.getMusicCoreService(); + assertTrue(mc != null); + MusicUtil.setLockUsing("nothing"); + mc = null; + mc = MusicUtil.getMusicCoreService(); + assertTrue(mc != null); + + } + + @Test + public void testCipherEncKey() { + MusicUtil.setCipherEncKey("cipherEncKey"); + assertTrue("cipherEncKey".equals(MusicUtil.getCipherEncKey())); + } + + @Test + public void testGetMusicPropertiesFilePath() { + MusicUtil.setMusicPropertiesFilePath("filepath"); + assertEquals(MusicUtil.getMusicPropertiesFilePath(),"filepath"); + } + + @Test + public void testGetDefaultLockLeasePeriod() { + MusicUtil.setDefaultLockLeasePeriod(5000); + assertEquals(MusicUtil.getDefaultLockLeasePeriod(),5000); + } + + @Test + public void testIsDebug() { + MusicUtil.setDebug(true); + assertTrue(MusicUtil.isDebug()); + } + + @Test + public void testGetVersion() { + MusicUtil.setVersion("1.0.0"); + assertEquals(MusicUtil.getVersion(),"1.0.0"); + } + + @Test + public void testBuildVersionA() { + assertEquals(MusicUtil.buildVersion("1","2","3"),"1.2.3"); + } + + @Test + public void testBuildVersionB() { + assertEquals(MusicUtil.buildVersion("1",null,"3"),"1"); + } + + @Test + public void testBuildVersionC() { + assertEquals(MusicUtil.buildVersion("1","2",null),"1.2"); + } + + /* + @Test + public void testBuileVersionResponse() { + assertTrue(MusicUtil.buildVersionResponse("1","2","3").getClass().getSimpleName().equals("Builder")); + assertTrue(MusicUtil.buildVersionResponse("1",null,"3").getClass().getSimpleName().equals("Builder")); + assertTrue(MusicUtil.buildVersionResponse("1","2",null).getClass().getSimpleName().equals("Builder")); + assertTrue(MusicUtil.buildVersionResponse(null,null,null).getClass().getSimpleName().equals("Builder")); + } + */ + @Test + public void testGetConsistency() { + assertTrue(ConsistencyLevel.ONE.equals(MusicUtil.getConsistencyLevel("one"))); + } + + @Test + public void testRetryCount() { + MusicUtil.setRetryCount(1); + assertEquals(MusicUtil.getRetryCount(),1); + } + + @Test + public void testIsCadi() { + MusicUtil.setIsCadi(true); + assertEquals(MusicUtil.getIsCadi(),true); + } + + + @Test + public void testGetMyCassaHost() { + MusicUtil.setMyCassaHost("10.0.0.2"); + assertEquals(MusicUtil.getMyCassaHost(),"10.0.0.2"); + } + + @Test + public void testIsValidQueryObject() { + PreparedQueryObject myQueryObject = new PreparedQueryObject(); + myQueryObject.appendQueryString("select * from apple where type = ?"); + myQueryObject.addValue("macintosh"); + assertTrue(MusicUtil.isValidQueryObject(true,myQueryObject)); + + myQueryObject.appendQueryString("select * from apple"); + assertTrue(MusicUtil.isValidQueryObject(false,myQueryObject)); + + myQueryObject.appendQueryString("select * from apple where type = ?"); + assertFalse(MusicUtil.isValidQueryObject(true,myQueryObject)); + + myQueryObject = new PreparedQueryObject(); + myQueryObject.appendQueryString(""); + System.out.println("#######" + myQueryObject.getQuery().isEmpty()); + assertFalse(MusicUtil.isValidQueryObject(false,myQueryObject)); + + + } + + + + + @Test(expected = IllegalStateException.class) + public void testMusicUtil() { + System.out.println("MusicUtil Constructor Test"); + MusicUtil mu = new MusicUtil(); + System.out.println(mu.toString()); + } + + @Test + public void testConvertToCQLDataType() throws Exception { + Map<String,Object> myMap = new HashMap<String,Object>(); + myMap.put("name","tom"); + assertEquals(MusicUtil.convertToCQLDataType(DataType.varchar(),"Happy People"),"'Happy People'"); + assertEquals(MusicUtil.convertToCQLDataType(DataType.uuid(),UUID.fromString("29dc2afa-c2c0-47ae-afae-e72a645308ab")),"29dc2afa-c2c0-47ae-afae-e72a645308ab"); + assertEquals(MusicUtil.convertToCQLDataType(DataType.blob(),"Hi"),"Hi"); + assertEquals(MusicUtil.convertToCQLDataType(DataType.map(DataType.varchar(),DataType.varchar()),myMap),"{'name':'tom'}"); + } + + @Test + public void testConvertToActualDataType() throws Exception { + assertEquals(MusicUtil.convertToActualDataType(DataType.varchar(),"Happy People"),"Happy People"); + assertEquals(MusicUtil.convertToActualDataType(DataType.uuid(),"29dc2afa-c2c0-47ae-afae-e72a645308ab"),UUID.fromString("29dc2afa-c2c0-47ae-afae-e72a645308ab")); + assertEquals(MusicUtil.convertToActualDataType(DataType.varint(),"1234"),BigInteger.valueOf(Long.parseLong("1234"))); + assertEquals(MusicUtil.convertToActualDataType(DataType.bigint(),"123"),Long.parseLong("123")); + assertEquals(MusicUtil.convertToActualDataType(DataType.cint(),"123"),Integer.parseInt("123")); + assertEquals(MusicUtil.convertToActualDataType(DataType.cfloat(),"123.01"),Float.parseFloat("123.01")); + assertEquals(MusicUtil.convertToActualDataType(DataType.cdouble(),"123.02"),Double.parseDouble("123.02")); + assertEquals(MusicUtil.convertToActualDataType(DataType.cboolean(),"true"),Boolean.parseBoolean("true")); + List<String> myList = new ArrayList<String>(); + List<String> newList = myList; + myList.add("TOM"); + assertEquals(MusicUtil.convertToActualDataType(DataType.list(DataType.varchar()),myList),newList); + Map<String,Object> myMap = new HashMap<String,Object>(); + myMap.put("name","tom"); + Map<String,Object> newMap = myMap; + assertEquals(MusicUtil.convertToActualDataType(DataType.map(DataType.varchar(),DataType.varchar()),myMap),newMap); + } + + @Test + public void testConvertToActualDataTypeByte() throws Exception { + byte[] testByte = "TOM".getBytes(); + assertEquals(MusicUtil.convertToActualDataType(DataType.blob(),testByte),ByteBuffer.wrap(testByte)); + + } + + @Test + public void testJsonMaptoSqlString() throws Exception { + Map<String,Object> myMap = new HashMap<>(); + myMap.put("name","tom"); + myMap.put("value",5); + String result = MusicUtil.jsonMaptoSqlString(myMap,","); + assertTrue(result.contains("name")); + assertTrue(result.contains("value")); + } + + @Test + public void test_generateUUID() { + //this function shouldn't be in cachingUtil + System.out.println("Testing getUUID"); + String uuid1 = MusicUtil.generateUUID(); + String uuid2 = MusicUtil.generateUUID(); + assertFalse(uuid1==uuid2); + } + + + @Test + public void testIsValidConsistency(){ + assertTrue(MusicUtil.isValidConsistency("ALL")); + assertFalse(MusicUtil.isValidConsistency("TEST")); + } + + @Test + public void testLockUsing() { + MusicUtil.setLockUsing("testlock"); + assertEquals("testlock", MusicUtil.getLockUsing()); + } + + @Test + public void testCassaPort() { + MusicUtil.setCassandraPort(1234); + assertEquals(1234, MusicUtil.getCassandraPort()); + } + + @Test + public void testBuild() { + MusicUtil.setBuild("testbuild"); + assertEquals("testbuild", MusicUtil.getBuild()); + } + + @Test + public void testTransId() { + MusicUtil.setTransIdPrefix("prefix"); + assertEquals("prefix-", MusicUtil.getTransIdPrefix()); + } + + + @Test + public void testConversationIdPrefix() { + MusicUtil.setConversationIdPrefix("prefix-"); + assertEquals("prefix-", MusicUtil.getConversationIdPrefix()); + } + + @Test + public void testClientIdPrefix() { + MusicUtil.setClientIdPrefix("clientIdPrefix"); + assertEquals("clientIdPrefix-", MusicUtil.getClientIdPrefix()); + } + + @Test + public void testMessageIdPrefix() { + MusicUtil.setMessageIdPrefix("clientIdPrefix"); + assertEquals("clientIdPrefix-", MusicUtil.getMessageIdPrefix()); + } + + @Test + public void testTransIdPrefix() { + MusicUtil.setTransIdPrefix("transIdPrefix"); + assertEquals("transIdPrefix-", MusicUtil.getTransIdPrefix()); + } + + @Test + public void testConvIdReq() { + MusicUtil.setConversationIdRequired(true); + assertEquals(true, MusicUtil.getConversationIdRequired()); + } + + @Test + public void testClientIdRequired() { + MusicUtil.setClientIdRequired(true); + assertEquals(true, MusicUtil.getClientIdRequired()); + } + + @Test + public void testMessageIdRequired() { + MusicUtil.setMessageIdRequired(true); + assertEquals(true, MusicUtil.getMessageIdRequired()); + } + + @Test + public void testTransIdRequired() { + MusicUtil.setTransIdRequired(true); + assertEquals(true,MusicUtil.getTransIdRequired()); + } + + @Test + public void testGetCassandraConnectTimeOutMS() { + MusicUtil.setCassandraConnectTimeOutMS(2000); + assertEquals(2000,MusicUtil.getCassandraConnectTimeOutMS()); + } + + @Test + public void testGetCassandraReadTimeOutMS() { + MusicUtil.setCassandraReadTimeOutMS(2000); + assertEquals(2000,MusicUtil.getCassandraReadTimeOutMS()); + } + + /* + @Test + public void testLoadProperties() { + PropertiesLoader pl = new PropertiesLoader(); + pl.loadProperties(); + } + */ +} diff --git a/music-core/src/test/java/org/onap/music/datastore/ConditionTest.java b/music-core/src/test/java/org/onap/music/datastore/ConditionTest.java new file mode 100644 index 00000000..2aac62af --- /dev/null +++ b/music-core/src/test/java/org/onap/music/datastore/ConditionTest.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * ============LICENSE_START========================================== org.onap.music + * =================================================================== Copyright (c) 2019 AT&T + * Intellectual Property =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + *******************************************************************************/ + +package org.onap.music.datastore; + +import org.onap.music.datastore.Condition; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.exceptions.MusicServiceException; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.spy; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.Spy; + +public class ConditionTest { + + @Spy + private Condition condition; + private Map<String, Object> conditions; + private PreparedQueryObject selectQueryForTheRow; + + @Before + public void setup() { + conditions = Mockito.mock(Map.class); + selectQueryForTheRow = Mockito.mock(PreparedQueryObject.class); + condition = spy(new Condition(conditions, selectQueryForTheRow)); + } + + @Test + public void testCondition() throws Exception { + ResultSet rs = Mockito.mock(ResultSet.class); + Row row = Mockito.mock(Row.class); + MusicDataStore dsHandle = Mockito.mock(MusicDataStore.class); + Mockito.when(rs.one()).thenReturn(row); + Mockito.doReturn(rs).when(condition).quorumGet(Mockito.any()); + boolean result = false; + Mockito.when(dsHandle.doesRowSatisfyCondition(Mockito.any(), Mockito.any())).thenReturn(true); + Mockito.doReturn(dsHandle).when(condition).getDSHandle(); + result = condition.testCondition(); + assertEquals(true, result); + } +} diff --git a/music-core/src/test/java/org/onap/music/datastore/MusicDataStoreTest.java b/music-core/src/test/java/org/onap/music/datastore/MusicDataStoreTest.java new file mode 100644 index 00000000..9260cd92 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/datastore/MusicDataStoreTest.java @@ -0,0 +1,436 @@ +/******************************************************************************* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + *******************************************************************************/ +package org.onap.music.datastore; + +import static org.junit.Assert.*; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Consumer; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.MusicUtil; +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.CodecRegistry; +import com.datastax.driver.core.ColumnDefinitions; +import com.datastax.driver.core.ColumnDefinitions.Definition; +import com.datastax.driver.core.exceptions.WriteTimeoutException; +import com.datastax.driver.core.ColumnMetadata; +import com.datastax.driver.core.Configuration; +import com.datastax.driver.core.ConsistencyLevel; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.KeyspaceMetadata; +import com.datastax.driver.core.Metadata; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.SimpleStatement; +import com.datastax.driver.core.Statement; +import com.datastax.driver.core.TableMetadata; +import com.datastax.driver.core.WriteType; + +@RunWith(MockitoJUnitRunner.class) +public class MusicDataStoreTest { + + MusicDataStore dataStore; + + @Mock + Session session; + + @Mock + Cluster cluster; + + @Before + public void before() { + CodecRegistry cr = Mockito.mock(CodecRegistry.class); + Configuration config = Mockito.mock(Configuration.class); + Mockito.when(cluster.getConfiguration()).thenReturn(config); + Mockito.when(config.getCodecRegistry()).thenReturn(cr); + dataStore = new MusicDataStore(cluster, session); + } + + + @Test + public void testMusicDataStoreClusterSession() { + Session session = Mockito.mock(Session.class); + Cluster cluster = Mockito.mock(Cluster.class); + + CodecRegistry cr = Mockito.mock(CodecRegistry.class); + Configuration config = Mockito.mock(Configuration.class); + Mockito.when(cluster.getConfiguration()).thenReturn(config); + Mockito.when(config.getCodecRegistry()).thenReturn(cr); + + + MusicDataStore mds = new MusicDataStore(cluster, session); + assertEquals(session, mds.getSession()); + assertEquals(cluster, mds.getCluster()); + } + + @Test + public void testSession() { + Session session = Mockito.mock(Session.class); + dataStore.setSession(session); + assertEquals(session, dataStore.getSession()); + } + + @Test + public void testCluster() { + Cluster cluster = Mockito.mock(Cluster.class); + CodecRegistry cr = Mockito.mock(CodecRegistry.class); + Configuration config = Mockito.mock(Configuration.class); + Mockito.when(cluster.getConfiguration()).thenReturn(config); + Mockito.when(config.getCodecRegistry()).thenReturn(cr); + + dataStore.setCluster(cluster); + assertEquals(cluster, dataStore.getCluster()); + } + + @Test + public void testClose() { + dataStore.close(); + Mockito.verify(session).close(); + } + + @Test + public void testReturnColumnDataType() { + Metadata meta = Mockito.mock(Metadata.class); + Mockito.when(cluster.getMetadata()).thenReturn(meta); + KeyspaceMetadata ksmd = Mockito.mock(KeyspaceMetadata.class); + Mockito.when(meta.getKeyspace("keyspace")).thenReturn(ksmd); + TableMetadata tmd = Mockito.mock(TableMetadata.class); + Mockito.when(ksmd.getTable("table")).thenReturn(tmd); + ColumnMetadata cmd = Mockito.mock(ColumnMetadata.class); + Mockito.when(tmd.getColumn("columnName")).thenReturn(cmd); + Mockito.when(cmd.getType()).thenReturn(com.datastax.driver.core.DataType.text()); + + com.datastax.driver.core.DataType dt = dataStore.returnColumnDataType("keyspace", "table", "columnName"); + assertEquals(com.datastax.driver.core.DataType.text(), dt); + } + + @Test + public void testReturnColumnMetadata() { + Metadata meta = Mockito.mock(Metadata.class); + Mockito.when(cluster.getMetadata()).thenReturn(meta); + KeyspaceMetadata ksmd = Mockito.mock(KeyspaceMetadata.class); + Mockito.when(meta.getKeyspace("keyspace")).thenReturn(ksmd); + TableMetadata tmd = Mockito.mock(TableMetadata.class); + Mockito.when(ksmd.getTable("tableName")).thenReturn(tmd); + + dataStore.returnColumnMetadata("keyspace", "tableName"); + assertEquals(tmd, dataStore.returnColumnMetadata("keyspace", "tableName")); + } + + @Test + public void testReturnKeyspaceMetadata() { + Metadata meta = Mockito.mock(Metadata.class); + Mockito.when(cluster.getMetadata()).thenReturn(meta); + KeyspaceMetadata ksmd = Mockito.mock(KeyspaceMetadata.class); + Mockito.when(meta.getKeyspace("keyspace")).thenReturn(ksmd); + + assertEquals(ksmd, dataStore.returnKeyspaceMetadata("keyspace")); + } + + @Test + public void testGetColValue() { + Row row = Mockito.mock(Row.class); + Mockito.when(row.getString("columnName")).thenReturn("value"); + UUID uuid = UUID.randomUUID(); + Mockito.when(row.getUUID("columnName")).thenReturn(uuid); + Mockito.when(row.getVarint("columnName")).thenReturn(BigInteger.ONE); + Mockito.when(row.getLong("columnName")).thenReturn((long) 117); + Mockito.when(row.getInt("columnName")).thenReturn(5); + Mockito.when(row.getFloat("columnName")).thenReturn(Float.MAX_VALUE); + Mockito.when(row.getDouble("columnName")).thenReturn(Double.valueOf("2.5")); + Mockito.when(row.getBool("columnName")).thenReturn(true); + Mockito.when(row.getMap("columnName", String.class, String.class)).thenReturn(new HashMap<String, String>()); + Mockito.when(row.getList("columnName", String.class)).thenReturn(new ArrayList<String>()); + + + assertEquals("value", dataStore.getColValue(row, "columnName", DataType.varchar())); + assertEquals(uuid, dataStore.getColValue(row, "columnName", DataType.uuid())); + assertEquals(BigInteger.ONE, dataStore.getColValue(row, "columnName", DataType.varint())); + assertEquals((long) 117, dataStore.getColValue(row, "columnName", DataType.bigint())); + assertEquals(5, dataStore.getColValue(row, "columnName", DataType.cint())); + assertEquals(Float.MAX_VALUE, dataStore.getColValue(row, "columnName", DataType.cfloat())); + assertEquals(2.5, dataStore.getColValue(row, "columnName", DataType.cdouble())); + assertEquals(true, dataStore.getColValue(row, "columnName", DataType.cboolean())); + assertEquals(0, ((Map<String, String>) dataStore.getColValue(row, "columnName", + DataType.map(DataType.varchar(), DataType.varchar()))).size()); + assertEquals(0, + ((List<String>) dataStore.getColValue(row, "columnName", DataType.list(DataType.varchar()))).size()); + } + + @Test + public void testGetBlobValue() { + Row row = Mockito.mock(Row.class); + Mockito.when(row.getBytes("col")).thenReturn(ByteBuffer.allocate(16)); + + byte[] byteArray = dataStore.getBlobValue(row, "col", DataType.blob()); + assertEquals(16, byteArray.length); + } + + @Test + public void testDoesRowSatisfyCondition() throws Exception { + Row row = Mockito.mock(Row.class); + ColumnDefinitions cd = Mockito.mock(ColumnDefinitions.class); + Mockito.when(row.getColumnDefinitions()).thenReturn(cd); + Mockito.when(cd.getType("col1")).thenReturn(DataType.varchar()); + + Map<String, Object> condition = new HashMap<>(); + condition.put("col1", "val1"); + + Mockito.when(row.getString("col1")).thenReturn("val1"); + + assertTrue(dataStore.doesRowSatisfyCondition(row, condition)); + + condition.put("col1", "val2"); + assertFalse(dataStore.doesRowSatisfyCondition(row, condition)); + } + + @Test + public void testMarshalData() { + ResultSet results = Mockito.mock(ResultSet.class); + Row row = Mockito.mock(Row.class); + Mockito.when(row.getString("colName")).thenReturn("rowValue"); + //mock for (Row row: results) + Iterator mockIterator = Mockito.mock(Iterator.class); + //Mockito.doCallRealMethod().when(results).forEach(Mockito.any(Consumer.class)); + Mockito.when(results.iterator()).thenReturn(mockIterator); + Mockito.when(mockIterator.hasNext()).thenReturn(true, false); + Mockito.when(mockIterator.next()).thenReturn(row); + + ColumnDefinitions cd = Mockito.mock(ColumnDefinitions.class); + Mockito.when(row.getColumnDefinitions()).thenReturn(cd); + //for (Definition: colDefinitions) + Iterator mockIterator2 = Mockito.mock(Iterator.class); + //Mockito.doCallRealMethod().when(cd).forEach(Mockito.any(Consumer.class)); + Mockito.when(cd.iterator()).thenReturn(mockIterator2); + Mockito.when(mockIterator2.hasNext()).thenReturn(true, false); + Definition def = Mockito.mock(Definition.class); + Mockito.when(mockIterator2.next()).thenReturn(def); + Mockito.when(def.getType()).thenReturn(DataType.varchar()); + Mockito.when(def.getName()).thenReturn("colName"); + + Map<String, HashMap<String, Object>> data = dataStore.marshalData(results); + System.out.println("Marshalled data: " + data); + + assertTrue(data.containsKey("row 0")); + assertEquals("rowValue", data.get("row 0").get("colName")); + } + + private ArgumentCaptor<SimpleStatement> sessionExecuteResponse() { + ResultSet rs = Mockito.mock(ResultSet.class); + Mockito.when(session.execute(Mockito.any(Statement.class))).thenReturn(rs); + + ArgumentCaptor<SimpleStatement> argument = ArgumentCaptor.forClass(SimpleStatement.class); + return argument; + } + + @Test + public void testExecutePutPreparedQueryObjectString() throws Exception { + ArgumentCaptor<SimpleStatement> argument = sessionExecuteResponse(); + String queryString = "INSERT INTO cycling.cyclist_name (lastname, firstname) VALUES (?,?);"; + String lastName = "KRUIKSWIJK"; + String firstName = "Steven"; + + PreparedQueryObject query = new PreparedQueryObject(queryString, lastName, firstName); + dataStore.executePut(query, MusicUtil.CRITICAL); + + Mockito.verify(session).execute(argument.capture()); + assertEquals(ConsistencyLevel.QUORUM, argument.getValue().getConsistencyLevel()); + assertEquals(queryString, argument.getValue().getQueryString()); + assertEquals(2, argument.getValue().valuesCount()); + } + + @Test + public void testExecutePut_ONE() throws Exception { + ArgumentCaptor<SimpleStatement> argument = sessionExecuteResponse(); + String queryString = "INSERT INTO cycling.cyclist_name (lastname, firstname) VALUES (?,?);"; + String lastName = "KRUIKSWIJK"; + String firstName = "Steven"; + + PreparedQueryObject query = new PreparedQueryObject(queryString, lastName, firstName); + dataStore.executePut(query, MusicUtil.ONE); + + Mockito.verify(session).execute(argument.capture()); + assertEquals(ConsistencyLevel.ONE, argument.getValue().getConsistencyLevel()); + assertEquals(queryString, argument.getValue().getQueryString()); + assertEquals(2, argument.getValue().valuesCount()); + } + + @Test + public void testExecutePut_quorum() throws Exception { + ArgumentCaptor<SimpleStatement> argument = sessionExecuteResponse(); + String queryString = "INSERT INTO cycling.cyclist_name (lastname, firstname) VALUES (?,?);"; + String lastName = "KRUIKSWIJK"; + String firstName = "Steven"; + + PreparedQueryObject query = new PreparedQueryObject(queryString, lastName, firstName); + dataStore.executePut(query, MusicUtil.QUORUM); + + Mockito.verify(session).execute(argument.capture()); + //should be quorum! + assertEquals(ConsistencyLevel.LOCAL_QUORUM, argument.getValue().getConsistencyLevel()); + assertEquals(queryString, argument.getValue().getQueryString()); + assertEquals(2, argument.getValue().valuesCount()); + } + + @Test + public void testExecutePut_ALL() throws Exception { + ArgumentCaptor<SimpleStatement> argument = sessionExecuteResponse(); + String queryString = "INSERT INTO cycling.cyclist_name (lastname, firstname) VALUES (?,?);"; + String lastName = "KRUIKSWIJK"; + String firstName = "Steven"; + + PreparedQueryObject query = new PreparedQueryObject(queryString, lastName, firstName); + dataStore.executePut(query, MusicUtil.ALL); + + Mockito.verify(session).execute(argument.capture()); + assertEquals(ConsistencyLevel.ALL, argument.getValue().getConsistencyLevel()); + assertEquals(queryString, argument.getValue().getQueryString()); + assertEquals(2, argument.getValue().valuesCount()); + } + + @Test(expected = MusicQueryException.class) + public void testExecutePut_BadQueryObj() throws Exception { + String queryString = "INSERT INTO cycling.cyclist_name (lastname, firstname) VALUES (?,?);"; + String lastName = "KRUIKSWIJK"; + String firstName = "Steven"; + + //Provide extra value here, middle initial + PreparedQueryObject query = new PreparedQueryObject(queryString, lastName, firstName, "P"); + try { + dataStore.executePut(query, MusicUtil.CRITICAL); + } catch (Exception e) { + System.out.println(e.getMessage()); + throw e; + } + + fail("Should have throw error"); + } + + @Test + public void testExecutePutPreparedQueryObjectStringLong() throws Exception { + ArgumentCaptor<SimpleStatement> argument = sessionExecuteResponse(); + String queryString = "INSERT INTO cycling.cyclist_name (lastname, firstname) VALUES ('KRUIKSWIJK','Steven');"; + + + PreparedQueryObject query = new PreparedQueryObject(queryString); + dataStore.executePut(query, MusicUtil.EVENTUAL, 10); + + Mockito.verify(session).execute(argument.capture()); + assertEquals(ConsistencyLevel.ONE, argument.getValue().getConsistencyLevel()); + assertEquals(queryString, argument.getValue().getQueryString()); + } + + @Test + public void testExecuteGet() throws Exception { + ArgumentCaptor<SimpleStatement> argument = sessionExecuteResponse(); + + PreparedQueryObject query = new PreparedQueryObject("SELECT * FROM KEYSPACE.TABLE"); + + dataStore.executeGet(query, MusicUtil.ONE); + + Mockito.verify(session).execute(argument.capture()); + assertEquals(ConsistencyLevel.ONE, argument.getValue().getConsistencyLevel()); + assertEquals("SELECT * FROM KEYSPACE.TABLE", argument.getValue().getQueryString()); + } + + @Test (expected = MusicQueryException.class) + public void testExecuteGet_badQuery() throws Exception { + ArgumentCaptor<SimpleStatement> argument = sessionExecuteResponse(); + + PreparedQueryObject query = new PreparedQueryObject("SELECT * FROM KEYSPACE.TABLE", "broken"); + + dataStore.executeGet(query, MusicUtil.ONE); + + Mockito.verify(session).execute(argument.capture()); + assertEquals(ConsistencyLevel.ONE, argument.getValue().getConsistencyLevel()); + assertEquals("SELECT * FROM KEYSPACE.TABLE", argument.getValue().getQueryString()); + } + + @Test + public void testExecuteOneConsistencyGet() throws Exception { + ArgumentCaptor<SimpleStatement> argument = sessionExecuteResponse(); + PreparedQueryObject query = new PreparedQueryObject("SELECT * FROM KEYSPACE.TABLE"); + + dataStore.executeOneConsistencyGet(query); + + + Mockito.verify(session).execute(argument.capture()); + assertEquals(ConsistencyLevel.ONE, argument.getValue().getConsistencyLevel()); + assertEquals("SELECT * FROM KEYSPACE.TABLE", argument.getValue().getQueryString()); + } + + @Test + public void testExecuteLocalQuorumConsistencyGet() throws Exception { + ArgumentCaptor<SimpleStatement> argument = sessionExecuteResponse(); + PreparedQueryObject query = new PreparedQueryObject("SELECT * FROM KEYSPACE.TABLE"); + + dataStore.executeLocalQuorumConsistencyGet(query); + + Mockito.verify(session).execute(argument.capture()); + assertEquals(ConsistencyLevel.LOCAL_QUORUM, argument.getValue().getConsistencyLevel()); + assertEquals("SELECT * FROM KEYSPACE.TABLE", argument.getValue().getQueryString()); + } + + @Test + public void testExecuteQuorumConsistencyGet() throws Exception { + ArgumentCaptor<SimpleStatement> argument = sessionExecuteResponse(); + PreparedQueryObject query = new PreparedQueryObject("SELECT * FROM KEYSPACE.TABLE"); + + dataStore.executeQuorumConsistencyGet(query); + + Mockito.verify(session).execute(argument.capture()); + assertEquals(ConsistencyLevel.QUORUM, argument.getValue().getConsistencyLevel()); + assertEquals("SELECT * FROM KEYSPACE.TABLE", argument.getValue().getQueryString()); + } + + + @Test + public void testExecutePut() { + Mockito.when(session.execute(Mockito.any(SimpleStatement.class))) + .thenThrow(new WriteTimeoutException(ConsistencyLevel.QUORUM, WriteType.CAS, 1, 3)); + + try { + dataStore.executePut(new PreparedQueryObject("Test query"), "critical"); + } catch (MusicServiceException e) { + return; + } catch (MusicQueryException e) { + // should never reach here + fail(); + } + fail(); + } +} diff --git a/music-core/src/test/java/org/onap/music/datastore/PreparedQueryObjectTest.java b/music-core/src/test/java/org/onap/music/datastore/PreparedQueryObjectTest.java new file mode 100644 index 00000000..7ab7d148 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/datastore/PreparedQueryObjectTest.java @@ -0,0 +1,101 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 IBM. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * e + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +public class PreparedQueryObjectTest { + + private PreparedQueryObject preparedQueryObject; + + @Before + public void setUp() + { + preparedQueryObject = new PreparedQueryObject(); + } + + @Test + public void testKeyspaceName() + { + preparedQueryObject.setKeyspaceName("keyspaceName"); + assertEquals("keyspaceName", preparedQueryObject.getKeyspaceName()); + } + + @Test + public void testConsistency() + { + preparedQueryObject.setConsistency("consistency"); + assertEquals("consistency", preparedQueryObject.getConsistency()); + } + + @Test + public void testTableName() + { + preparedQueryObject.setTableName("tableName"); + assertEquals("tableName", preparedQueryObject.getTableName()); + } + + @Test + public void testoperation() + { + preparedQueryObject.setOperation("operation"); + assertEquals("operation", preparedQueryObject.getOperation()); + } + + @Test + public void testprimaryKeyValue() + { + preparedQueryObject.setPrimaryKeyValue("primaryKeyValue"); + assertEquals("primaryKeyValue", preparedQueryObject.getPrimaryKeyValue()); + } + + @Test + public void testAddValue() { + preparedQueryObject.addValue("one"); + assertEquals("one", preparedQueryObject.getValues().get(0)); + } + + @Test + public void testAddValues() { + preparedQueryObject.addValues("one", "two", "three"); + assertEquals(3, preparedQueryObject.getValues().size()); + assertEquals("two", preparedQueryObject.getValues().get(1)); + } + + @Test + public void testConstructorQuery() { + preparedQueryObject = new PreparedQueryObject("some query string"); + assertEquals("some query string", preparedQueryObject.getQuery()); + } + + @Test + public void testConstructorQueryValues() { + preparedQueryObject = new PreparedQueryObject("another query string", "a", "b", "c"); + assertEquals("another query string", preparedQueryObject.getQuery()); + assertEquals(3, preparedQueryObject.getValues().size()); + assertEquals("b", preparedQueryObject.getValues().get(1)); + } +} diff --git a/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JSONObjectTest.java b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JSONObjectTest.java new file mode 100644 index 00000000..9fb549d2 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JSONObjectTest.java @@ -0,0 +1,54 @@ + +/*- + * ============LICENSE_START========================================== + * ONAP MUSIC + * =================================================================== + * Copyright (C) 2020 IBM Intellectual Property. All rights reserved. + * =================================================================== + * + * Unless otherwise specified, all software contained herein is licensed + * under the Apache License, Version 2.0 (the "License"); + * you may not use this software except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Unless otherwise specified, all documentation contained herein is licensed + * under the Creative Commons License, Attribution 4.0 Intl. (the "License"); + * you may not use this documentation except in compliance with the License. + * You may obtain a copy of the License at + * + * https://creativecommons.org/licenses/by/4.0/ + * + * Unless required by applicable law or agreed to in writing, documentation + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================ + * + * + */ +package org.onap.music.datastore.jsonobjects; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class JSONObjectTest { + + @Test + public void testGetData(){ + JSONObject js=new JSONObject(); + js.setData("test"); + assertEquals(js.getData(),"test"); + + } +} diff --git a/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonDeleteTest.java b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonDeleteTest.java new file mode 100644 index 00000000..5b9cef8b --- /dev/null +++ b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonDeleteTest.java @@ -0,0 +1,113 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore.jsonobjects; + +import static org.junit.Assert.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; + +public class JsonDeleteTest { + + JsonDelete jd = null; + + @Before + public void init() { + jd = new JsonDelete(); + } + + @Test + public void testGetConditions() { + Map<String,Object> mapSo = new HashMap<>(); + mapSo.put("key1","one"); + mapSo.put("key2","two"); + jd.setConditions(mapSo); + assertEquals("one",jd.getConditions().get("key1")); + } + + @Test + public void testGetConsistencyInfo() { + Map<String,String> mapSs = new HashMap<>(); + mapSs.put("key3","three"); + mapSs.put("key4","four"); + jd.setConsistencyInfo(mapSs); + assertEquals("three",jd.getConsistencyInfo().get("key3")); + } + + @Test + public void testGetColumns() { + List<String> ary = new ArrayList<>(); + ary.add("e1"); + ary.add("e2"); + ary.add("e3"); + jd.setColumns(ary); + assertEquals("e1",jd.getColumns().get(0)); + } + + @Test + public void testGetTtl() { + jd.setTtl("2000"); + assertEquals("2000",jd.getTtl()); + } + + @Test + public void testGetTimestamp() { + jd.setTimestamp("20:00"); + assertEquals("20:00",jd.getTimestamp()); + + } + + @Test + public void testGetKeyspaceName() { + jd.setKeyspaceName("keyspace"); + assertEquals("keyspace",jd.getKeyspaceName()); + + } + + @Test + public void testGetTableName() { + jd.setTableName("tablename"); + assertEquals("tablename",jd.getTableName()); + + } + + @Test + public void testGetPrimarKeyValue() { + jd.setPrimarKeyValue("primarykey"); + assertEquals("primarykey",jd.getPrimarKeyValue()); + + } + + @Test + public void testRowIdString() { + StringBuilder builder = new StringBuilder("testing"); + jd.setRowIdString(builder); + assertEquals(jd.getRowIdString().toString(),builder.toString()); + } + +} diff --git a/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonIndexTest.java b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonIndexTest.java new file mode 100644 index 00000000..0d89a339 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonIndexTest.java @@ -0,0 +1,74 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore.jsonobjects; + +import static org.junit.Assert.*; +import java.util.HashMap; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.onap.music.datastore.PreparedQueryObject; + +public class JsonIndexTest { + + JsonIndex ji = null; + + + @Before + public void init() { + ji = new JsonIndex(null, null, null, null); + } + + + + @Test + public void testKeyspace() { + ji.setKeyspaceName("keyspaceName"); + assertEquals("keyspaceName", ji.getKeyspaceName()); + } + + @Test + public void testIndexName() { + ji.setIndexName("indexName"); + assertEquals("indexName", ji.getIndexName()); + } + + @Test + public void testFieldName() { + ji.setFieldName("field"); + assertEquals("field", ji.getFieldName()); + } + + @Test + public void testTableName() { + ji.setTableName("table"); + assertEquals("table", ji.getTableName()); + } + + @Test + public void testCreateIndexQuery() { + JsonIndex ji2 = new JsonIndex("index", "keyspace", "table", "field"); + PreparedQueryObject query = ji2.genCreateIndexQuery(); + assertEquals("Create index if not exists index on keyspace.table (field);", query.getQuery()); + } +} diff --git a/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonInsertTest.java b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonInsertTest.java new file mode 100644 index 00000000..ad71c9ea --- /dev/null +++ b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonInsertTest.java @@ -0,0 +1,176 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (c) 2019 IBM. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore.jsonobjects; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.SerializationUtils; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.internal.util.reflection.FieldSetter; +import org.onap.music.datastore.MusicDataStore; +import org.onap.music.datastore.MusicDataStoreHandle; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import com.datastax.driver.core.ColumnMetadata; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.Session; +//import org.mockito.internal.util.reflection.Whitebox; +import com.datastax.driver.core.TableMetadata; + + +public class JsonInsertTest { + + JsonInsert ji = new JsonInsert(); + + @Test + public void testGetKeyspaceName() { + ji.setKeyspaceName("keyspace"); + assertEquals("keyspace",ji.getKeyspaceName()); + } + + @Test + public void testGetTableName() { + ji.setTableName("table"); + assertEquals("table",ji.getTableName()); + } + + @Test + public void testGetConsistencyInfo() { + Map<String,String> cons = new HashMap<>(); + cons.put("test","true"); + ji.setConsistencyInfo(cons); + assertEquals("true",ji.getConsistencyInfo().get("test")); + } + + @Test + public void testGetTtl() { + ji.setTtl("ttl"); + assertEquals("ttl",ji.getTtl()); + } + + @Test + public void testGetTimestamp() { + ji.setTimestamp("10:30"); + assertEquals("10:30",ji.getTimestamp()); + } + + @Test + public void testGetValues() { + Map<String,Object> cons = new HashMap<>(); + cons.put("val1","one"); + cons.put("val2","two"); + ji.setValues(cons); + assertEquals("one",ji.getValues().get("val1")); + } + + @Test + public void testGetRowSpecification() { + Map<String,Object> cons = new HashMap<>(); + cons.put("val1","one"); + cons.put("val2","two"); + ji.setRowSpecification(cons); + assertEquals("two",ji.getRowSpecification().get("val2")); + } + + @Test + public void testSerialize() { + Map<String,Object> cons = new HashMap<>(); + cons.put("val1","one"); + cons.put("val2","two"); + ji.setTimestamp("10:30"); + ji.setRowSpecification(cons); + byte[] test1 = ji.serialize(); + byte[] ji1 = SerializationUtils.serialize(ji); + assertArrayEquals(ji1,test1); + } + + @Test + public void testObjectMap() + { + Map<String, byte[]> map = new HashMap<>(); + ji.setObjectMap(map); + assertEquals(map, ji.getObjectMap()); + } + + @Test + public void testPrimaryKey() { + ji.setPrimaryKeyVal("primKey"); + assertEquals("primKey", ji.getPrimaryKeyVal()); + } + + @Test + public void testGenInsertPreparedQueryObj() throws Exception { + ji.setKeyspaceName("keyspace"); + ji.setTableName("table"); + ji.setPrimaryKeyVal("value"); + Map<String,Object> rowSpec = new HashMap<>(); + rowSpec.put("val1","one"); + rowSpec.put("val2","two"); + ji.setRowSpecification(rowSpec); + Map<String,Object> vals = new HashMap<>(); + vals.put("val1","one"); + vals.put("val2","two"); + ji.setValues(vals); + + Map<String,String> cons = new HashMap<>(); + cons.put("type","quorum"); + ji.setConsistencyInfo(cons); + + MusicDataStore mds = Mockito.mock(MusicDataStore.class); + Session session = Mockito.mock(Session.class); + Mockito.when(mds.getSession()).thenReturn(session); + MusicDataStoreHandle mdsh = Mockito.mock(MusicDataStoreHandle.class); + FieldSetter.setField(mdsh, mdsh.getClass().getDeclaredField("mDstoreHandle"), mds); + TableMetadata tableMeta = Mockito.mock(TableMetadata.class); + Mockito.when(mds.returnColumnMetadata(Mockito.anyString(), Mockito.anyString())) + .thenReturn(tableMeta); + + ColumnMetadata cmd = Mockito.mock(ColumnMetadata.class); + List<ColumnMetadata> listcmd = new ArrayList<>(); + listcmd.add(cmd); + Mockito.when(tableMeta.getPrimaryKey()).thenReturn(listcmd); + Mockito.when(cmd.getName()).thenReturn("val1"); + Mockito.when(tableMeta.getColumn("val1")).thenReturn(cmd); + Mockito.when(tableMeta.getColumn("val2")).thenReturn(cmd); + Mockito.when(cmd.getType()).thenReturn(DataType.text()); + + PreparedQueryObject query = ji.genInsertPreparedQueryObj(); + System.out.println(query.getQuery()); + System.out.println(query.getValues()); + + + assertEquals("INSERT INTO keyspace.table (vector_ts,val2,val1) VALUES (?,?,?);", query.getQuery()); + assertTrue(query.getValues().containsAll(vals.values())); + } + +} diff --git a/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonKeySpaceTest.java b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonKeySpaceTest.java new file mode 100644 index 00000000..a3fa58e4 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonKeySpaceTest.java @@ -0,0 +1,72 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore.jsonobjects; + +import static org.junit.Assert.*; +import java.util.HashMap; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; + +public class JsonKeySpaceTest { + + JsonKeySpace jk = null; + + + @Before + public void init() { + jk = new JsonKeySpace(); + } + + + + @Test + public void testGetConsistencyInfo() { + Map<String, String> mapSs = new HashMap<>(); + mapSs.put("k1", "one"); + jk.setConsistencyInfo(mapSs); + assertEquals("one",jk.getConsistencyInfo().get("k1")); + } + + @Test + public void testGetReplicationInfo() { + Map<String,Object> mapSo = new HashMap<>(); + mapSo.put("k1", "one"); + jk.setReplicationInfo(mapSo); + assertEquals("one",jk.getReplicationInfo().get("k1")); + + } + + @Test + public void testGetDurabilityOfWrites() { + jk.setDurabilityOfWrites("1"); + assertEquals("1",jk.getDurabilityOfWrites()); + } + + @Test + public void testGetKeyspaceName() { + jk.setKeyspaceName("Keyspace"); + assertEquals("Keyspace",jk.getKeyspaceName()); + } + +} diff --git a/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonLockTest.java b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonLockTest.java new file mode 100644 index 00000000..75db75e5 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonLockTest.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + *******************************************************************************/ + +package org.onap.music.datastore.jsonobjects; + +import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Test; +import org.onap.music.lockingservice.cassandra.LockType; + +public class JsonLockTest { + + JsonLock jsonLock; + + @Before + public void setup() { + jsonLock = new JsonLock(); + } + + @Test + public void testSetLockType() { + jsonLock.setLockType(LockType.READ); + assertEquals(LockType.READ, jsonLock.getLocktype()); + + jsonLock.setLockType(LockType.WRITE); + assertEquals(LockType.WRITE, jsonLock.getLocktype()); + + jsonLock.setLockType(LockType.PROMOTING); + assertEquals(LockType.PROMOTING, jsonLock.getLocktype()); + } +} diff --git a/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonSelectTest.java b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonSelectTest.java new file mode 100644 index 00000000..baada1d5 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonSelectTest.java @@ -0,0 +1,68 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (c) 2018-2019 IBM + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore.jsonobjects; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; + +public class JsonSelectTest { + JsonSelect js = new JsonSelect(); + + @Test + public void testGetConsistencyInfo() { + Map<String, String> mapSs = new HashMap<>(); + mapSs.put("k1", "one"); + js.setConsistencyInfo(mapSs); + assertEquals("one", js.getConsistencyInfo().get("k1")); + } + + @Test + public void testSerialize() throws IOException { + Map<String, String> mapSs = new HashMap<>(); + mapSs.put("Key", "Value"); + js.setConsistencyInfo(mapSs); + js.serialize(); + } + + @Test + public void testGetKeyspaceName() { + js.setKeyspaceName("testkeyspace"); + assertEquals("testkeyspace",js.getKeyspaceName()); + + } + + @Test + public void testGetTableName() { + js.setTableName("testkeyspace"); + assertEquals("testkeyspace",js.getTableName()); + + } + +} diff --git a/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonTableTest.java b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonTableTest.java new file mode 100644 index 00000000..3ab32d40 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonTableTest.java @@ -0,0 +1,153 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (c) 2019 IBM. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore.jsonobjects; + +import static org.junit.Assert.*; +import java.util.HashMap; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.onap.music.exceptions.MusicQueryException; + +public class JsonTableTest { + + JsonTable jt = null; + + @Before + public void init() { + jt = new JsonTable(); + } + + @Test + public void testGetConsistencyInfo() { + Map<String, String> mapSs = new HashMap<>(); + mapSs.put("k1", "one"); + jt.setConsistencyInfo(mapSs); + assertEquals("one",jt.getConsistencyInfo().get("k1")); + } + + @Test + public void testGetProperties() { + Map<String, Object> properties = new HashMap<>(); + properties.put("k1", "one"); + jt.setProperties(properties); + assertEquals(properties.size(), jt.getProperties().size()); + } + + @Test + public void testGetFields() { + Map<String, String> fields = new HashMap<>(); + fields.put("k1", "one"); + jt.setFields(fields); + assertEquals("one",jt.getFields().get("k1")); + } + + @Test + public void testGetKeyspaceName() { + String keyspace = "keyspace"; + jt.setKeyspaceName(keyspace); + assertEquals(keyspace,jt.getKeyspaceName()); + } + + @Test + public void testGetTableName() { + String table = "table"; + jt.setTableName(table); + assertEquals(table,jt.getTableName()); + } + + @Test + public void testGetClusteringOrder() { + String clusteringOrder = "clusteringOrder"; + jt.setClusteringOrder(clusteringOrder); + assertEquals(clusteringOrder,jt.getClusteringOrder()); + } + + @Test + public void testGetClusterKey() { + String clusterKey = "clusterKey"; + jt.setClusteringKey(clusterKey); + assertEquals(clusterKey, jt.getClusteringKey()); + } + + @Test + public void testGetPrimaryKey() { + String primaryKey = "primaryKey"; + jt.setPrimaryKey(primaryKey); + assertEquals(primaryKey,jt.getPrimaryKey()); + } + + @Test + public void testFilteringKey() { + jt.setFilteringKey("FilteringKey"); + assertEquals("FilteringKey",jt.getFilteringKey()); + } + + @Test + public void testPartitionKey() { + jt.setPartitionKey("ParitionKey"); + assertEquals("ParitionKey",jt.getPartitionKey()); + } + + @Test + public void genCreateTableQuery() throws MusicQueryException { + JsonTable jt2 = new JsonTable(); + jt2.setKeyspaceName("keyspace"); + jt2.setTableName("table"); + Map<String, String> fields = new HashMap<>(); + fields.put("k1", "one"); + jt2.setFields(fields); + jt2.setPrimaryKey("k1"); + Map<String, String> mapSs = new HashMap<>(); + mapSs.put("k1", "one"); + jt2.setConsistencyInfo(mapSs); + String clusteringOrder = "clusteringOrder"; + jt.setClusteringOrder(clusteringOrder); + String clusterKey = "clusterKey"; + jt.setClusteringKey(clusterKey); + + System.out.println(jt2.genCreateTableQuery().getQuery()); + assertEquals("CREATE TABLE keyspace.table (vector_ts text,k1 one, PRIMARY KEY ( (k1) ));", + jt2.genCreateTableQuery().getQuery()); + } + + @Test + public void genDropTableQuery() throws MusicQueryException { + JsonTable jt2 = new JsonTable(); + jt2.setKeyspaceName("keyspace"); + jt2.setTableName("table"); + Map<String, String> fields = new HashMap<>(); + fields.put("k1", "one"); + jt2.setFields(fields); + jt2.setPrimaryKey("k1"); + Map<String, String> mapSs = new HashMap<>(); + mapSs.put("k1", "one"); + jt.setConsistencyInfo(mapSs); + + System.out.println(jt2.genDropTableQuery().getQuery()); + assertEquals("DROP TABLE keyspace.table;", + jt2.genDropTableQuery().getQuery()); + } +} diff --git a/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonUpdateTest.java b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonUpdateTest.java new file mode 100644 index 00000000..37c729f4 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/JsonUpdateTest.java @@ -0,0 +1,166 @@ +/******************************************************************************* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2018 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (c) 2019 IBM. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + *******************************************************************************/ + +package org.onap.music.datastore.jsonobjects; + +import static org.junit.Assert.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.ws.rs.core.MultivaluedMap; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.music.datastore.jsonobjects.JsonUpdate.RowIdentifier; +import com.datastax.driver.core.ColumnMetadata; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.TableMetadata; + +public class JsonUpdateTest { + + JsonUpdate ju = null; + + @Before + public void init() { + ju = new JsonUpdate(); + } + + + @Test + public void testGetConditions() { + Map<String,Object> mapSo = new HashMap<>(); + mapSo.put("key1","one"); + mapSo.put("key2","two"); + ju.setConditions(mapSo); + assertEquals("one",ju.getConditions().get("key1")); + } + + @Test + public void testGetRow_specification() { + Map<String,Object> mapSo = new HashMap<>(); + mapSo.put("key1","one"); + mapSo.put("key2","two"); + ju.setRow_specification(mapSo); + assertEquals("one",ju.getRow_specification().get("key1")); + } + + @Test + public void testGetKeyspaceName() { + String keyspace = "keyspace"; + ju.setKeyspaceName(keyspace); + assertEquals(keyspace,ju.getKeyspaceName()); + } + + @Test + public void testGetTableName() { + String table = "table"; + ju.setTableName(table); + assertEquals(table,ju.getTableName()); + } + + @Test + public void testGetConsistencyInfo() { + Map<String, String> mapSs = new HashMap<>(); + mapSs.put("k1", "one"); + ju.setConsistencyInfo(mapSs); + assertEquals("one",ju.getConsistencyInfo().get("k1")); + } + + @Test + public void testGetTtl() { + ju.setTtl("2000"); + assertEquals("2000",ju.getTtl()); + } + + @Test + public void testGetTimestamp() { + ju.setTimestamp("20:00"); + assertEquals("20:00",ju.getTimestamp()); + + } + + @Test + public void testGetValues() { + Map<String,Object> cons = new HashMap<>(); + cons.put("val1","one"); + cons.put("val2","two"); + ju.setValues(cons); + assertEquals("one",ju.getValues().get("val1")); + } + + @Test + public void testSerialize() { + assertTrue(ju.serialize() instanceof byte[]); + } + + @Test + public void testRowIdString() { + ju.setRowIdString("testing"); + assertEquals("testing", ju.getRowIdString()); + } + + @Test + public void testPrimaryKeyValue() { + ju.setPrimarKeyValue("primeKey"); + assertEquals("primeKey", ju.getPrimarKeyValue()); + } + + @Test + public void testGenUpdatePreparedQueryObj() throws Exception { + JsonUpdate ju = Mockito.spy(JsonUpdate.class); + MultivaluedMap<String, String> rowParams = Mockito.mock(MultivaluedMap.class); + + ju.setKeyspaceName("keyspace"); + ju.setTableName("table"); + ju.setPrimarKeyValue("primaryKeyValue"); + Map<String, String> consistencyInfo = new HashMap<>(); + consistencyInfo.put("type", "critical"); + ju.setConsistencyInfo(consistencyInfo); + Map<String, Object> values = new HashMap<>(); + values.put("col1", "val1"); + ju.setValues(values); + + TableMetadata tmd = Mockito.mock(TableMetadata.class); + Mockito.doReturn(tmd).when(ju).returnColumnMetadata(Mockito.anyString(), Mockito.anyString()); + ColumnMetadata cmd = Mockito.mock(ColumnMetadata.class); + Mockito.when(tmd.getColumn("col1")).thenReturn(cmd); + List<ColumnMetadata> colList = new ArrayList<>(); + colList.add(cmd); + Mockito.when(tmd.getPrimaryKey()).thenReturn(colList); + Mockito.when(cmd.getType()).thenReturn(DataType.varchar()); + + RowIdentifier rowId = Mockito.mock(RowIdentifier.class); + Mockito.doReturn(rowId).when(ju).getRowIdentifier(Mockito.anyString(), Mockito.anyString(), Mockito.any(), + Mockito.any()); + + Mockito.when(rowId.getRowIdString()).thenReturn("col1"); + Mockito.when(rowId.getPrimaryKeyValue()).thenReturn("val1"); + + + assertEquals("UPDATE keyspace.table SET vector_ts=?,col1= ? WHERE col1;", + ju.genUpdatePreparedQueryObj(rowParams).getQuery()); + } +} diff --git a/music-core/src/test/java/org/onap/music/datastore/jsonobjects/RowIdentifierTest.java b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/RowIdentifierTest.java new file mode 100644 index 00000000..e29f0377 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/datastore/jsonobjects/RowIdentifierTest.java @@ -0,0 +1,60 @@ +/*- + * ============LICENSE_START========================================== + * ONAP MUSIC + * =================================================================== + * Copyright (C) 2020 IBM Intellectual Property. All rights reserved. + * =================================================================== + * + * Unless otherwise specified, all software contained herein is licensed + * under the Apache License, Version 2.0 (the "License"); + * you may not use this software except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Unless otherwise specified, all documentation contained herein is licensed + * under the Creative Commons License, Attribution 4.0 Intl. (the "License"); + * you may not use this documentation except in compliance with the License. + * You may obtain a copy of the License at + * + * https://creativecommons.org/licenses/by/4.0/ + * + * Unless required by applicable law or agreed to in writing, documentation + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================ + * + * + */ +package org.onap.music.datastore.jsonobjects; + +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonUpdate; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class RowIdentifierTest { + String primarykey="primarykey"; + String rowIdString="123"; + PreparedQueryObject queryObject=new PreparedQueryObject("select * from employee"); + JsonUpdate ju=new JsonUpdate(); + JsonUpdate.RowIdentifier rowId= ju.new RowIdentifier(primarykey,rowIdString,queryObject); + @Test + public void testConstructor(){ + rowId.setPrimaryKeyValue(primarykey); + rowId.setRowIdString(rowIdString); + assertEquals(rowId.getPrimaryKeyValue(),"primarykey"); + assertEquals(rowId.getRowIdString(),"123"); + } +} diff --git a/music-core/src/test/java/org/onap/music/eelf/logging/format/AppMessagesTest.java b/music-core/src/test/java/org/onap/music/eelf/logging/format/AppMessagesTest.java new file mode 100644 index 00000000..cba9c7c2 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/eelf/logging/format/AppMessagesTest.java @@ -0,0 +1,65 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 IBM Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + */ + +package org.onap.music.eelf.logging.format; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +public class AppMessagesTest { + + private AppMessages messages; + + @Before + public void setUp() { + messages= AppMessages.ALREADYEXIST; + } + + @Test + public void testDetails() + { + messages.setDetails("details"); + assertEquals("details", messages.getDetails()); + } + + @Test + public void testResolution() + { + messages.setResolution("Resolution"); + assertEquals("Resolution", messages.getResolution()); + } + + @Test + public void testErrorCode() + { + messages.setErrorCode("ErrorCode"); + assertEquals("ErrorCode", messages.getErrorCode()); + } + + @Test + public void testErrorDescription() + { + messages.setErrorDescription("ErrorDescription"); + assertEquals("ErrorDescription", messages.getErrorDescription()); + } +} diff --git a/music-core/src/test/java/org/onap/music/eelf/logging/format/ErrorSeverityTest.java b/music-core/src/test/java/org/onap/music/eelf/logging/format/ErrorSeverityTest.java new file mode 100644 index 00000000..b2b0fafa --- /dev/null +++ b/music-core/src/test/java/org/onap/music/eelf/logging/format/ErrorSeverityTest.java @@ -0,0 +1,41 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 IBM Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + */ +package org.onap.music.eelf.logging.format; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class ErrorSeverityTest { + + @Test + public void TestErrorServerity() + { + assertEquals("INFO",ErrorSeverity.INFO.name()); + assertEquals("WARN",ErrorSeverity.WARN.name()); + assertEquals("ERROR",ErrorSeverity.ERROR.name()); + assertEquals("FATAL",ErrorSeverity.FATAL.name()); + assertEquals("CRITICAL",ErrorSeverity.CRITICAL.name()); + assertEquals("MAJOR",ErrorSeverity.MAJOR.name()); + assertEquals("MINOR",ErrorSeverity.MINOR.name()); + assertEquals("NONE",ErrorSeverity.NONE.name()); + } +} diff --git a/music-core/src/test/java/org/onap/music/eelf/logging/format/ErrorTypesTest.java b/music-core/src/test/java/org/onap/music/eelf/logging/format/ErrorTypesTest.java new file mode 100644 index 00000000..ff7b188b --- /dev/null +++ b/music-core/src/test/java/org/onap/music/eelf/logging/format/ErrorTypesTest.java @@ -0,0 +1,48 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * Modifications Copyright (C) 2019 IBM + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.eelf.logging.format; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class ErrorTypesTest { + + @Test + public void Test1() + { + assertEquals("CONNECTIONERROR",ErrorTypes.CONNECTIONERROR.name()); + assertEquals("SESSIONEXPIRED",ErrorTypes.SESSIONEXPIRED.name()); + assertEquals("AUTHENTICATIONERROR",ErrorTypes.AUTHENTICATIONERROR.name()); + assertEquals("CACHEERROR",ErrorTypes.CACHEERROR.name()); + assertEquals("SERVICEUNAVAILABLE",ErrorTypes.SERVICEUNAVAILABLE.name()); + assertEquals("QUERYERROR",ErrorTypes.QUERYERROR.name()); + assertEquals("DATAERROR",ErrorTypes.DATAERROR.name()); + assertEquals("GENERALSERVICEERROR",ErrorTypes.GENERALSERVICEERROR.name()); + assertEquals("MUSICSERVICEERROR",ErrorTypes.MUSICSERVICEERROR.name()); + assertEquals("LOCKINGERROR",ErrorTypes.LOCKINGERROR.name()); + assertEquals("UNKNOWN",ErrorTypes.UNKNOWN.name()); + + } +} diff --git a/music-core/src/test/java/org/onap/music/exceptions/MusicDeadlockExceptionTest.java b/music-core/src/test/java/org/onap/music/exceptions/MusicDeadlockExceptionTest.java new file mode 100644 index 00000000..db0e10ea --- /dev/null +++ b/music-core/src/test/java/org/onap/music/exceptions/MusicDeadlockExceptionTest.java @@ -0,0 +1,135 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 IBM Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.exceptions; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class MusicDeadlockExceptionTest { + + private String owner = "tester"; + private String keyspace = "testing"; + private String table = "lockq"; + private String key = "test"; + + @Test + public void TestException1() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicDeadlockException(); + } + } catch (MusicDeadlockException mde) { + assertEquals("org.onap.music.exceptions.MusicDeadlockException", mde.getClass().getName()); + } + + } + + @Test + public void TestException6() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicDeadlockException("org.onap.music.exceptions.MusicDeadlockException"); + } + } catch (MusicDeadlockException mde) { + assertEquals(mde.getMessage(),"org.onap.music.exceptions.MusicDeadlockException"); + } + + } + + @Test + public void TestException2() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicDeadlockException("MusicDeadlockException Exception occured.."); + } + } catch (MusicDeadlockException mde) { + assertEquals(mde.getMessage(), "MusicDeadlockException Exception occured.."); + } + + } + + @Test + public void TestException3() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicDeadlockException(new Throwable()); + } + } catch (MusicDeadlockException mve) { + assertEquals("org.onap.music.exceptions.MusicDeadlockException", mve.getClass().getName()); + } + + } + + @Test + public void TestException4() { + String message = "Exception occured"; + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicDeadlockException(message, new Throwable()); + } + } catch (MusicDeadlockException mde) { + assertEquals("org.onap.music.exceptions.MusicDeadlockException", mde.getClass().getName()); + } + + } + + @Test + public void TestException5() { + String message = "Exception occured"; + boolean enableSuppression = true; + boolean writableStackTrace = false; + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicDeadlockException(message, new Throwable(), enableSuppression, + writableStackTrace); + } + } catch (MusicDeadlockException mde) { + assertEquals("org.onap.music.exceptions.MusicDeadlockException", mde.getClass().getName()); + } + + } + + @Test + public void TestSetValues() + { + MusicDeadlockException mde=new MusicDeadlockException(); + mde.setValues(owner,keyspace,table,key); + assertEquals("tester",mde.getOwner()); + assertEquals("testing",mde.getKeyspace()); + assertEquals("lockq",mde.getTable()); + assertEquals("test",mde.getKey()); + } +} diff --git a/music-core/src/test/java/org/onap/music/exceptions/MusicLockingExceptionTest.java b/music-core/src/test/java/org/onap/music/exceptions/MusicLockingExceptionTest.java new file mode 100644 index 00000000..583a9fd4 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/exceptions/MusicLockingExceptionTest.java @@ -0,0 +1,104 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 IBM Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.exceptions; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class MusicLockingExceptionTest { + + @Test + public void TestException1() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicLockingException(); + } + } catch (MusicLockingException mle) { + assertEquals("org.onap.music.exceptions.MusicLockingException", mle.getClass().getName()); + } + + } + + @Test + public void TestException2() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicLockingException("MusicLockingException Exception occured.."); + } + } catch (MusicLockingException mle) { + assertEquals(mle.getMessage(), "MusicLockingException Exception occured.."); + } + + } + + @Test + public void TestException3() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicLockingException(new Throwable()); + } + } catch (MusicLockingException mle) { + assertEquals("org.onap.music.exceptions.MusicLockingException", mle.getClass().getName()); + } + + } + + @Test + public void TestException4() { + String message = "Exception occured"; + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicLockingException(message, new Throwable()); + } + } catch (MusicLockingException mle) { + assertEquals("org.onap.music.exceptions.MusicLockingException", mle.getClass().getName()); + } + + } + + @Test + public void TestException5() { + String message = "Exception occured"; + boolean enableSuppression = true; + boolean writableStackTrace = false; + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicLockingException(message, new Throwable(), enableSuppression, writableStackTrace); + } + } catch (MusicLockingException mle) { + assertEquals("org.onap.music.exceptions.MusicLockingException", mle.getClass().getName()); + } + + } + +} diff --git a/music-core/src/test/java/org/onap/music/exceptions/MusicPolicyVoilationExceptionTest.java b/music-core/src/test/java/org/onap/music/exceptions/MusicPolicyVoilationExceptionTest.java new file mode 100644 index 00000000..22e2d728 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/exceptions/MusicPolicyVoilationExceptionTest.java @@ -0,0 +1,106 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 IBM Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.exceptions; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class MusicPolicyVoilationExceptionTest { + + @Test + public void TestException1() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicPolicyVoilationException(); + } + } catch (MusicPolicyVoilationException mve) { + assertEquals("org.onap.music.exceptions.MusicPolicyVoilationException", mve.getClass().getName()); + } + + } + + @Test + public void TestException2() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicPolicyVoilationException("MusicPolicyVoilationException Exception occured.."); + } + } catch (MusicPolicyVoilationException mve) { + assertEquals(mve.getMessage(), "MusicPolicyVoilationException Exception occured.."); + } + + } + + @Test + public void TestException3() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicPolicyVoilationException(new Throwable()); + } + } catch (MusicPolicyVoilationException mve) { + assertEquals("org.onap.music.exceptions.MusicPolicyVoilationException", mve.getClass().getName()); + } + + } + + @Test + public void TestException4() { + String message = "Exception occured"; + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicPolicyVoilationException(message, new Throwable()); + } + } catch (MusicPolicyVoilationException mve) { + assertEquals("org.onap.music.exceptions.MusicPolicyVoilationException", mve.getClass().getName()); + } + + } + + @Test + public void TestException5() { + String message = "Exception occured"; + boolean enableSuppression = true; + boolean writableStackTrace = false; + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicPolicyVoilationException(message, new Throwable(), enableSuppression, + writableStackTrace); + } + } catch (MusicPolicyVoilationException mve) { + assertEquals("org.onap.music.exceptions.MusicPolicyVoilationException", mve.getClass().getName()); + } + + } + +} diff --git a/music-core/src/test/java/org/onap/music/exceptions/MusicQueryExceptionTest.java b/music-core/src/test/java/org/onap/music/exceptions/MusicQueryExceptionTest.java new file mode 100644 index 00000000..9096506a --- /dev/null +++ b/music-core/src/test/java/org/onap/music/exceptions/MusicQueryExceptionTest.java @@ -0,0 +1,118 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 IBM Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.exceptions; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class MusicQueryExceptionTest { + + @Test + public void TestException1() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicQueryException(); + } + } catch (MusicQueryException mqe) { + assertEquals("org.onap.music.exceptions.MusicQueryException", mqe.getClass().getName()); + } + + } + + @Test + public void TestException2() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicQueryException("MusicQueryException Exception occured.."); + } + } catch (MusicQueryException mqe) { + assertEquals(mqe.getMessage(), "MusicQueryException Exception occured.."); + } + + } + + @Test + public void TestException3() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicQueryException("MusicQueryException Exception occured..", 001); + } + } catch (MusicQueryException mqe) { + assertEquals(mqe.getMessage(), "MusicQueryException Exception occured.."); + } + + } + + @Test + public void TestException4() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicQueryException(new Throwable()); + } + } catch (MusicQueryException mqe) { + assertEquals("org.onap.music.exceptions.MusicQueryException", mqe.getClass().getName()); + } + + } + + @Test + public void TestException5() { + String message = "Exception occured"; + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicQueryException(message, new Throwable()); + } + } catch (MusicQueryException mqe) { + assertEquals("org.onap.music.exceptions.MusicQueryException", mqe.getClass().getName()); + } + + } + + @Test + public void TestException6() { + String message = "Exception occured"; + boolean enableSuppression = true; + boolean writableStackTrace = false; + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicQueryException(message, new Throwable(), enableSuppression, writableStackTrace); + } + } catch (MusicQueryException mqe) { + assertEquals("org.onap.music.exceptions.MusicQueryException", mqe.getClass().getName()); + } + + } + +} diff --git a/music-core/src/test/java/org/onap/music/exceptions/MusicServiceExceptionTest.java b/music-core/src/test/java/org/onap/music/exceptions/MusicServiceExceptionTest.java new file mode 100644 index 00000000..bf056b61 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/exceptions/MusicServiceExceptionTest.java @@ -0,0 +1,145 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 IBM Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.exceptions; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class MusicServiceExceptionTest { + @Test + public void TestException1() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicServiceException(); + } + } catch (MusicServiceException mse) { + assertEquals("org.onap.music.exceptions.MusicServiceException", mse.getClass().getName()); + } + + } + + @Test + public void TestException2() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicServiceException("MusicServiceException Exception occured.."); + } + } catch (MusicServiceException mse) { + assertEquals(mse.getMessage(), "MusicServiceException Exception occured.."); + } + + } + + @Test + public void TestException3() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicServiceException("MusicServiceException Exception occured..", 001); + } + } catch (MusicServiceException mse) { + assertEquals(mse.getMessage(), "MusicServiceException Exception occured.."); + } + + } + + @Test + public void TestException4() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicServiceException("MusicServiceException Exception occured..", 001, "errorMsg"); + } + } catch (MusicServiceException mse) { + assertEquals(mse.getMessage(), "MusicServiceException Exception occured.."); + } + + } + + @Test + public void TestException5() { + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicServiceException(new Throwable()); + } + } catch (MusicServiceException mse) { + assertEquals("org.onap.music.exceptions.MusicServiceException", mse.getClass().getName()); + } + + } + + @Test + public void TestException6() { + String message = "Exception occured"; + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicServiceException(message, new Throwable()); + } + } catch (MusicServiceException mse) { + assertEquals("org.onap.music.exceptions.MusicServiceException", mse.getClass().getName()); + } + + } + + @Test + public void TestException7() { + String message = "Exception occured"; + boolean enableSuppression = true; + boolean writableStackTrace = false; + String s1 = "Value1"; + String s2 = "value2"; + try { + if (!s1.equalsIgnoreCase(s2)) { + throw new MusicServiceException(message, new Throwable(), enableSuppression, writableStackTrace); + } + } catch (MusicServiceException mse) { + assertEquals("org.onap.music.exceptions.MusicServiceException", mse.getClass().getName()); + } + + } + + @Test + public void testErrorCode() { + MusicServiceException musicServiceException = new MusicServiceException(); + musicServiceException.setErrorCode(0001); + assertEquals(0001, musicServiceException.getErrorCode()); + } + + @Test + public void testSetErrorMsg() { + MusicServiceException musicServiceException = new MusicServiceException(); + musicServiceException.setErrorMessage("errorMsg"); + assertEquals("errorMsg", musicServiceException.getErrorMessage()); + } + +} diff --git a/music-core/src/test/java/org/onap/music/lockingservice/cassandra/CassaLockStoreTest.java b/music-core/src/test/java/org/onap/music/lockingservice/cassandra/CassaLockStoreTest.java new file mode 100644 index 00000000..a608a970 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/lockingservice/cassandra/CassaLockStoreTest.java @@ -0,0 +1,311 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.lockingservice.cassandra; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import java.util.Iterator; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.music.datastore.MusicDataStore; +import org.onap.music.exceptions.MusicLockingException; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.DeadlockDetectionUtil; +import com.datastax.driver.core.ConsistencyLevel; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.WriteType; +import com.datastax.driver.core.exceptions.WriteTimeoutException; + +public class CassaLockStoreTest { + + private CassaLockStore cassaLockStore; + private CassaLockStore.LockObject lockObject; + private MusicDataStore dsHandle; + + @Before + public void setUp() { + dsHandle = Mockito.mock(MusicDataStore.class); + cassaLockStore = new CassaLockStore(dsHandle); + lockObject = cassaLockStore.new LockObject(false, null, null, null, null, null); + } + + @Test + public void testLockOwner() { + lockObject.setIsLockOwner(true); + assertEquals(true, lockObject.getIsLockOwner()); + + lockObject.setIsLockOwner(false); + assertEquals(false, lockObject.getIsLockOwner()); + } + + @Test + public void testAcquireTime() { + lockObject.setAcquireTime("2019-11-11T15:42:12+00:00"); + assertEquals("2019-11-11T15:42:12+00:00", lockObject.getAcquireTime()); + } + + @Test + public void testCreateTime() { + lockObject.setCreateTime("2019-11-11T15:43:44+00:00"); + assertEquals("2019-11-11T15:43:44+00:00", lockObject.getCreateTime()); + } + + @Test + public void testLockRef() { + lockObject.setLockRef("LockReference"); + assertEquals("LockReference", lockObject.getLockRef()); + } + + @Test + public void testLockType() { + lockObject.setLocktype(LockType.READ); + assertEquals(LockType.READ, lockObject.getLocktype()); + } + + @Test + public void testOwner() { + lockObject.setOwner("Owner"); + assertEquals("Owner", lockObject.getOwner()); + } + + @Test + public void testCreateLockQueue() { + try { + Mockito.when(dsHandle.executePut(Mockito.any(), Mockito.any())).thenReturn(true); + assertEquals(true, cassaLockStore.createLockQueue("keyspace1", "table1")); + } catch (MusicServiceException | MusicQueryException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testGenLockRefandEnQueue() { + ResultSet resultSetMock = Mockito.mock(ResultSet.class); + List<Row> latestGuardRow = Mockito.mock(List.class); + Mockito.when(latestGuardRow.isEmpty()).thenReturn(false); + Row row = Mockito.mock(Row.class); + Mockito.when(latestGuardRow.get(0)).thenReturn(row); + Mockito.when(row.getLong(0)).thenReturn((long) 4); + Mockito.when(resultSetMock.all()).thenReturn(latestGuardRow); + try { + Mockito.when(dsHandle.executeOneConsistencyGet(Mockito.any())).thenReturn(resultSetMock); + Mockito.when(dsHandle.executePut(Mockito.any(), Mockito.any())).thenReturn(true); + assertEquals("$keyspace2.table2.lockName2$5", + cassaLockStore.genLockRefandEnQueue("keyspace2", "table2", "lockName2", LockType.READ, "owner2")); + } catch (MusicServiceException | MusicQueryException | MusicLockingException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testGetLockQueue() { + ResultSet resultSetMock = Mockito.mock(ResultSet.class); + Iterator<Row> iterator = Mockito.mock(Iterator.class); + Mockito.when(iterator.hasNext()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false); + Row row = Mockito.mock(Row.class); + Mockito.when(row.getLong("lockReference")).thenReturn((long)1).thenReturn((long)2).thenReturn((long)3); + Mockito.when(row.get("lockType", LockType.class)).thenReturn(LockType.WRITE).thenReturn(LockType.WRITE).thenReturn(LockType.WRITE); + Mockito.when(iterator.next()).thenReturn(row).thenReturn(row).thenReturn(row); + Mockito.when(resultSetMock.iterator()).thenReturn(iterator); + + try { + Mockito.when(dsHandle.executeOneConsistencyGet(Mockito.any())).thenReturn(resultSetMock); + assertEquals("2", cassaLockStore.getLockQueue("keyspace2", "table2", "key2").get(1)); + } catch (MusicServiceException | MusicQueryException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testGetLockQueueSize() { + ResultSet resultSetMock = Mockito.mock(ResultSet.class); + Row row = Mockito.mock(Row.class); + Mockito.when(resultSetMock.one()).thenReturn(row); + Mockito.when(row.getLong("count")).thenReturn((long) 6); + try { + Mockito.when(dsHandle.executeOneConsistencyGet(Mockito.any())).thenReturn(resultSetMock); + assertEquals(6, cassaLockStore.getLockQueueSize("keyspace3", "table3", "key3")); + } catch (MusicServiceException | MusicQueryException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testPeekLockQueue() { + ResultSet resultSetMock = Mockito.mock(ResultSet.class); + Row row = Mockito.mock(Row.class); + Mockito.when(row.isNull("lockReference")).thenReturn(false); + Mockito.when(row.getLong("lockReference")).thenReturn((long) 6); + Mockito.when(row.getString("createTime")).thenReturn("2019-11-13T15:05:45+00:00"); + Mockito.when(row.getString("acquireTime")).thenReturn("2019-11-13T15:05:45+00:00"); + Mockito.when(row.isNull("lockReference")).thenReturn(false); + Mockito.when(resultSetMock.one()).thenReturn(row); + try { + Mockito.when(dsHandle.executeOneConsistencyGet(Mockito.any())).thenReturn(resultSetMock); + assertEquals("6", cassaLockStore.peekLockQueue("keyspace4", "table4", "key4").getLockRef()); + } catch (MusicServiceException | MusicQueryException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testGetCurrentLockHolders() { + ResultSet resultSetMock = Mockito.mock(ResultSet.class); + Iterator<Row> iterator = Mockito.mock(Iterator.class); + Mockito.when(iterator.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false); + Row row = Mockito.mock(Row.class); + Mockito.when(row.getLong("lockReference")).thenReturn((long) 5).thenReturn((long) 5); + Mockito.when(row.get("lockType", LockType.class)).thenReturn(LockType.WRITE); + Mockito.when(iterator.next()).thenReturn(row).thenReturn(row); + Mockito.when(resultSetMock.iterator()).thenReturn(iterator); + try { + Mockito.when(dsHandle.executeOneConsistencyGet(Mockito.any())).thenReturn(resultSetMock); + assertEquals("$keyspace5.table5.key5$5", cassaLockStore.getCurrentLockHolders("keyspace5", "table5", "key5").get(1)); + } catch (MusicServiceException | MusicQueryException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testIsLockOwner() { + ResultSet resultSetMock = Mockito.mock(ResultSet.class); + Iterator<Row> iterator = Mockito.mock(Iterator.class); + Mockito.when(iterator.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false); + Row row = Mockito.mock(Row.class); + Mockito.when(row.getLong("lockReference")).thenReturn((long) 5); + Mockito.when(row.get("lockType", LockType.class)).thenReturn(LockType.WRITE); + Mockito.when(iterator.next()).thenReturn(row).thenReturn(row); + Mockito.when(resultSetMock.iterator()).thenReturn(iterator); + try { + Mockito.when(dsHandle.executeOneConsistencyGet(Mockito.any())).thenReturn(resultSetMock); + assertEquals(true, cassaLockStore.isLockOwner("keyspace5", "table5", "key5", "5")); + } catch (MusicServiceException | MusicQueryException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testGetLockInfo() { + ResultSet resultSetMock = Mockito.mock(ResultSet.class); + Row row = Mockito.mock(Row.class); + Mockito.when(row.isNull("lockReference")).thenReturn(false); + Mockito.when(row.getLong("lockReference")).thenReturn((long) 6); + Mockito.when(row.getString("createTime")).thenReturn("2019-11-13T15:05:45+00:00"); + Mockito.when(row.getString("acquireTime")).thenReturn("2019-11-13T15:05:45+00:00"); + LockType locktype = Mockito.mock(LockType.class); + Mockito.when(row.get("lockType", LockType.class)).thenReturn(locktype); + Mockito.when(row.getString("owner")).thenReturn("owner6"); + Mockito.when(resultSetMock.one()).thenReturn(row); + + try { + Mockito.when(dsHandle.executeOneConsistencyGet(Mockito.any())).thenReturn(resultSetMock); + CassaLockStore csLockStore = Mockito.spy(cassaLockStore); + Mockito.doReturn(true).when(csLockStore).isLockOwner(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any()); + assertEquals("6", csLockStore.getLockInfo("keyspace6", "table6", "key6", "6").getLockRef()); + } catch (MusicServiceException | MusicQueryException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testCheckForDeadlock() { + DeadlockDetectionUtil ddu = Mockito.mock(DeadlockDetectionUtil.class); + ResultSet resultSetMock = Mockito.mock(ResultSet.class); + Iterator<Row> it = Mockito.mock(Iterator.class); + Row row = Mockito.mock(Row.class); + Mockito.when(it.hasNext()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false); + Mockito.when(row.getString("key")).thenReturn("key8"); + Mockito.when(row.getString("owner")).thenReturn("owner8"); + Mockito.when(row.getString("acquiretime")).thenReturn("1"); + Mockito.when(it.next()).thenReturn(row).thenReturn(row).thenReturn(row); + Mockito.when(resultSetMock.iterator()).thenReturn(it); + CassaLockStore csLockStore = Mockito.spy(cassaLockStore); + Mockito.doReturn(ddu).when(csLockStore).getDeadlockDetectionUtil(); + Mockito.when(ddu.checkForDeadlock(Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(true); + try { + Mockito.when(dsHandle.executeLocalQuorumConsistencyGet(Mockito.any())).thenReturn(resultSetMock); + assertEquals(false, + cassaLockStore.checkForDeadlock("keyspace8", "table8", "lockName8", LockType.WRITE, "owner8", true)); + } catch (MusicServiceException | MusicQueryException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testGetAllLocksForOwner() { + ResultSet resultSetMock = Mockito.mock(ResultSet.class); + Iterator<Row> it = Mockito.mock(Iterator.class); + Mockito.when(it.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false); + Row row = Mockito.mock(Row.class); + Mockito.when(row.getString("key")).thenReturn("key10"); + Mockito.when(row.getLong("lockreference")).thenReturn((long) 10); + Mockito.when(it.next()).thenReturn(row); + Mockito.when(resultSetMock.iterator()).thenReturn(it); + try { + Mockito.when(dsHandle.executeQuorumConsistencyGet(Mockito.any())).thenReturn(resultSetMock); + assertEquals("key10$10", cassaLockStore.getAllLocksForOwner("owneer10", "keyspace10", "table10").get(1)); + } catch (MusicServiceException | MusicQueryException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testDequeueLockRef() throws Exception { + cassaLockStore.deQueueLockRef("keyspace1", "table1", "key6", "6", 2); + + // note only expecting 1 call to this instance, expecting it to succeed + Mockito.verify(dsHandle, Mockito.times(1)).executePut(Mockito.any(), Mockito.anyString()); + } + + @Test + public void testDequeueLockRefWriteTimeout() throws Exception { + int retryCount = 22; + try { + Mockito.when(dsHandle.executePut(Mockito.any(), Mockito.anyString())) + .thenThrow(new MusicServiceException("Cassandra timeout during...")); + cassaLockStore.deQueueLockRef("keyspace1", "table1", "key6", "6", retryCount); + + // Should never reach here + fail(); + } catch (MusicServiceException | MusicQueryException | MusicLockingException e) { + // should throw an error + } + + Mockito.verify(dsHandle, Mockito.times(retryCount)).executePut(Mockito.any(), Mockito.anyString()); + } +} diff --git a/music-core/src/test/java/org/onap/music/lockingservice/cassandra/MusicLockStateTest.java b/music-core/src/test/java/org/onap/music/lockingservice/cassandra/MusicLockStateTest.java new file mode 100644 index 00000000..e5b655bd --- /dev/null +++ b/music-core/src/test/java/org/onap/music/lockingservice/cassandra/MusicLockStateTest.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + *******************************************************************************/ + +package org.onap.music.lockingservice.cassandra; + +import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Test; +import org.onap.music.lockingservice.cassandra.MusicLockState.LockStatus; + +public class MusicLockStateTest { + + MusicLockState musicLockState; + + @Before + public void setup() { + musicLockState = new MusicLockState(LockStatus.LOCKED, "", true); + } + + @Test + public void testGetLeasePeriod() { + musicLockState.setLeasePeriod(200L); + assertEquals(200L, musicLockState.getLeasePeriod()); + } + + @Test + public void testIsNeedToSyncQuorum() { + assertEquals(true, musicLockState.isNeedToSyncQuorum()); + } + + @Test + public void testGetLeaseStartTime() { + musicLockState.setLeaseStartTime(200L); + assertEquals(200L, musicLockState.getLeaseStartTime()); + } + + @Test + public void testGetLockStatus() { + musicLockState.setLockStatus(LockStatus.LOCKED); + assertEquals(LockStatus.LOCKED, musicLockState.getLockStatus()); + } + + @Test + public void testGetLockHolder() { + musicLockState.setLockHolder("lockHolder"); + assertEquals("lockHolder", musicLockState.getLockHolder()); + } + + @Test + public void testGetErrorMessage() { + MusicLockState musicLockState2 = new MusicLockState("This is error message"); + assertEquals("This is error message", musicLockState2.getErrorMessage()); + } + + @Test + public void testSerialize() { + byte[] serializedBytes = musicLockState.serialize(); + MusicLockState musicLockState3 = musicLockState.deSerialize(serializedBytes); + assertEquals(musicLockState.getLeasePeriod(),musicLockState3.getLeasePeriod()); + assertEquals(musicLockState.isNeedToSyncQuorum(),musicLockState3.isNeedToSyncQuorum()); + assertEquals(musicLockState.getLeaseStartTime(),musicLockState3.getLeaseStartTime()); + assertEquals(musicLockState.getLockStatus(),musicLockState3.getLockStatus()); + assertEquals(musicLockState.getLockHolder(),musicLockState3.getLockHolder()); + assertEquals(musicLockState.getErrorMessage(),musicLockState3.getErrorMessage()); + } + +} diff --git a/music-core/src/test/java/org/onap/music/main/CipherUtilTest.java b/music-core/src/test/java/org/onap/music/main/CipherUtilTest.java new file mode 100644 index 00000000..ff187ffd --- /dev/null +++ b/music-core/src/test/java/org/onap/music/main/CipherUtilTest.java @@ -0,0 +1,55 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 IBM Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.main; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +public class CipherUtilTest { + + private CipherUtil cipherUtil; + + @Before + public void setup() { + cipherUtil = new CipherUtil(); + } + + @Test + public void testEncryptPKC() { + String encryptedText = CipherUtil.encryptPKC("This is another string to be encrypted", + "4BFF9DCCD774F3650E20C4D3F69F8C99"); + System.out.println("*************************" + encryptedText); + assertEquals(88, encryptedText.length()); + } + + @Test + public void testDecryptPKC() { + String encryptedText = CipherUtil.encryptPKC("This is another string to be encrypted", + "4BFF9DCCD774F3650E20C4D3F69F8C99"); + assertEquals("This is another string to be encrypted", + CipherUtil.decryptPKC(encryptedText, "4BFF9DCCD774F3650E20C4D3F69F8C99")); + } + +} diff --git a/music-core/src/test/java/org/onap/music/main/DeadlockDetectionUtilTest.java b/music-core/src/test/java/org/onap/music/main/DeadlockDetectionUtilTest.java new file mode 100644 index 00000000..ab767e17 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/main/DeadlockDetectionUtilTest.java @@ -0,0 +1,87 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 IBM Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.main; + +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import org.junit.Before; +import org.junit.Test; +//import org.junit.experimental.runners.Enclosed; +//import org.junit.runner.RunWith; +import org.onap.music.main.DeadlockDetectionUtil.OwnershipType; + +//@RunWith(Enclosed.class) +public class DeadlockDetectionUtilTest { + private DeadlockDetectionUtil ddu; + + @Before + public void setup() { + ddu = new DeadlockDetectionUtil(); + } + + @Test + public void testListAllNodes() { + ddu = new DeadlockDetectionUtil(); + ddu.setExisting("r1", "o2", OwnershipType.ACQUIRED); + ddu.setExisting("r3", "o2", OwnershipType.ACQUIRED); + + ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + System.setOut(new PrintStream(outContent)); + ddu.listAllNodes(); + + /* + * String expectedOutput = "In DeadlockDetectionUtil: \n" + + * " o2 : Node [id=o2, links=r3, visited=false, onStack=false]\n" + + * " r3 : Node [id=r3, links=, visited=false, onStack=false]\n" + + * " r1 : Node [id=r1, links=o2, visited=false, onStack=false]\n"; + * assertEquals(expectedOutput, outContent.toString()); + * + * ddu = new DeadlockDetectionUtil(); ddu.setExisting("111", "222", + * OwnershipType.CREATED); ddu.setExisting("333", "222", OwnershipType.CREATED); + * outContent = new ByteArrayOutputStream(); System.setOut(new + * PrintStream(outContent)); ddu.listAllNodes(); expectedOutput = + * "In DeadlockDetectionUtil: \n" + + * " o222 : Node [id=o222, links=r111r333, visited=false, onStack=false]\n" + + * " r333 : Node [id=r333, links=, visited=false, onStack=false]\n" + + * " r111 : Node [id=r111, links=, visited=false, onStack=false]"; + * assertEquals(expectedOutput, outContent.toString()); + */ + } + + @Test + public void testcheckForDeadlock() { + ddu = new DeadlockDetectionUtil(); + ddu.setExisting("111", "222", DeadlockDetectionUtil.OwnershipType.ACQUIRED); + ddu.setExisting("333", "444", DeadlockDetectionUtil.OwnershipType.ACQUIRED); + assertEquals(false, ddu.checkForDeadlock("111", "444", DeadlockDetectionUtil.OwnershipType.CREATED)); + + ddu = new DeadlockDetectionUtil(); + ddu.setExisting("111", "222", DeadlockDetectionUtil.OwnershipType.ACQUIRED); + ddu.setExisting("333", "444", DeadlockDetectionUtil.OwnershipType.ACQUIRED); + ddu.setExisting("333", "222", DeadlockDetectionUtil.OwnershipType.CREATED); + assertEquals(true, ddu.checkForDeadlock("111", "444", DeadlockDetectionUtil.OwnershipType.CREATED)); + } +} diff --git a/music-core/src/test/java/org/onap/music/main/MusicCoreTest.java b/music-core/src/test/java/org/onap/music/main/MusicCoreTest.java new file mode 100644 index 00000000..4714778b --- /dev/null +++ b/music-core/src/test/java/org/onap/music/main/MusicCoreTest.java @@ -0,0 +1,391 @@ +/******************************************************************************* + * ============LICENSE_START========================================== org.onap.music + * =================================================================== Copyright (c) 2019 AT&T + * Intellectual Property =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + *******************************************************************************/ + +package org.onap.music.main; + +import static org.junit.Assert.assertEquals; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.ws.rs.core.MultivaluedMap; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.internal.util.reflection.FieldSetter; +import org.onap.music.datastore.Condition; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonDelete; +import org.onap.music.datastore.jsonobjects.JsonIndex; +import org.onap.music.datastore.jsonobjects.JsonInsert; +import org.onap.music.datastore.jsonobjects.JsonKeySpace; +import org.onap.music.datastore.jsonobjects.JsonSelect; +import org.onap.music.datastore.jsonobjects.JsonTable; +import org.onap.music.datastore.jsonobjects.JsonUpdate; +import org.onap.music.exceptions.MusicLockingException; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.lockingservice.cassandra.CassaLockStore; +import org.onap.music.lockingservice.cassandra.LockType; +import org.onap.music.lockingservice.cassandra.MusicLockState; +import org.onap.music.service.MusicCoreService; +import com.datastax.driver.core.ResultSet; + +public class MusicCoreTest { + + MusicCore mCore; + MusicCoreService musicCore; + CassaLockStore mLockHandle; + + @Before + public void setup() { + mCore = new MusicCore(); + musicCore = Mockito.mock(MusicCoreService.class); + mLockHandle = Mockito.mock(CassaLockStore.class); + try { + FieldSetter.setField(mCore, mCore.getClass().getDeclaredField("musicCore"), musicCore); + } catch (NoSuchFieldException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testAcquireLock() throws MusicLockingException, MusicQueryException, MusicServiceException { + ReturnType returnType = Mockito.mock(ReturnType.class); + ReturnType result = null; + Mockito.when(musicCore.acquireLock(Mockito.any(), Mockito.any())).thenReturn(returnType); + result = MusicCore.acquireLock("key1", "lockid1"); + assertEquals(returnType, result); + } + + @Test + public void testacquireLockWithLease() throws MusicLockingException, MusicQueryException, MusicServiceException { + ReturnType returnType = Mockito.mock(ReturnType.class); + ReturnType result = null; + Mockito.when(musicCore.acquireLockWithLease(Mockito.anyString(), Mockito.anyString(), Mockito.anyLong())) + .thenReturn(returnType); + result = MusicCore.acquireLockWithLease("key1", "lockid1", 100L); + assertEquals(returnType, result); + } + + @Test + public void testCreateLockReferenceAtomic() throws MusicLockingException { + String result = null; + Mockito.when(musicCore.createLockReferenceAtomic(Mockito.any())).thenReturn("lockreference1"); + result = MusicCore.createLockReferenceAtomic("key2"); + assertEquals("lockreference1", result); + } + + @Test + public void testCreateLockReference() throws MusicLockingException { + String result = null; + Mockito.when(musicCore.createLockReference(Mockito.any(), Mockito.any())).thenReturn("lockreference2"); + result = MusicCore.createLockReference("key3", "owner3"); + assertEquals("lockreference2", result); + } + + @Test + public void testCreateLockReferenceAtomic2() throws MusicLockingException { + String result = null; + Mockito.when(musicCore.createLockReferenceAtomic(Mockito.any(), Mockito.any())).thenReturn("lockreference3"); + result = MusicCore.createLockReferenceAtomic("key4", LockType.READ); + assertEquals("lockreference3", result); + } + + @Test + public void testCreateLockReference2() throws MusicLockingException { + String result = null; + Mockito.when(musicCore.createLockReference(Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn("lockreference4"); + result = MusicCore.createLockReference("key4", LockType.READ, "owner4"); + assertEquals("lockreference4", result); + } + + @Test + public void testCreateTable() throws MusicServiceException { + ResultType resultType = Mockito.mock(ResultType.class); + ResultType result = null; + Mockito.when(musicCore.createTable(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(resultType); + result = MusicCore.createTable("keyspace1", "table1", new PreparedQueryObject(), "consistency"); + assertEquals(resultType, result); + } + + @Test + public void testQuorumGet() { + ResultSet rs = Mockito.mock(ResultSet.class); + Mockito.when(musicCore.quorumGet(Mockito.any())).thenReturn(rs); + assertEquals(rs, MusicCore.quorumGet(new PreparedQueryObject())); + } + + @Test + public void testWhoseTurnIsIt() { + Mockito.when(musicCore.whoseTurnIsIt(Mockito.any())).thenReturn("turn"); + assertEquals("turn", MusicCore.whoseTurnIsIt("key5")); + } + + @Test + public void testGetCurrentLockHolders() { + List<String> result = Mockito.mock(List.class); + Mockito.when(musicCore.getCurrentLockHolders(Mockito.any())).thenReturn(result); + assertEquals(result, MusicCore.getCurrentLockHolders("key6")); + } + + @Test + public void testPromoteLock() throws MusicLockingException { + ReturnType returnType = Mockito.mock(ReturnType.class); + ReturnType result = null; + Mockito.when(musicCore.promoteLock(Mockito.any())).thenReturn(returnType); + result = MusicCore.promoteLock("lockid2"); + assertEquals(returnType, result); + } + + @Test + public void testEventualPut() { + ReturnType returnType = Mockito.mock(ReturnType.class); + Mockito.when(musicCore.eventualPut(Mockito.any())).thenReturn(returnType); + assertEquals(returnType, MusicCore.eventualPut(new PreparedQueryObject())); + } + + @Test + public void testEventualPut_nb() { + ReturnType returnType = Mockito.mock(ReturnType.class); + Mockito.when(musicCore.eventualPut_nb(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(returnType); + assertEquals(returnType, + MusicCore.eventualPut_nb(new PreparedQueryObject(), "keyspace2", "table2", "primarykey1")); + } + + @Test + public void testCriticalPut() { + ReturnType returnType = Mockito.mock(ReturnType.class); + Mockito.when(musicCore.criticalPut(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), + Mockito.any())).thenReturn(returnType); + assertEquals(returnType, MusicCore.criticalPut("keyspace3", "table3", "primarykey2", new PreparedQueryObject(), + "lockreference2", new Condition(new HashMap(), new PreparedQueryObject()))); + } + + @Test + public void testNonKeyRelatedPut() throws MusicServiceException, MusicQueryException { + ResultType resultType = Mockito.mock(ResultType.class); + ResultType result = null; + Mockito.when(musicCore.nonKeyRelatedPut(Mockito.any(), Mockito.any())).thenReturn(resultType); + result = MusicCore.nonKeyRelatedPut(new PreparedQueryObject(), "consistency2"); + assertEquals(resultType, result); + } + + @Test + public void testGet() throws MusicServiceException { + ResultSet rs = Mockito.mock(ResultSet.class); + ResultSet result = null; + Mockito.when(musicCore.get(Mockito.any())).thenReturn(rs); + result = MusicCore.get(new PreparedQueryObject()); + assertEquals(rs, result); + } + + @Test + public void testCriticalGet() throws MusicServiceException { + ResultSet rs = Mockito.mock(ResultSet.class); + ResultSet result = null; + Mockito.when(musicCore.criticalGet(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(rs); + result = MusicCore.criticalGet("keyspace4", "table4", "primarykey3", new PreparedQueryObject(), + "lockreference3"); + assertEquals(rs, result); + } + + @Test + public void testAtomicPut() throws MusicLockingException, MusicQueryException, MusicServiceException { + ReturnType returnType = Mockito.mock(ReturnType.class); + ReturnType result = null; + Mockito.when(musicCore.atomicPut(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(returnType); + result = MusicCore.atomicPut("keyspace5", "table5", "primarykey4", new PreparedQueryObject(), + new Condition(new HashMap(), new PreparedQueryObject())); + assertEquals(returnType, result); + } + + @Test + public void testAtomicGet() throws MusicServiceException, MusicLockingException, MusicQueryException { + ResultSet rs = Mockito.mock(ResultSet.class); + ResultSet result = null; + Mockito.when(musicCore.atomicGet(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(rs); + result = MusicCore.atomicGet("keyspace5", "table5", "primarykey4", new PreparedQueryObject()); + assertEquals(rs, result); + } + + @Test + public void testGetLockQueue() throws MusicServiceException, MusicQueryException, MusicLockingException { + List<String> result = Mockito.mock(List.class); + List<String> rst = null; + Mockito.when(musicCore.getLockQueue(Mockito.any())).thenReturn(result); + rst = MusicCore.getLockQueue("key5"); + assertEquals(result, rst); + } + + @Test + public void testGetLockQueueSize() throws MusicServiceException, MusicQueryException, MusicLockingException { + long result = 0L; + Mockito.when(musicCore.getLockQueueSize(Mockito.any())).thenReturn(100L); + result = MusicCore.getLockQueueSize("key6"); + assertEquals(100L, result); + } + + @Test + public void testatomicPutWithDeleteLock() throws MusicLockingException { + ReturnType returnType = Mockito.mock(ReturnType.class); + ReturnType result = null; + Mockito.when(musicCore.atomicPutWithDeleteLock(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), + Mockito.any())).thenReturn(returnType); + result = MusicCore.atomicPutWithDeleteLock("keyspace5", "table5", "primarykey4", new PreparedQueryObject(), + new Condition(new HashMap(), new PreparedQueryObject())); + assertEquals(returnType, result); + } + + @Test + public void testAtomicGetWithDeleteLock() throws MusicServiceException, MusicLockingException { + ResultSet rs = Mockito.mock(ResultSet.class); + ResultSet result = null; + Mockito.when(musicCore.atomicGetWithDeleteLock(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(rs); + result = MusicCore.atomicGetWithDeleteLock("keyspace5", "table5", "primarykey4", new PreparedQueryObject()); + assertEquals(rs, result); + } + + @Test + public void testValidateLock() { + Map<String, Object> map = Mockito.mock(Map.class); + Mockito.when(musicCore.validateLock(Mockito.any())).thenReturn(map); + assertEquals(map, MusicCore.validateLock("lockname")); + } + + @Test + public void testReleaseLock() throws MusicLockingException { + MusicLockState musicLockState = Mockito.mock(MusicLockState.class); + MusicLockState result = null; + Mockito.when(musicCore.releaseLock(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(musicLockState); + result = MusicCore.releaseLock("lockid", true); + assertEquals(musicLockState, result); + } + + @Test + public void testReleaseAllLocksForOwner() throws MusicLockingException, MusicServiceException, MusicQueryException { + List<String> result = Mockito.mock(List.class); + List<String> rst = null; + Mockito.when(musicCore.releaseAllLocksForOwner(Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(result); + rst = MusicCore.releaseAllLocksForOwner("owner2", "keyspace6", "table6"); + assertEquals(result, rst); + } + + @Test + public void testCreateKeyspace() throws MusicServiceException, MusicQueryException { + ResultType resultType = Mockito.mock(ResultType.class); + ResultType result = null; + Mockito.when(musicCore.createKeyspace(Mockito.any(), Mockito.any())).thenReturn(resultType); + result = MusicCore.createKeyspace(new JsonKeySpace(), "consistency3"); + assertEquals(resultType, result); + } + + @Test + public void testDropKeyspace() throws MusicServiceException, MusicQueryException { + ResultType resultType = Mockito.mock(ResultType.class); + ResultType result = null; + Mockito.when(musicCore.dropKeyspace(Mockito.any(), Mockito.any())).thenReturn(resultType); + result = MusicCore.dropKeyspace(new JsonKeySpace(), "consistency4"); + assertEquals(resultType, result); + } + + @Test + public void testCreateTable2() throws MusicServiceException, MusicQueryException { + ResultType resultType = Mockito.mock(ResultType.class); + ResultType result = null; + Mockito.when(musicCore.createTable(Mockito.any(), Mockito.any())).thenReturn(resultType); + result = MusicCore.createTable(new JsonTable(), "consistency5"); + assertEquals(resultType, result); + } + + @Test + public void testDropTable() throws MusicServiceException, MusicQueryException { + ResultType resultType = Mockito.mock(ResultType.class); + ResultType result = null; + Mockito.when(musicCore.dropTable(Mockito.any(), Mockito.any())).thenReturn(resultType); + result = MusicCore.dropTable(new JsonTable(), "consistency5"); + assertEquals(resultType, result); + } + + @Test + public void testCreateIndex() throws MusicServiceException, MusicQueryException { + ResultType resultType = Mockito.mock(ResultType.class); + ResultType result = null; + Mockito.when(musicCore.createIndex(Mockito.any(), Mockito.any())).thenReturn(resultType); + result = MusicCore.createIndex(new JsonIndex("indexName", "keyspace7", "table7", "field"), "consistency6"); + assertEquals(resultType, result); + } + + @Test + public void testSelect() throws MusicServiceException, MusicQueryException { + ResultSet rs = Mockito.mock(ResultSet.class); + ResultSet result = null; + Mockito.when(musicCore.select(Mockito.any(), Mockito.any())).thenReturn(rs); + MultivaluedMap<String, String> map = Mockito.mock(MultivaluedMap.class); + result = MusicCore.select(new JsonSelect(), map); + assertEquals(rs, result); + } + + @Test + public void testSelectCritical() throws MusicLockingException, MusicQueryException, MusicServiceException { + ResultSet rs = Mockito.mock(ResultSet.class); + ResultSet result = null; + Mockito.when(musicCore.selectCritical(Mockito.any(), Mockito.any())).thenReturn(rs); + MultivaluedMap<String, String> map = Mockito.mock(MultivaluedMap.class); + result = MusicCore.selectCritical(new JsonInsert(), map); + assertEquals(rs, result); + } + + @Test + public void testInsertIntoTable() throws MusicLockingException, MusicQueryException, MusicServiceException { + ReturnType returnType = Mockito.mock(ReturnType.class); + ReturnType result = null; + Mockito.when(musicCore.insertIntoTable(Mockito.any())).thenReturn(returnType); + result = MusicCore.insertIntoTable(new JsonInsert()); + assertEquals(returnType, result); + } + + @Test + public void testUpdateTable() throws MusicLockingException, MusicQueryException, MusicServiceException { + ReturnType returnType = Mockito.mock(ReturnType.class); + ReturnType result = null; + Mockito.when(musicCore.updateTable(Mockito.any(), Mockito.any())).thenReturn(returnType); + MultivaluedMap<String, String> map = Mockito.mock(MultivaluedMap.class); + result = MusicCore.updateTable(new JsonUpdate(), map); + assertEquals(returnType, result); + } + + @Test + public void testDeleteFromTable() throws MusicLockingException, MusicQueryException, MusicServiceException { + ReturnType returnType = Mockito.mock(ReturnType.class); + ReturnType result = null; + MultivaluedMap<String, String> map = Mockito.mock(MultivaluedMap.class); + Mockito.when(musicCore.deleteFromTable(Mockito.any(), Mockito.any())).thenReturn(returnType); + result = MusicCore.deleteFromTable(new JsonDelete(), map); + assertEquals(returnType, result); + } +} diff --git a/music-core/src/test/java/org/onap/music/main/ResultTypeTest.java b/music-core/src/test/java/org/onap/music/main/ResultTypeTest.java new file mode 100644 index 00000000..d6ccc1f1 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/main/ResultTypeTest.java @@ -0,0 +1,42 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.main; + +import static org.junit.Assert.*; +import org.junit.Test; + +public class ResultTypeTest { + + @Test + public void testResultType() { + assertEquals("SUCCESS",ResultType.SUCCESS.name()); + assertEquals("FAILURE",ResultType.FAILURE.name()); + } + + @Test + public void testGetResult() { + assertEquals("Success",ResultType.SUCCESS.getResult()); + assertEquals("Failure",ResultType.FAILURE.getResult()); + } + +} diff --git a/music-core/src/test/java/org/onap/music/main/ReturnTypeTest.java b/music-core/src/test/java/org/onap/music/main/ReturnTypeTest.java new file mode 100644 index 00000000..fbb5f84d --- /dev/null +++ b/music-core/src/test/java/org/onap/music/main/ReturnTypeTest.java @@ -0,0 +1,82 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.main; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import org.junit.Test; + +public class ReturnTypeTest { + + @Test + public void testReturnType() { + ReturnType result = new ReturnType(ResultType.SUCCESS,"message"); + assertEquals(result.getMessage(),"message"); + assertEquals(result.getResult(),ResultType.SUCCESS); + } + + @Test + public void testTimingInfo() { + ReturnType result = new ReturnType(ResultType.SUCCESS,"message"); + result.setTimingInfo("123"); + assertEquals(result.getTimingInfo(),"123"); + } + + @Test + public void testGetResult() { + ReturnType result = new ReturnType(ResultType.FAILURE,"message"); + assertEquals(result.getResult(),ResultType.FAILURE); + } + + @Test + public void testGetMessage() { + ReturnType result = new ReturnType(ResultType.SUCCESS,"message"); + result.setMessage("NewMessage"); + assertEquals(result.getMessage(),"NewMessage"); + } + + @Test + public void testToJson() { + ReturnType result = new ReturnType(ResultType.SUCCESS,"message"); + String myJson = result.toJson(); + assertTrue(myJson.contains("message")); + } + + @Test + public void testToString() { + ReturnType result = new ReturnType(ResultType.SUCCESS,"message"); + String test = result.toString(); + assertTrue(test.contains("message")); + } + + @Test + public void testToMap() { + ReturnType result = new ReturnType(ResultType.SUCCESS,"message"); + Map<String, Object> myMap = result.toMap(); + assertTrue(myMap.containsKey("message")); + } + +} diff --git a/music-core/src/test/java/org/onap/music/service/impl/MusicCassaCoreTest.java b/music-core/src/test/java/org/onap/music/service/impl/MusicCassaCoreTest.java new file mode 100644 index 00000000..33debfaa --- /dev/null +++ b/music-core/src/test/java/org/onap/music/service/impl/MusicCassaCoreTest.java @@ -0,0 +1,485 @@ +/******************************************************************************* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2018 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + *******************************************************************************/ +package org.onap.music.service.impl; + +import static org.junit.Assert.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.onap.music.datastore.MusicDataStore; +import org.onap.music.datastore.MusicDataStoreHandle; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonKeySpace; +import org.onap.music.datastore.jsonobjects.JsonTable; +import org.onap.music.exceptions.MusicLockingException; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.lockingservice.cassandra.CassaLockStore; +import org.onap.music.lockingservice.cassandra.CassaLockStore.LockObject; +import org.onap.music.lockingservice.cassandra.LockType; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import org.onap.music.main.ReturnType; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; + +@RunWith(MockitoJUnitRunner.class) +public class MusicCassaCoreTest { + + @Mock + private CassaLockStore mLockHandle; + + @Mock + private MusicDataStore dsHandle; + + @Mock + private Session session; + + MusicCassaCore core; + + @Before + public void before() { + core = MusicCassaCore.getInstance(); + MusicCassaCore.setmLockHandle(mLockHandle); + MusicDataStoreHandle.setMDstoreHandle(dsHandle); + Mockito.when(dsHandle.getSession()).thenReturn(session); + } + + @Test + public void testGetmLockHandle() { + assertEquals(mLockHandle, MusicCassaCore.getmLockHandle()); + } + + @Test + public void testSetmLockHandle() { + CassaLockStore m2 = Mockito.mock(CassaLockStore.class); + MusicCassaCore.setmLockHandle(m2); + assertEquals(m2, MusicCassaCore.getmLockHandle()); + //revert back to original handle + MusicCassaCore.setmLockHandle(mLockHandle); + } + + @Test + public void testGetInstance() { + assertEquals(core, MusicCassaCore.getInstance()); + } + + @Test + public void testGetLockingServiceHandle() { + assertEquals(mLockHandle, MusicCassaCore.getmLockHandle()); + } + + @Test + public void testCreateLockReferenceAtomicString() throws Exception { + String fullyQualifiedKey = "keyspace.table.lockName"; + Mockito.when(mLockHandle.genLockRefandEnQueue("keyspace", "table", "lockName", LockType.WRITE, null)) + .thenReturn("lockReturned"); + + String lockRef = core.createLockReferenceAtomic(fullyQualifiedKey); + + Mockito.verify(mLockHandle).genLockRefandEnQueue("keyspace", "table", "lockName", LockType.WRITE, null); + assertEquals("lockReturned", lockRef); + } + + @Test + public void testCreateLockReferenceStringString() throws Exception { + String fullyQualifiedKey = "keyspace.table.lockName"; + String owner = "owner1"; + Mockito.when(mLockHandle.genLockRefandEnQueue("keyspace", "table", "lockName", LockType.WRITE, owner)) + .thenReturn("lockReturned"); + + String lockRef = core.createLockReference(fullyQualifiedKey, owner); + + Mockito.verify(mLockHandle).genLockRefandEnQueue("keyspace", "table", "lockName", LockType.WRITE, owner); + assertEquals("lockReturned", lockRef); + } + + @Test + public void testCreateLockReferenceAtomicStringLockType() throws Exception { + String fullyQualifiedKey = "keyspace.table.lockName"; + Mockito.when(mLockHandle.genLockRefandEnQueue("keyspace", "table", "lockName", LockType.READ, null)) + .thenReturn("lockReturned"); + + String lockRef = core.createLockReferenceAtomic(fullyQualifiedKey, LockType.READ); + + Mockito.verify(mLockHandle).genLockRefandEnQueue("keyspace", "table", "lockName", LockType.READ, null); + assertEquals("lockReturned", lockRef); + } + + @Test + public void testCreateLockReferenceStringLockTypeString() throws Exception { + String fullyQualifiedKey = "keyspace.table.lockName"; + String owner = "owner1"; + Mockito.when(mLockHandle.genLockRefandEnQueue("keyspace", "table", "lockName", LockType.READ, owner)) + .thenReturn("lockReturned"); + + String lockRef = core.createLockReference(fullyQualifiedKey, LockType.READ, owner); + + Mockito.verify(mLockHandle).genLockRefandEnQueue("keyspace", "table", "lockName", LockType.READ, owner); + assertEquals("lockReturned", lockRef); + } + + @Test + public void testPromoteLock() throws Exception { + String lockId = "$keyspace.table.lockName$1"; + Mockito.when(mLockHandle.promoteLock("keyspace", "table", "lockName", "1")) + .thenReturn(new ReturnType(ResultType.SUCCESS, "Lock Promoted")); + + ReturnType rt = core.promoteLock(lockId); + assertEquals(ResultType.SUCCESS, rt.getResult()); + assertEquals("Lock Promoted", rt.getMessage()); + } + + @Test + public void testAcquireLockWithLease() throws Exception { + String fullyQualifiedKey = "keyspace.table.lockName"; + String lockId = "$keyspace.table.lockName$1"; + long leasePeriod = 1000; + String currTime = String.valueOf(System.currentTimeMillis()); + Mockito.when(mLockHandle.peekLockQueue("keyspace", "table", "lockName")) + .thenReturn(mLockHandle.new LockObject(true, lockId, currTime, currTime, LockType.WRITE, null)); + Mockito.when(mLockHandle.getLockInfo("keyspace", "table", "lockName", "1")) + .thenReturn(mLockHandle.new LockObject(false, lockId, null, null, LockType.WRITE, null)); + + ReturnType rt = core.acquireLockWithLease(fullyQualifiedKey, lockId, leasePeriod); + assertEquals(ResultType.FAILURE, rt.getResult()); + } + + @Test + public void testAcquireLock() throws Exception { + String fullyQualifiedKey = "keyspace.table.lockName"; + String lockId = "$keyspace.table.lockName$1"; + Mockito.when(mLockHandle.getLockInfo("keyspace", "table", "lockName", "1")) + .thenReturn(mLockHandle.new LockObject(false, lockId, null, null, LockType.WRITE, null)); + + ReturnType rt = core.acquireLock(fullyQualifiedKey, lockId); + + assertEquals(ResultType.FAILURE, rt.getResult()); + Mockito.verify(mLockHandle).getLockInfo("keyspace", "table", "lockName", "1"); + /*TODO: if we successfully acquire the lock we hit an error by trying to read MusicDatastoreHandle */ + } + + @Test + public void testWhoseTurnIsIt() throws Exception { + String fullyQualifiedKey = "keyspace.table.lockName"; + Mockito.when(mLockHandle.peekLockQueue("keyspace", "table", "lockName")) + .thenReturn(mLockHandle.new LockObject(true, "1", "", "", LockType.WRITE, null)); + + String topOfQ = core.whoseTurnIsIt(fullyQualifiedKey); + System.out.println(topOfQ); + + assertEquals("$"+fullyQualifiedKey+"$1", topOfQ); + } + + @Test + public void testGetCurrentLockHolders() throws Exception { + String fullyQualifiedKey = "keyspace.table.lockName"; + List<String> currentHolders = new ArrayList<>(); + currentHolders.add("$"+fullyQualifiedKey+"$1"); + currentHolders.add("$"+fullyQualifiedKey+"$2"); + Mockito.when(mLockHandle.getCurrentLockHolders("keyspace", "table", "lockName")) + .thenReturn(currentHolders); + + List<String> holders = core.getCurrentLockHolders(fullyQualifiedKey); + + assertTrue(currentHolders.containsAll(holders) && holders.containsAll(currentHolders)); + } + + @Test + public void testGetLockNameFromId() { + String lockId = "$keyspace.table.lockName$1"; + assertEquals("keyspace.table.lockName", core.getLockNameFromId(lockId)); + } + + @Test + public void testDestroyLockRefString() throws Exception { + String lockId = "$keyspace.table.lockName$1"; + + core.destroyLockRef(lockId); + Mockito.verify(mLockHandle).deQueueLockRef("keyspace", "table", "lockName", "1", MusicUtil.getRetryCount()); + } + + @Test + public void testDestroyLockRefStringString() throws Exception { + String fullyQualifiedKey = "keyspace.table.lockName"; + String lockReference = "1"; + + core.destroyLockRef(fullyQualifiedKey, lockReference); + Mockito.verify(mLockHandle).deQueueLockRef("keyspace", "table", "lockName", "1", MusicUtil.getRetryCount()); + } + + @Test + public void testReleaseLock() throws Exception { + String lockId = "$keyspace.table.lockName$1"; + + core.releaseLock(lockId, true); + + Mockito.verify(mLockHandle).deQueueLockRef("keyspace", "table", "lockName", "1", MusicUtil.getRetryCount()); + } + + @Test + public void testVoluntaryReleaseLock() throws Exception { + String fullyQualifiedKey = "keyspace.table.lockName"; + String lockReference = "1"; + + core.voluntaryReleaseLock(fullyQualifiedKey, lockReference); + + Mockito.verify(mLockHandle).deQueueLockRef("keyspace", "table", "lockName", "1", MusicUtil.getRetryCount()); + } + + @Test + public void testReleaseAllLocksForOwner() throws Exception { + List<String> ownersLocks = new ArrayList<>(); + ownersLocks.add("lockName$1"); + ownersLocks.add("lockName$2"); + Mockito.when(mLockHandle.getAllLocksForOwner("ownerId", "keyspace", "table")) + .thenReturn(ownersLocks); + + List<String> locksReleased = core.releaseAllLocksForOwner("ownerId", "keyspace", "table"); + + Mockito.verify(mLockHandle).deQueueLockRef("keyspace", "table", "lockName", "1", MusicUtil.getRetryCount()); + Mockito.verify(mLockHandle).deQueueLockRef("keyspace", "table", "lockName", "2", MusicUtil.getRetryCount()); + assertTrue(ownersLocks.containsAll(locksReleased) && locksReleased.containsAll(ownersLocks)); + } + + + @Test + public void testValidateLock() { + String lockId = "$keyspace.table.lockName$1"; + + assertFalse(core.validateLock(lockId).containsKey("Error")); + } + + @Test + public void testGetLockQueue() throws Exception { + String fullyQualifiedKey = "keyspace.table.lockName"; + List<String> myList = new ArrayList<>(); + Mockito.when(mLockHandle.getLockQueue("keyspace", "table", "lockName")) + .thenReturn(myList); + List<String> theirList = core.getLockQueue(fullyQualifiedKey); + + assertEquals(myList, theirList); + } + + @Test + public void testGetLockQueueSize() throws Exception { + String fullyQualifiedKey = "keyspace.table.lockName"; + Mockito.when(mLockHandle.getLockQueueSize("keyspace", "table", "lockName")) + .thenReturn((long) 23); + long theirSize = core.getLockQueueSize(fullyQualifiedKey); + + assertEquals(23, theirSize); + } + + @Test + public void testCreateTable() throws MusicServiceException, MusicQueryException { + String keyspaceName = "keyspace"; + String tableName = "table"; + JsonTable table = new JsonTable(); + table.setTableName(tableName); + table.setKeyspaceName(keyspaceName); + Map<String, String> fields = new HashMap<>(); + fields.put("employee", "text"); + fields.put("salary", "int"); + table.setFields(fields); + table.setPrimaryKey("employee"); + + Mockito.when(mLockHandle.createLockQueue(Mockito.matches(keyspaceName), Mockito.matches(tableName))) + .thenReturn(true); + Mockito.when(dsHandle.executePut(Mockito.any(PreparedQueryObject.class), Mockito.matches("eventual"))).thenReturn(true); + ResultType rs = core.createTable(table , "eventual"); + + assertEquals(ResultType.SUCCESS, rs); + } + + @Test + public void testDropTable() throws MusicServiceException, MusicQueryException { + String keyspaceName = "keyspace"; + String tableName = "table"; + JsonTable table = new JsonTable(); + table.setTableName(tableName); + table.setKeyspaceName(keyspaceName); + + ArgumentCaptor<PreparedQueryObject> queryCaptor = ArgumentCaptor.forClass(PreparedQueryObject.class); + Mockito.when(dsHandle.executePut(queryCaptor.capture(), Mockito.matches("eventual"))).thenReturn(true); + + ResultType rs = core.dropTable(table, "eventual"); + assertEquals(ResultType.SUCCESS, rs); + assertEquals("DROP TABLE keyspace.table;", queryCaptor.getValue().getQuery()); + } + + @Test + public void testQuorumGet() throws MusicServiceException, MusicQueryException { + PreparedQueryObject query = new PreparedQueryObject("SELECT * FROM EMPLOYEES;"); + ResultSet rs = Mockito.mock(ResultSet.class); + Mockito.when(dsHandle.executeQuorumConsistencyGet(Mockito.same(query))).thenReturn(rs); + ResultSet returnedRs = core.quorumGet(query); + + assertEquals(rs, returnedRs); + } + + @Test + public void testForciblyReleaseLock() throws MusicServiceException, MusicQueryException, MusicLockingException { + String fullyQualifiedKey = "keyspace.table.lockName"; + ArgumentCaptor<PreparedQueryObject> unsyncedQuery = ArgumentCaptor.forClass(PreparedQueryObject.class); + Mockito.doReturn(true).when(dsHandle).executePut(unsyncedQuery.capture(), Mockito.matches("critical")); + core.forciblyReleaseLock(fullyQualifiedKey, "123"); + + assertEquals("insert into keyspace.unsyncedKeys_table (key) values (?);",unsyncedQuery.getValue().getQuery()); + } + + @Test + public void testEventualPut() throws MusicServiceException, MusicQueryException { + PreparedQueryObject query = new PreparedQueryObject("INSERT INTO EMPLOYEES VALUES ('John', 1);"); + Mockito.when(dsHandle.executePut(Mockito.same(query), Mockito.matches("eventual"))).thenReturn(true); + + assertEquals(ResultType.SUCCESS, core.eventualPut(query).getResult()); + } + + @Test + public void testEventualPutNB() throws MusicServiceException, MusicQueryException { + String keyspace = "keyspace"; + String table = "EMPLOYEES"; + String primaryKey = "NAME"; + PreparedQueryObject query = new PreparedQueryObject("INSERT INTO EMPLOYEES VALUES ('John', 1);"); + + ArgumentCaptor<PreparedQueryObject> queryCapture = ArgumentCaptor.forClass(PreparedQueryObject.class); + ResultSet rs = Mockito.mock(ResultSet.class); + Row row = Mockito.mock(Row.class); + Mockito.when(dsHandle.executeQuorumConsistencyGet(queryCapture.capture())).thenReturn(rs); + Mockito.when(rs.one()).thenReturn(row); + + Mockito.when(dsHandle.executePut(queryCapture.capture(), Mockito.matches("eventual"))).thenReturn(true); + + ReturnType rt = core.eventualPut_nb(query, keyspace, table, primaryKey); + + assertEquals("SELECT guard FROM keyspace.lockq_EMPLOYEES WHERE key = ? ;", + queryCapture.getAllValues().get(0).getQuery()); + assertEquals("INSERT INTO EMPLOYEES VALUES ('John', 1);", queryCapture.getAllValues().get(1).getQuery()); + + assertEquals(ResultType.SUCCESS, rt.getResult()); + } + + @Test + public void testCriticalPut() throws MusicServiceException, MusicQueryException { + String keyspace = "keyspace"; + String table = "table"; + String primaryKey = "lockName"; + PreparedQueryObject query = new PreparedQueryObject("INSERT INTO TABLE VALUES ('John', 1);"); + String lockId = "$keyspace.table.lockName$1"; + + Mockito.when(mLockHandle.getLockInfo("keyspace", "table", "lockName", "1")) + .thenReturn(mLockHandle.new LockObject(true, lockId, null, null, LockType.WRITE, null)); + + ArgumentCaptor<PreparedQueryObject> queryCapture = ArgumentCaptor.forClass(PreparedQueryObject.class); + Mockito.when(dsHandle.executePut(queryCapture.capture(), Mockito.matches("critical"))).thenReturn(true); + ReturnType rt = core.criticalPut(keyspace, table, primaryKey, query, lockId, null); + + assertEquals(true, queryCapture.getValue().getQuery() + .startsWith("INSERT INTO TABLE VALUES ('John', 1) USING TIMESTAMP")); + assertEquals(ResultType.SUCCESS, rt.getResult()); + } + + @Test + public void testNonKeyRelatedPut() throws MusicServiceException, MusicQueryException { + PreparedQueryObject query = new PreparedQueryObject("INSERT INTO TABLE VALUES ('John', 1);"); + String consistency = "eventual"; + ArgumentCaptor<PreparedQueryObject> queryCapture = ArgumentCaptor.forClass(PreparedQueryObject.class); + Mockito.when(dsHandle.executePut(queryCapture.capture(), Mockito.matches(consistency))).thenReturn(true); + + core.nonKeyRelatedPut(query, consistency); + + assertEquals(query.getQuery(), queryCapture.getValue().getQuery()); + } + + @Test + public void testGet() throws MusicServiceException, MusicQueryException { + PreparedQueryObject query = new PreparedQueryObject("SELECT * FROM EMPLOYEES;"); + ResultSet rs = Mockito.mock(ResultSet.class); + Mockito.when(dsHandle.executeOneConsistencyGet(Mockito.same(query))).thenReturn(rs); + assertEquals(rs, core.get(query)); + } + + @Test + public void testCriticalGet() throws MusicServiceException, MusicQueryException { + String keyspace = "keyspace"; + String table = "table"; + String primaryKey = "lockName"; + PreparedQueryObject query = new PreparedQueryObject("SELECT * FROM EMPLOYEES WHERE LOCKNAME='lockName';"); + String lockId = "$keyspace.table.lockName$1"; + + Mockito.when(mLockHandle.getLockInfo("keyspace", "table", "lockName", "1")) + .thenReturn(mLockHandle.new LockObject(true, lockId, null, null, LockType.WRITE, null)); + + ArgumentCaptor<PreparedQueryObject> queryCapture = ArgumentCaptor.forClass(PreparedQueryObject.class); + ResultSet rs = Mockito.mock(ResultSet.class); + Mockito.when(dsHandle.executeQuorumConsistencyGet(queryCapture.capture())).thenReturn(rs); + assertEquals(rs, core.criticalGet(keyspace, table, primaryKey, query, lockId)); + } + + @Test + public void testCreateKeyspace() throws MusicServiceException, MusicQueryException { + String keyspace = "cycling"; + JsonKeySpace ks = new JsonKeySpace(); + ks.setKeyspaceName(keyspace); + ks.setDurabilityOfWrites("true"); + + Map<String, Object> replicationInfo = new HashMap<>(); + replicationInfo.put("class", "SimpleStrategy"); + replicationInfo.put("replication_factor", 1); + ks.setReplicationInfo(replicationInfo); + Map<String, String> consistencyInfo = new HashMap<>(); + consistencyInfo.put("consistency", "quorum"); + ks.setConsistencyInfo(consistencyInfo); + + ArgumentCaptor<PreparedQueryObject> queryCapture = ArgumentCaptor.forClass(PreparedQueryObject.class); + Mockito.when(dsHandle.executePut(queryCapture.capture(), Mockito.matches("eventual"))).thenReturn(true); + + core.createKeyspace(ks , "eventual"); + + assertEquals("CREATE KEYSPACE cycling WITH replication = {'replication_factor':1,'class':'SimpleStrategy'} AND durable_writes = true;", + queryCapture.getValue().getQuery()); + } + + @Test + public void testDropKeyspace() throws MusicServiceException, MusicQueryException { + String keyspace = "cycling"; + JsonKeySpace ks = new JsonKeySpace(); + ks.setKeyspaceName(keyspace); + + ArgumentCaptor<PreparedQueryObject> queryCapture = ArgumentCaptor.forClass(PreparedQueryObject.class); + Mockito.when(dsHandle.executePut(queryCapture.capture(), Mockito.matches("eventual"))).thenReturn(true); + + core.dropKeyspace(ks , "eventual"); + + assertEquals("DROP KEYSPACE cycling;", queryCapture.getValue().getQuery()); + } +} diff --git a/music-core/src/test/java/org/onap/music/unittests/jsonobjects/JSONObjectTest.java b/music-core/src/test/java/org/onap/music/unittests/jsonobjects/JSONObjectTest.java new file mode 100644 index 00000000..7f6af4c5 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/unittests/jsonobjects/JSONObjectTest.java @@ -0,0 +1,44 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 IBM. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.unittests.jsonobjects; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import org.onap.music.datastore.jsonobjects.JSONObject; + +public class JSONObjectTest { + private JSONObject jsonObject; + + @Before + public void setUp() { + jsonObject = new JSONObject(); + } + + @Test + public void testGetSetData() { + jsonObject.setData("data"); + Assert.assertEquals("data", jsonObject.getData()); + } +} diff --git a/music-core/src/test/java/org/onap/music/unittests/jsonobjects/JsonLeasedLockTest.java b/music-core/src/test/java/org/onap/music/unittests/jsonobjects/JsonLeasedLockTest.java new file mode 100644 index 00000000..b7dfa075 --- /dev/null +++ b/music-core/src/test/java/org/onap/music/unittests/jsonobjects/JsonLeasedLockTest.java @@ -0,0 +1,47 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.unittests.jsonobjects; + +import static org.junit.Assert.*; +import org.junit.Before; +import org.junit.Test; +import org.onap.music.datastore.jsonobjects.JsonLeasedLock; + +public class JsonLeasedLockTest { + + JsonLeasedLock jl = null; + + @Before + public void init() { + jl = new JsonLeasedLock(); + } + + + @Test + public void testGetLeasePeriod() { + long lease = 20000; + jl.setLeasePeriod(lease); + assertEquals(lease,jl.getLeasePeriod()); + } + +} diff --git a/music-core/src/test/java/org/onap/music/unittests/jsonobjects/MusicHealthCheckTest.java b/music-core/src/test/java/org/onap/music/unittests/jsonobjects/MusicHealthCheckTest.java new file mode 100644 index 00000000..ceda3f3a --- /dev/null +++ b/music-core/src/test/java/org/onap/music/unittests/jsonobjects/MusicHealthCheckTest.java @@ -0,0 +1,48 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 IBM. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.unittests.jsonobjects; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; +import org.onap.music.eelf.healthcheck.MusicHealthCheck; + +public class MusicHealthCheckTest { + + private MusicHealthCheck musicHealthCheck; + + @Before + public void setUp() + { + musicHealthCheck= new MusicHealthCheck(); + } + + @Test + public void testCassandraHost() + { + musicHealthCheck.setCassandrHost("9042"); + assertEquals("9042", musicHealthCheck.getCassandrHost()); + } + +} diff --git a/music-core/src/test/resources/LICENSE.txt b/music-core/src/test/resources/LICENSE.txt new file mode 100644 index 00000000..cc6cdea5 --- /dev/null +++ b/music-core/src/test/resources/LICENSE.txt @@ -0,0 +1,24 @@ + +The following license applies to all files in this and sub-directories. Licenses +are included in individual source files where appropriate, and if it differs +from this text, it supersedes this. Any file that does not have license text +defaults to being covered by this text; not all files support the addition of +licenses. +# +# ------------------------------------------------------------------------- +# Copyright (c) 2017 AT&T Intellectual Property +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------- +#
\ No newline at end of file diff --git a/music-core/src/test/resources/Resources.properties b/music-core/src/test/resources/Resources.properties new file mode 100644 index 00000000..72269cb8 --- /dev/null +++ b/music-core/src/test/resources/Resources.properties @@ -0,0 +1,50 @@ +#============LICENSE_START========================================== +#org.onap.music +#=================================================================== +# Copyright (c) 2017 AT&T Intellectual Property +#=================================================================== +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +#============LICENSE_END============================================= +#==================================================================== +#Resource key=Error Code|Message text|Resolution text |Description text +LOADING_DEFAULT_LOG_CONFIGURATION=\ + EELF0001I|\ + Loading default logging configuration from system resource file "{0}"|\ + No external logging configurations were defined or found, So verify the default logging configuration from system resource file (../logback.xml). |\ + Loading default logging configuration from system resource file +LOADING_LOG_CONFIGURATION=EELF0002I|\ + Loading logging configuration from file "{0}"|\ + Verify the correct logging configuration file is loaded. |\ + Loading logging configuration for specific file +LOGGING_ALREADY_INITIALIZED=\ + EELF0003W|\ + Logging has already been initialized, check the container logging definitions to ensure they represent your desired logging configuration.|\ + Verify the container logging definitions to ensure they represent your desired logging configuration. |\ + Logging has already been initialized, check the container logging definitions to ensure they represent your desired logging configuration. +NO_LOG_CONFIGURATION=\ + EELF0004E|\ + No log configuration could be found or defaulted!|\ + No external and default logging configuration file. |\ + No log configuration could be found or defaulted! +SEARCHING_LOG_CONFIGURATION=\ + EELF0005I|\ + Searching path "{0}" for log configuration file "{1}"|\ + Verify the correct Path({user.home};etc;../etc) and filename (eelf.logging.file).|\ + Searching path for specific log configuration file. +UNSUPPORTED_LOGGING_FRAMEWORK=\ + EELF0006E|\ + An unsupported logging framework is bound to SLF4J. |\ + Verify your logging frameworks.|\ + An unsupported logging framework is bound to SLF4J. + diff --git a/music-core/src/test/resources/application.properties b/music-core/src/test/resources/application.properties new file mode 100644 index 00000000..02e9c1a9 --- /dev/null +++ b/music-core/src/test/resources/application.properties @@ -0,0 +1,2 @@ +server.port=8080 +server.servlet.context-path=/MUSIC/rest
\ No newline at end of file diff --git a/music-core/src/test/resources/cache.ccf b/music-core/src/test/resources/cache.ccf new file mode 100644 index 00000000..e152ee8b --- /dev/null +++ b/music-core/src/test/resources/cache.ccf @@ -0,0 +1,62 @@ +# DEFAULT CACHE REGION +jcs.default=DC +jcs.default.cacheattributes=org.apache.commons.jcs.engine.CompositeCacheAttributes +jcs.default.cacheattributes.MaxObjects=1000 +jcs.default.cacheattributes.MemoryCacheName=org.apache.commons.jcs.engine.memory.lru.LRUMemoryCache +jcs.default.elementattributes=org.apache.commons.jcs.engine.ElementAttributes +jcs.default.elementattributes.IsEternal=true +jcs.default.elementattributes.IsSpool=true + +# PRE-DEFINED CACHE REGIONS +jcs.region.musicCache= +jcs.region.musicCache.cacheattributes=org.apache.commons.jcs.engine.CompositeCacheAttributes +jcs.region.musicCache.cacheattributes.MaxObjects=1000 +jcs.region.musicCache.cacheattributes.MemoryCacheName=org.apache.commons.jcs.engine.memory.lru.LRUMemoryCache +jcs.region.musicCache.cacheattributes.UseMemoryShrinker=false +jcs.region.musicCache.cacheattributes.MaxMemoryIdleTime=3600 +jcs.region.musicCache.cacheattributes.ShrinkerInterval=60 +jcs.region.musicCache.cacheattributes.MaxSpoolPerRun=500 +jcs.region.musicCache.elementattributes=org.apache.commons.jcs.engine.ElementAttributes +jcs.region.musicCache.elementattributes.IsEternal=false + + +# PRE-DEFINED CACHE REGIONS +jcs.region.aafCache= +jcs.region.aafCache.cacheattributes=org.apache.commons.jcs.engine.CompositeCacheAttributes +jcs.region.aafCache.cacheattributes.MaxObjects=1000 +jcs.region.aafCache.cacheattributes.MemoryCacheName=org.apache.commons.jcs.engine.memory.lru.LRUMemoryCache +jcs.region.aafCache.cacheattributes.UseMemoryShrinker=false +jcs.region.aafCache.cacheattributes.MaxMemoryIdleTime=3600 +jcs.region.aafCache.cacheattributes.ShrinkerInterval=60 +jcs.region.aafCache.cacheattributes.MaxSpoolPerRun=500 +jcs.region.aafCache.elementattributes=org.apache.commons.jcs.engine.ElementAttributes +jcs.region.aafCache.elementattributes.IsEternal=false + +# PRE-DEFINED CACHE REGIONS +jcs.region.appNameCache= +jcs.region.appNameCache.cacheattributes=org.apache.commons.jcs.engine.CompositeCacheAttributes +jcs.region.appNameCache.cacheattributes.MaxObjects=1000 +jcs.region.appNameCache.cacheattributes.MemoryCacheName=org.apache.commons.jcs.engine.memory.lru.LRUMemoryCache +jcs.region.appNameCache.cacheattributes.UseMemoryShrinker=false +jcs.region.appNameCache.cacheattributes.MaxMemoryIdleTime=3600 +jcs.region.appNameCache.cacheattributes.ShrinkerInterval=60 +jcs.region.appNameCache.cacheattributes.MaxSpoolPerRun=500 +jcs.region.appNameCache.elementattributes=org.apache.commons.jcs.engine.ElementAttributes +jcs.region.appNameCache.elementattributes.IsEternal=false + +jcs.default=DC +jcs.default.cacheattributes=org.apache.commons.jcs.engine.CompositeCacheAttributes +jcs.default.cacheattributes.MaxObjects=1000 +jcs.default.cacheattributes.MemoryCacheName=org.apache.commons.jcs.engine.memory.lru.LRUMemoryCache +jcs.default.elementattributes=org.apache.commons.jcs.engine.ElementAttributes +jcs.default.elementattributes.IsEternal=true +jcs.default.elementattributes.IsSpool=true + +jcs.region.eternalCache=DC +jcs.region.eternalCache.cacheattributes=org.apache.commons.jcs.engine.CompositeCacheAttributes +jcs.region.eternalCache.cacheattributes.MaxObjects=1000 +jcs.region.eternalCache.cacheattributes.MemoryCacheName=org.apache.commons.jcs.engine.memory.lru.LRUMemoryCache +jcs.region.eternalCache.elementattributes=org.apache.commons.jcs.engine.ElementAttributes +jcs.region.eternalCache.elementattributes.IsEternal=true +jcs.region.eternalCache.elementattributes.IsSpool=true + diff --git a/music-core/src/test/resources/logback.xml b/music-core/src/test/resources/logback.xml new file mode 100644 index 00000000..6bc5fd5e --- /dev/null +++ b/music-core/src/test/resources/logback.xml @@ -0,0 +1,302 @@ +<!-- + ============LICENSE_START========================================== + org.onap.music + =================================================================== + Copyright (c) 2017 AT&T Intellectual Property + =================================================================== + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + ============LICENSE_END============================================= + ==================================================================== +--> +<configuration scan="true" scanPeriod="3 seconds"> + <!--<jmxConfigurator /> --> + <!-- directory path for all other type logs --> + <property name="logDir" value="/opt/app/music/logs" /> + + <!-- directory path for debugging type logs --> + <property name="debugDir" value="debug-logs" /> + + <!-- specify the component name --> + <!-- <property name="componentName" value="EELF"></property> --> + <property name="componentName" value="MUSIC"></property> + + <!-- log file names --> + <property name="generalLogName" value="music" /> + <property name="securityLogName" value="security" /> + <property name="errorLogName" value="error" /> + <property name="metricsLogName" value="metrics" /> + <property name="auditLogName" value="audit" /> + <property name="debugLogName" value="debug" /> + <property name="defaultPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n" /> + <!-- <property name="applicationLoggerPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %msg%n" /> --> + <property name="applicationLoggerPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5level %X{keyspace} - %msg%n" /> + <property name="auditLoggerPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{VirtualServerName}|%X{ServiceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}|%X{Unused}|%X{ProcessKey}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}| %msg%n" /> + <property name="metricsLoggerPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{VirtualServerName}|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}|%X{Unused}|%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}| %msg%n" /> + <!-- <property name="errorLoggerPattern" value= "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %msg%n " /> --> + <property name="errorLoggerPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5level %X{keyspace} - %msg%n" /> + <property name="debugLoggerPattern" value="%date{ISO8601,UTC}|%X{RequestId}| %msg%n" ></property> + <property name="logDirectory" value="${logDir}/${componentName}" /> + <property name="debugLogDirectory" value="${debugDir}/${componentName}" /> + <!-- Example evaluator filter applied against console appender --> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <!-- <encoder> + <pattern>${defaultPattern}</pattern> + </encoder> --> + <layout class=""> + <pattern> + %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n + </pattern> + </layout> + </appender> + + <!-- ============================================================================ --> + <!-- EELF Appenders --> + <!-- ============================================================================ --> +<!-- <appender name="EELF" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${generalLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${generalLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>100MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${applicationLoggerPattern}</pattern> + </encoder> + </appender> --> + + <!-- <appender name="EELF" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${generalLogName}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + daily rollover + <fileNamePattern>${logDirectory}/${generalLogName}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern> + <maxFileSize>1GB</maxFileSize> + <maxHistory>5</maxHistory> + <totalSizeCap>5GB</totalSizeCap> + </rollingPolicy> + <encoder> + <pattern>${applicationLoggerPattern}</pattern> + </encoder> + </appender> --> + + + <appender name="EELF" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${generalLogName}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <!-- daily rollover --> + <fileNamePattern>${logDirectory}/${generalLogName}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern> + <maxFileSize>1GB</maxFileSize> + <maxHistory>5</maxHistory> + <totalSizeCap>5GB</totalSizeCap> + </rollingPolicy> + <encoder> + <pattern>${applicationLoggerPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELF" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <includeCallerData>true</includeCallerData> + <appender-ref ref="EELF" /> + </appender> + + <!-- EELF Security Appender. This appender is used to record security events + to the security log file. Security events are separate from other loggers + in EELF so that security log records can be captured and managed in a secure + way separate from the other logs. This appender is set to never discard any + events. --> + <appender name="EELFSecurity" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${securityLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${securityLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n </pattern> + </encoder> + </appender> + + <appender name="asyncEELFSecurity" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <discardingThreshold>0</discardingThreshold> + <appender-ref ref="EELFSecurity" /> + </appender> + + + + + <!-- EELF Audit Appender. This appender is used to record audit engine + related logging events. The audit logger and appender are specializations + of the EELF application root logger and appender. This can be used to segregate + Policy engine events from other components, or it can be eliminated to record + these events as part of the application root log. --> + + <appender name="EELFAudit" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${auditLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${auditLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${auditLoggerPattern}</pattern> + </encoder> + </appender> + <appender name="asyncEELFAudit" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFAudit" /> + </appender> + +<appender name="EELFMetrics" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${metricsLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${metricsLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <!-- <pattern>"%d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - + %msg%n"</pattern> --> + <pattern>${metricsLoggerPattern}</pattern> + </encoder> + </appender> + + + <appender name="asyncEELFMetrics" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFMetrics"/> + </appender> + + <appender name="EELFError" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${errorLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${errorLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${errorLoggerPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELFError" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFError"/> + </appender> + + <appender name="EELFDebug" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${debugLogDirectory}/${debugLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${debugLogDirectory}/${debugLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${debugLoggerPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELFDebug" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFDebug" /> + <includeCallerData>true</includeCallerData> + </appender> + + + <!-- ============================================================================ --> + <!-- EELF loggers --> + <!-- ============================================================================ --> + <logger name="com.att.eelf" level="info" additivity="false"> + <appender-ref ref="asyncEELF" /> + + </logger> + <logger name="com.att.eelf.security" level="info" additivity="false"> + <appender-ref ref="asyncEELFSecurity" /> + + </logger> + + + <logger name="com.att.eelf.audit" level="info" additivity="false"> + <appender-ref ref="asyncEELFAudit" /> + + </logger> + + <logger name="com.att.eelf.metrics" level="info" additivity="false"> + <appender-ref ref="asyncEELFMetrics" /> + + </logger> + + + <logger name="com.att.eelf.error" level="error" additivity="false"> + <appender-ref ref="asyncEELFError" /> + + </logger> + + <logger name="com.att.eelf.debug" level="debug" additivity="false"> + <appender-ref ref="asyncEELFDebug" /> + + </logger> + + <root level="INFO"> + <appender-ref ref="asyncEELF" /> + <!-- <appender-ref ref="STDOUT" /> --> + </root> + + <!-- Conductor Specific additions to squash WARNING and INFO --> + <logger name="com.datastax.driver.core.Cluster" level="ERROR"/> + <logger name="org.onap.music.main.MusicCore" level="ERROR"/> + +</configuration> diff --git a/music-core/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/music-core/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 00000000..1f0955d4 --- /dev/null +++ b/music-core/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline diff --git a/music-core/src/test/resources/mockito-extensions/org.mockito.plugins.StackTraceCleanerProvider b/music-core/src/test/resources/mockito-extensions/org.mockito.plugins.StackTraceCleanerProvider new file mode 100644 index 00000000..bc2f0992 --- /dev/null +++ b/music-core/src/test/resources/mockito-extensions/org.mockito.plugins.StackTraceCleanerProvider @@ -0,0 +1 @@ +org.mockito.internal.exceptions.stacktrace.DefaultStackTraceCleanerProvider diff --git a/music-core/src/test/resources/project.properties b/music-core/src/test/resources/project.properties new file mode 100644 index 00000000..199afa33 --- /dev/null +++ b/music-core/src/test/resources/project.properties @@ -0,0 +1,4 @@ +version=${project.version} +artifactId=${project.artifactId} +music.properties=/opt/app/music/etc/music.properties + |