aboutsummaryrefslogtreecommitdiffstats
path: root/music-core/src
diff options
context:
space:
mode:
Diffstat (limited to 'music-core/src')
-rwxr-xr-xmusic-core/src/main/java/org/onap/music/datastore/MusicDataStore.java31
-rw-r--r--music-core/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java3
-rw-r--r--music-core/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java2
-rw-r--r--music-core/src/main/java/org/onap/music/lockingservice/cassandra/LockCleanUpDaemon.java132
-rw-r--r--music-core/src/main/java/org/onap/music/main/CipherUtil.java19
-rw-r--r--music-core/src/main/java/org/onap/music/main/MusicUtil.java44
-rw-r--r--music-core/src/main/java/org/onap/music/service/MusicCoreService.java2
-rw-r--r--music-core/src/main/java/org/onap/music/service/impl/MusicCassaCore.java25
-rw-r--r--music-core/src/test/java/org/onap/music/eelf/logging/format/ErrorTypesTest.java48
-rw-r--r--music-core/src/test/java/org/onap/music/service/impl/MusicCassaCoreTest.java209
10 files changed, 480 insertions, 35 deletions
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
index 7f6c42ca..cb22c0f4 100755
--- a/music-core/src/main/java/org/onap/music/datastore/MusicDataStore.java
+++ b/music-core/src/main/java/org/onap/music/datastore/MusicDataStore.java
@@ -374,22 +374,25 @@ public class MusicDataStore {
ResultSet rs = session.execute(preparedInsert);
result = rs.wasApplied();
-
- }
- catch (AlreadyExistsException ae) {
- // logger.error(EELFLoggerDelegate.errorLogger,"AlreadExistsException: " + ae.getMessage(),AppMessages.QUERYERROR,
- // ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
- throw new MusicQueryException("AlreadyExistsException: " + ae.getMessage(),ae);
- } catch ( InvalidQueryException e ) {
- // logger.error(EELFLoggerDelegate.errorLogger,"InvalidQueryException: " + e.getMessage(),AppMessages.SESSIONFAILED + " ["
- // + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
- throw new MusicQueryException("InvalidQueryException: " + e.getMessage(),e);
+ } 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.getClass().toString() + ":" + e.getMessage(),AppMessages.SESSIONFAILED + " ["
- // + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR, e);
- throw new MusicServiceException("Executing Session Failure for Request = " + "["
- + queryObject.getQuery() + "]" + " Reason = " + e.getMessage(),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;
}
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
index 92457d07..09fe0d35 100644
--- a/music-core/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java
+++ b/music-core/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java
@@ -88,6 +88,9 @@ public class MusicDataStoreHandle {
return mDstoreHandle;
}
+ public static void setMDstoreHandle(MusicDataStore dsHandle) {
+ mDstoreHandle = dsHandle;
+ }
/**
*
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
index e9533344..a727357f 100644
--- 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
@@ -50,7 +50,7 @@ import com.datastax.driver.extras.codecs.enums.EnumNameCodec;
public class CassaLockStore {
private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CassaLockStore.class);
- private static String table_prepend_name = "lockQ_";
+ public static final String table_prepend_name = "lockQ_";
private MusicDataStore dsHandle;
public CassaLockStore() {
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..492a48f0
--- /dev/null
+++ b/music-core/src/main/java/org/onap/music/lockingservice/cassandra/LockCleanUpDaemon.java
@@ -0,0 +1,132 @@
+/*
+ * ============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.List;
+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.MusicQueryException;
+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) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ 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 {
+ 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/main/CipherUtil.java b/music-core/src/main/java/org/onap/music/main/CipherUtil.java
index 327022d5..3278dc12 100644
--- a/music-core/src/main/java/org/onap/music/main/CipherUtil.java
+++ b/music-core/src/main/java/org/onap/music/main/CipherUtil.java
@@ -259,13 +259,20 @@ public class CipherUtil {
}
}
- /*public static void main(String[] args) {
+ public static void main(String[] args) {
- System.out.println("Encrypted password: "+encryptPKC("cassandra"));
+ 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: "+decryptPKC("dDhqAp5/RwZbl9yRSZg15fN7Qul9eiE/JFkKemtTib0="));
- System.out.println("Decrypted password: "+decryptPKC("I/dOtD/YYzBStbtOYhKuUUyPHSW2G9ZzdSyB8bJp4vk="));
- System.out.println("Decrypted password: "+decryptPKC("g7zJqg74dLsH/fyL7I75b4eySy3pbMS2xVqkrB5lDl8="));
- }*/
+ System.out.println("Decrypted password (to verify): " + decryptPKC(enc));
+ }
}
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
index 78d17c60..865ca01f 100644
--- a/music-core/src/main/java/org/onap/music/main/MusicUtil.java
+++ b/music-core/src/main/java/org/onap/music/main/MusicUtil.java
@@ -34,9 +34,11 @@ 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;
@@ -107,6 +109,8 @@ public class MusicUtil {
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",
@@ -160,7 +164,26 @@ public class MusicUtil {
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");
}
@@ -810,6 +833,27 @@ public class MusicUtil {
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;
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
index 2fc88145..753d9b28 100644
--- a/music-core/src/main/java/org/onap/music/service/MusicCoreService.java
+++ b/music-core/src/main/java/org/onap/music/service/MusicCoreService.java
@@ -97,7 +97,7 @@ public interface MusicCoreService {
* @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
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
index 63f2d14c..d29ba32b 100644
--- 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
@@ -27,12 +27,13 @@ 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;
@@ -75,7 +76,9 @@ public class MusicCassaCore implements MusicCoreService {
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
}
@@ -84,7 +87,8 @@ public class MusicCassaCore implements MusicCoreService {
return mLockHandle;
}
- public static void setmLockHandle(CassaLockStore mLockHandle) {
+ //for unit testing purposes
+ static void setmLockHandle(CassaLockStore mLockHandle) {
MusicCassaCore.mLockHandle = mLockHandle;
}
@@ -119,10 +123,11 @@ public class MusicCassaCore implements MusicCoreService {
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("\\.");
@@ -348,7 +353,6 @@ public class MusicCassaCore implements MusicCoreService {
* @return Boolean Indicates success or failure
* @throws MusicServiceException
*
- *
*/
public ResultType createTable(String keyspace, String table, PreparedQueryObject tableQueryObject,
String consistency) throws MusicServiceException {
@@ -357,9 +361,9 @@ public class MusicCassaCore implements MusicCoreService {
try {
// create shadow locking table
result = getLockingServiceHandle().createLockQueue(keyspace, table);
- if (result == false)
+ if (result == false) {
return ResultType.FAILURE;
-
+ }
result = false;
// create table to track unsynced_keys
@@ -370,8 +374,11 @@ public class MusicCassaCore implements MusicCoreService {
PreparedQueryObject queryObject = new PreparedQueryObject();
queryObject.appendQueryString(tabQuery);
- result = false;
result = MusicDataStoreHandle.getDSHandle().executePut(queryObject, "eventual");
+ if (result == false) {
+ return ResultType.FAILURE;
+ }
+ result = false;
// create actual table
result = MusicDataStoreHandle.getDSHandle().executePut(tableQueryObject, consistency);
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/service/impl/MusicCassaCoreTest.java b/music-core/src/test/java/org/onap/music/service/impl/MusicCassaCoreTest.java
index 280ba207..33debfaa 100644
--- 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
@@ -23,14 +23,21 @@ 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;
@@ -40,21 +47,32 @@ 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());
@@ -281,4 +299,187 @@ public class MusicCassaCoreTest {
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());
+ }
}