/*
* 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.
*/
package com.wizecommerce.hecuba;
import static org.junit.Assert.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.ListUtils;
import org.apache.commons.lang.time.DateUtils;
import org.junit.Test;
import com.google.common.collect.Lists;
import com.wizecommerce.hecuba.util.CassandraTestBase;
public abstract class HecubaCassandraManagerTestBase extends CassandraTestBase {
// Apparently, cassandra can not handle larger integer set as TTL. So we are limiting the TTL to 10 years (which
// technically is equal to not setting TTL at all :).
final int TEN_YEARS = (int) TimeUnit.DAYS.toSeconds(365 * 10);
public void testConstructor() {
String clusterName = "My Awesome Cluster";
String locationURL = "africa:northamerica:southamerica:asia:europe";
String thriftPorts = "3726";
String keyspace = "WizeCommerce";
String cf = "Platform and Infra";
String secondaryIndexColumns = "Column_1:Column_2:Column_3";
CassandraParamsBean bean = new CassandraParamsBean();
bean.setClustername(clusterName);
bean.setLocationURLs(locationURL);
bean.setThriftPorts(thriftPorts);
bean.setKeyspace(keyspace);
bean.setColumnFamily(cf);
bean.setSiColumns(secondaryIndexColumns);
assertEquals(clusterName, bean.getClustername());
assertEquals(locationURL, bean.getLocationURLs());
assertEquals(thriftPorts, bean.getThriftPorts());
assertEquals(keyspace, bean.getKeyspace());
assertEquals(cf, bean.getColumnFamily());
assertEquals(secondaryIndexColumns, bean.getSiColumns());
HecubaClientManager<Long> cassandraManager = getHecubaClientManager(bean);
assertEquals(clusterName, cassandraManager.getClusterName());
assertEquals(locationURL, cassandraManager.getLocationURL());
assertEquals(thriftPorts, cassandraManager.getPort());
assertEquals(keyspace, cassandraManager.getKeyspace());
assertEquals(cf, cassandraManager.getColumnFamilyName());
assertTrue(ListUtils.removeAll(Arrays.asList(secondaryIndexColumns.split(":")), cassandraManager.getColumnsToIndexOnColumnNameAndValue()).size() == 0);
}
/**
* Runs the secondary index tests with columnSize overrides enabled.
*/
/**
* testSecondaryIndexWithMaxColumnsOverride
*
* @throws Exception
*/
@Test
public void testUpdateRowScenario16() throws Exception {
final int maxResultSetSize = 120;
CassandraParamsBean bean = getDefaultCassandraParamsBean();
bean.setMaxSiColumnCount(maxResultSetSize);
bean.setMaxColumnCount(maxResultSetSize);
bean.setSiColumns("MySecondaryKey_1:MySecondaryKey_2");
// Run all generic tests to verify standard behavior is still functional.
runSecondaryIndexTests(bean);
// Large SecondIndex result set.
HecubaClientManager<Long> cassandraManager = getHecubaClientManager(bean);
// Write 120 rows to cassandra, with the same secondary Index.
for (long i = 0; i < maxResultSetSize; i++) {
HashMap<String, Object> row = new HashMap<String, Object>();
row.put("column_1", "value_1");
row.put("column_2", "value_2");
row.put("MySecondaryKey_1", "MySecondaryKey_1_value_1");
cassandraManager.updateRow(i, row);
}
// try to retrieve data by secondaryIndex value.
CassandraResultSet<Long, String> results = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "MySecondaryKey_1_value_1");
int count = 1;
while (results.hasNextResult()) {
results.nextResult();
count++;
}
assertEquals(count, maxResultSetSize);
// Write 120 Columns to a single row
HashMap<String, Object> row = new HashMap<String, Object>();
final long now = System.currentTimeMillis();
for (int i = 0; i < maxResultSetSize; i++) {
row.put(String.valueOf(i), String.valueOf(i) + "_" + now);
}
cassandraManager.deleteRow(1234L); // clearing old data
cassandraManager.updateRow(1234L, row);
// Attempt to retrieve all 120 columns that were written.
Random random = new Random(System.currentTimeMillis());
try {
results = cassandraManager.readAllColumns(1234L);
assertEquals(results.getColumnNames().size(), maxResultSetSize);
// read a random value and verify the expected value.
int index = random.nextInt(maxResultSetSize);
assertEquals(results.getString(String.valueOf(index)), String.valueOf(index) + "_" + now);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testSecondaryIndexWithDeletes() throws Exception {
final int maxResultSetSize = 120;
CassandraParamsBean bean = getDefaultCassandraParamsBean();
bean.setMaxSiColumnCount(maxResultSetSize);
bean.setMaxColumnCount(maxResultSetSize);
bean.setSiColumns("MySecondaryKey_1:MySecondaryKey_2");
// retrieve the cassandra manager.
HecubaClientManager<Long> cassandraManager = getHecubaClientManager(bean);
/**
* 1. Test whether delete row works.
*/
// insert the record 1234L with this secondary index.
HashMap<String, Object> row = new HashMap<String, Object>();
row.put("column_1", "value_1");
row.put("column_2", "value_2");
row.put("MySecondaryKey_1", "MySecondaryKey_1_value_1");
cassandraManager.updateRow(1234L, row);
// now lets see whether we can retrieve this item by the secondary index.
final CassandraResultSet<Long, String> objectRetrievedBeforeDeletion = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "MySecondaryKey_1_value_1");
// 1. we should have retrieved exactly one
assertEquals(false, objectRetrievedBeforeDeletion.hasNextResult());
// 2. And that should have the id 1234L
assertEquals(new Long(1234), objectRetrievedBeforeDeletion.getKey());
// 3. And that should have other columns too.
assertEquals("value_1", objectRetrievedBeforeDeletion.getString("column_1"));
assertEquals("value_2", objectRetrievedBeforeDeletion.getString("column_2"));
assertEquals("MySecondaryKey_1_value_1", objectRetrievedBeforeDeletion.getString("MySecondaryKey_1"));
// now lets delete this item.
cassandraManager.deleteRow(1234L);
// can we retrieve it now?
final CassandraResultSet<Long, String> objectRetrievedAfterDeletion = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "MySecondaryKey_1_value_1");
assertEquals(null, objectRetrievedAfterDeletion);
/**
* 1. Test whether delete column works.
*/
// now lets add a new record.
row = new HashMap<String, Object>();
row.put("column_1", "value_1");
row.put("column_2", "value_2");
row.put("MySecondaryKey_2", "MySecondaryKey_2_value_2");
cassandraManager.updateRow(1978L, row);
// now lets see whether we can retrieve this item by the secondary index.
final CassandraResultSet<Long, String> objectRetrievedBeforeColumnDeletion = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_2", "MySecondaryKey_2_value_2");
// 1. we should have retrieved exactly one
assertEquals(false, objectRetrievedBeforeColumnDeletion.hasNextResult());
// 2. And that should have the id 1234L
assertEquals(new Long(1978L), objectRetrievedBeforeColumnDeletion.getKey());
// alright, now lets delete this secondary index column.
cassandraManager.deleteColumn(1978L, "MySecondaryKey_2");
// now lets see whether we can retrieve 1978L with this secondary index query.
final CassandraResultSet<Long, String> objectRetrievedAfterColumnDeletion = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_2", "MySecondaryKey_2_value_2");
assertEquals(null, objectRetrievedAfterColumnDeletion);
}
/**
* testSecondaryIndexWithUpdatesToMultipleColumns
*
* @throws Exception
*/
@Test
public void testUpdateRowScenario15() throws Exception {
CassandraParamsBean bean = getDefaultCassandraParamsBean();
bean.setSiColumns("MySecondaryKey_1:MySecondaryKey_2");
runSecondaryIndexTests(bean);
}
public void runSecondaryIndexTests(CassandraParamsBean bean) throws Exception {
HecubaClientManager<Long> cassandraManager = getHecubaClientManager(bean);
HashMap<String, Object> row = new HashMap<String, Object>();
row.put("column_1", "value_1");
row.put("column_2", "value_2");
row.put("MySecondaryKey_1", "MySecondaryKey_1_value_1");
cassandraManager.updateRow(1234L, row);
/**
* _______________________________________________ | MySecondaryKey_1:MySecondaryKey_1_value_1 | --> 1234 -----------------------------------------------
*/
// try to retrieve that by its id.
CassandraResultSet<Long, String> resultFromFirstRetrieval = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "MySecondaryKey_1_value_1");
// 1. we should have retrieved exactly one
assertEquals(false, resultFromFirstRetrieval.hasNextResult());
// 2. And that should have the id 1234L
assertEquals(new Long(1234), resultFromFirstRetrieval.getKey());
// 3. And that should have other columns too.
assertEquals("value_1", resultFromFirstRetrieval.getString("column_1"));
assertEquals("value_2", resultFromFirstRetrieval.getString("column_2"));
assertEquals("MySecondaryKey_1_value_1", resultFromFirstRetrieval.getString("MySecondaryKey_1"));
// add another row with the same value for the secondary index
row = new HashMap<String, Object>();
row.put("column_3", "value_3");
row.put("column_4", "value_4");
row.put("MySecondaryKey_1", "MySecondaryKey_1_value_1");
cassandraManager.updateRow(1233L, row);
/**
* _______________________________________________ | MySecondaryKey_1:MySecondaryKey_1_value_1 | --> 1234, 1233 -----------------------------------------------
*/
// BEGIN CHANGES
// see whether we can retrieve both
CassandraResultSet<Long, String> resultFromSecondRetrieval = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "MySecondaryKey_1_value_1");
// 1. And that should have the id 1234L and 1233L
if (resultFromSecondRetrieval.getKey().equals(1234L)) {
logger.info("Testing 1234");
assertEquals("value_1", resultFromSecondRetrieval.getString("column_1"));
assertEquals("value_2", resultFromSecondRetrieval.getString("column_2"));
assertEquals("MySecondaryKey_1_value_1", resultFromSecondRetrieval.getString("MySecondaryKey_1"));
} else {
logger.info("Testing 1233");
assertEquals("value_3", resultFromSecondRetrieval.getString("column_3"));
assertEquals("value_4", resultFromSecondRetrieval.getString("column_4"));
assertEquals("MySecondaryKey_1_value_1", resultFromSecondRetrieval.getString("MySecondaryKey_1"));
}
// 2. we should have retrieved 2 results.
assertTrue(resultFromSecondRetrieval.hasNextResult());
resultFromSecondRetrieval.nextResult();
if (resultFromSecondRetrieval.getKey().equals(1234L)) {
logger.info("Testing 1234");
assertEquals("value_1", resultFromSecondRetrieval.getString("column_1"));
assertEquals("value_2", resultFromSecondRetrieval.getString("column_2"));
assertEquals("MySecondaryKey_1_value_1", resultFromSecondRetrieval.getString("MySecondaryKey_1"));
} else {
logger.info("Testing 1233");
assertEquals("value_3", resultFromSecondRetrieval.getString("column_3"));
assertEquals("value_4", resultFromSecondRetrieval.getString("column_4"));
assertEquals("MySecondaryKey_1_value_1", resultFromSecondRetrieval.getString("MySecondaryKey_1"));
}
// change the value of the secondary index in one of the rows
row = new HashMap<String, Object>();
row.put("column_4", "value_44");
row.put("MySecondaryKey_1", "MySecondaryKey_1_value_2");
cassandraManager.updateRow(1233L, row);
/**
* __________________________________________ | MySecondaryKey_1:MySecondaryKey_1_value_1 | --> 1234 ------------------------------------------
*
* ____________________________________________ | MySecondaryKey_1:MySecondaryKey_1_value_2 | --> 1233 --------------------------------------------
*/
// retrieve the row from the new secondary value
CassandraResultSet<Long, String> resultFromThirdRetrieval = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "MySecondaryKey_1_value_2");
// 2. And that should have the id 1233L
assertEquals(new Long(1233), resultFromThirdRetrieval.getKey());
// 3. And that should have other columns too.
assertEquals("value_3", resultFromThirdRetrieval.getString("column_3"));
assertEquals("value_44", resultFromThirdRetrieval.getString("column_4"));
assertEquals("MySecondaryKey_1_value_2", resultFromThirdRetrieval.getString("MySecondaryKey_1"));
// try to retrieve from the previous one and see whether it returns only one.
CassandraResultSet<Long, String> resultFromFourthRetrieval = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "MySecondaryKey_1_value_1");
// 1. we should have retrieved exactly one
assertEquals(false, resultFromFourthRetrieval.hasNextResult());
// 2. And that should have the id 1234L and 1233L
assertEquals(new Long(1234), resultFromFourthRetrieval.getKey());
// change the value of the secondary index for the first row above and see whether the initial query returns
// anything now.
cassandraManager.updateString(1234L, "MySecondaryKey_1", "MySecondaryKey_1_value_3");
/**
* __________________________________________ | MySecondaryKey_1:MySecondaryKey_1_value_1 | --> ------------------------------------------
*
* ____________________________________________ | MySecondaryKey_1:MySecondaryKey_1_value_2 | --> 1233 --------------------------------------------
*
* ____________________________________________ | MySecondaryKey_1:MySecondaryKey_1_value_3 | --> 1234 --------------------------------------------
*
*/
CassandraResultSet<Long, String> resultFromFifthRetrieval = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "MySecondaryKey_1_value_1");
// 1. we should have retrieved none
assertEquals(null, resultFromFifthRetrieval);
resultFromFifthRetrieval = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "MySecondaryKey_1_value_2");
// 1. we should have retrieved one
assertEquals(false, resultFromFifthRetrieval.hasNextResult());
resultFromFifthRetrieval = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "MySecondaryKey_1_value_3");
// 1. we should have retrieved one
assertEquals(false, resultFromFifthRetrieval.hasNextResult());
}
/**
* ********************************************************************************************************
*
* Column name based secondary index tests
*
* ********************************************************************************************************
*/
/**
* testColumnNameBasedSecondaryIndexBasics
*
* @throws Exception
*/
@Test
public void testUpdateRowScenario14() throws Exception {
CassandraParamsBean bean = getDefaultCassandraParamsBean();
// create secondary index on all column names.
bean.setSiByColumnsPattern(".*");
bean.setSiColumns("MySecondaryKey_1:MySecondaryKey_2");
HecubaClientManager<Long> cassandraManager = getHecubaClientManager(bean);
HashMap<String, Object> row = new HashMap<String, Object>();
List<Long> listOfIds = Lists.newArrayList(123L, 124L, 126L, 127L, 3456L, 4567L);
for (Long id : listOfIds) {
row.clear();
row.put("column_1", "value_1");
if (id < 130) {
row.put("column_2", "value_2");
}
cassandraManager.updateRow(id, row);
}
// ***************************************************************************************
// Scenario 1: Check with the first column name.
// ***************************************************************************************
// first retrieve by column 1
CassandraResultSet<Long, String> idsWithColumn1 = cassandraManager.retrieveByColumnNameBasedSecondaryIndex("column_1");
// has it got some results.
assertNotNull(idsWithColumn1);
assertTrue(idsWithColumn1.hasResults());
int count = 0;
while (idsWithColumn1.hasResults()) {
Long key = idsWithColumn1.getKey();
count++;
// make sure this id is part of the original list
assertTrue(listOfIds.indexOf(key) > -1);
if (idsWithColumn1.hasNextResult()) {
idsWithColumn1.nextResult();
} else {
break;
}
}
// make sure we retrieved all of the ids.
assertEquals(count, listOfIds.size());
// ***************************************************************************************
// Scenario 2: Check with the second column name.
// ***************************************************************************************
// retrieve by column 2
CassandraResultSet<Long, String> idsWithColumn2 = cassandraManager.retrieveByColumnNameBasedSecondaryIndex("column_2");
// has it got some results.
assertTrue(idsWithColumn2.hasResults());
count = 0;
while (idsWithColumn2.hasResults()) {
Long key = idsWithColumn2.getKey();
count++;
// make sure this id is part of the original list
assertTrue(listOfIds.indexOf(key) > -1);
assertTrue(key < 130);
if (idsWithColumn2.hasNextResult()) {
idsWithColumn2.nextResult();
} else {
break;
}
}
assertEquals(4, count);
// ***************************************************************************************
// Scenario 3: Delete the column 1 from 3456L and 123L
// ***************************************************************************************
cassandraManager.deleteColumn(123L, "column_1");
cassandraManager.deleteColumn(3456L, "column_1");
// retrieve by column 1
idsWithColumn1 = cassandraManager.retrieveByColumnNameBasedSecondaryIndex("column_1");
// has it got some results.
assertTrue(idsWithColumn1.hasResults());
count = 0;
while (idsWithColumn1.hasResults()) {
Long key = idsWithColumn1.getKey();
count++;
// make sure this id is part of the original list
assertTrue(listOfIds.indexOf(key) > -1);
assertTrue(key != 123L && key != 3456L);
if (idsWithColumn1.hasNextResult()) {
idsWithColumn1.nextResult();
} else {
break;
}
}
assertEquals(4, count);
// ***************************************************************************************
// Scenario 3: Retrieve by a secondary index that doesn't exist
// ***************************************************************************************
idsWithColumn1 = cassandraManager.retrieveByColumnNameBasedSecondaryIndex("column_33");
// it shouldn't have any results.
assertNull(idsWithColumn1);
}
@Test
public void testReadColumnSlice() throws Exception {
logger.info("Testing Hector read column slice");
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
HashMap<String, Object> row = new HashMap<String, Object>();
/*********************************************************/
/****** TEST CASSANDRA ROW CONTAINS > 100 COLUMNS ********/
/*********************************************************/
// Insert 200 columns in cassandra in a single row
int noOfColumns = 200;
Long key = 1234L;
for (int i = 1; i <= noOfColumns; i++) {
row.put("column_" + i, "value_" + i);
}
cassandraManager.updateRow(key, row);
/**
* ---------------| Retrieve all columns for the key (no of columns < 10000) |---------------
*/
// Retrieve all columns
CassandraResultSet<Long, String> result = cassandraManager.readColumnSliceAllColumns(key);
// Column count should be 200
assertEquals(noOfColumns, result.getColumnNames().size());
for (String columnName : row.keySet()) {
assertEquals(row.get(columnName), result.getString(columnName));
}
/**
* ---------------| Retrieve N columns for the key |---------------
*/
// Retrieve 120 columns
result = cassandraManager.readColumnSlice(key, null, null, false, 120);
// Column count should be 120
assertEquals(120, result.getColumnNames().size());
/**
* ---------------| Retrieve N columns with column range specified |---------------
*/
// Columns in a range with limit as 10
result = cassandraManager.readColumnSlice(key, "column_111", "column_113", false, 10);
// This range contains 3 columns, so the column count should be 3
assertEquals(3, result.getColumnNames().size());
assertEquals("value_111", result.getString("column_111"));
assertEquals("value_112", result.getString("column_112"));
assertEquals("value_113", result.getString("column_113"));
/**
* ---------------| Retrieve N columns with column range specified in reverse |---------------
*/
// Columns in a range with limit as 10
result = cassandraManager.readColumnSlice(key, "column_113", "column_111", true, 10);
// This range contains 3 columns, so the column count should be 3
assertEquals(3, result.getColumnNames().size());
assertEquals("value_111", result.getString("column_111"));
assertEquals("value_112", result.getString("column_112"));
assertEquals("value_113", result.getString("column_113"));
/*********************************************************/
/****** TEST CASSANDRA ROW CONTAINS < 100 COLUMNS ********/
/*********************************************************/
/**
* ---------------| Retrieve all columns for row with < 100 columns |---------------
*/
row.clear();
key = 5678L;
for (int i = 1; i <= 80; i++) { // < 100 columns (80 in this example)
row.put("column_" + i, "value_" + i);
}
cassandraManager.updateRow(key, row);
result = cassandraManager.readColumnSliceAllColumns(key);
// Column count should be 80
assertEquals(80, result.getColumnNames().size());
for (String columnName : row.keySet()) {
assertEquals(row.get(columnName), result.getString(columnName));
}
/**
* ---------------| Retrieve N columns for the key |---------------
*/
// Retrieve 50 columns
result = cassandraManager.readColumnSlice(key, null, null, false, 50);
// Column count should be 120
assertEquals(50, result.getColumnNames().size());
/**
* ---------------| Retrieve N columns with column range specified |---------------
*/
// Columns in a range with limit as 10
result = cassandraManager.readColumnSlice(key, "column_11", "column_13", false, 10);
// This range contains 3 columns, so the column count should be 3
assertEquals(3, result.getColumnNames().size());
assertEquals("value_11", result.getString("column_11"));
assertEquals("value_12", result.getString("column_12"));
assertEquals("value_13", result.getString("column_13"));
/**
* ---------------| Retrieve N columns with column range specified in reverse |---------------
*/
result = cassandraManager.readColumnSlice(key, "column_13", "column_11", true, 10);
// This range contains 3 columns, so the column count should be 3
assertEquals(3, result.getColumnNames().size());
assertEquals("value_11", result.getString("column_11"));
assertEquals("value_12", result.getString("column_12"));
assertEquals("value_13", result.getString("column_13"));
/*************************************************************/
/****** TEST CASSANDRA ROW DOES NOT EXIST (CACHE MISS) *******/
/*************************************************************/
row.clear();
key = 9999L;
result = cassandraManager.readColumnSliceAllColumns(key);
assertEquals(0, result.getColumnNames().size());
result = cassandraManager.readColumnSlice(key, null, null, false, 50);
assertEquals(0, result.getColumnNames().size());
result = cassandraManager.readColumnSlice(key, "column_11", "column_13", false, 10);
assertEquals(0, result.getColumnNames().size());
}
@Test
public void testReadColumnSliceMultipleKeys() throws Exception {
logger.info("Testing Hector read column slice with multiple keys");
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
HashMap<String, Object> row1 = new HashMap<String, Object>();
/**********************************************************/
/****** TEST CASSANDRA ROWS CONTAINS > 100 COLUMNS ********/
/**********************************************************/
Long key1 = 1234L;
// Insert 200 columns in cassandra for key1
for (int i = 1; i <= 200; i++) {
row1.put("column_" + i, "value_" + i);
}
cassandraManager.updateRow(key1, row1);
// Insert 150 columns in cassandra for key2
HashMap<String, Object> row2 = new HashMap<String, Object>();
Long key2 = 5678L;
for (int i = 1; i <= 150; i++) {
row2.put("column_" + i, "value_" + i);
}
cassandraManager.updateRow(key2, row2);
Set<Long> keys = new HashSet<Long>();
keys.add(key1);
keys.add(key2);
/**
* ___________________________________________________________ | Retrieve all columns for all keys (no of columns < 10000)
* -----------------------------------------------------------
*/
CassandraResultSet<Long, String> result = cassandraManager.readColumnSliceAllColumns(keys);
Set<Long> keysCopy = new HashSet<Long>(keys);
int count = 0;
assertNotNull(result);
/**
* NOTE: We are using [while(true) --> break] loop here because CassandraResultSet points to the first row when its created. CassandraResultSet.hasNextResult returns true
* if there are any more rows and CassandraResultSet.nextResult () moves the pointer to the next row. So in the loop, we needed the processing --> check break condition -->
* move the pointer.
*/
while (true) {
count++;
assertEquals(true, keysCopy.remove(result.getKey()));
if (key1.equals(result.getKey())) {
// Column count should be 200
assertEquals(200, result.getColumnNames().size());
for (String columnName : row1.keySet()) {
assertEquals(row1.get(columnName), result.getString(columnName));
}
} else if (key2.equals(result.getKey())) {
// Column count should be 150
assertEquals(150, result.getColumnNames().size());
for (String columnName : row2.keySet()) {
assertEquals(row2.get(columnName), result.getString(columnName));
}
}
if (!result.hasNextResult()) {
break;
}
result.nextResult();
}
assertEquals(keys.size(), count); // Asserts the result set contains exactly same number of rows as is the
// keys size
assertEquals(0, keysCopy.size()); // Asserts we get both the keys in the result set
/*************************************************************************/
/****** TEST CASSANDRA ROWS CONTAINS < 100 COLUMNS + A MISS ROW ********/
/*************************************************************************/
cassandraManager.deleteRow(key1);
cassandraManager.deleteRow(key2);
long key3 = 9999L;
keys.add(key3);
row1.clear();
for (int i = 1; i <= 80; i++) {
row1.put("column_" + i, "value_" + i);
}
cassandraManager.updateRow(key1, row1);
row2.clear();
for (int i = 1; i <= 60; i++) {
row2.put("column_" + i, "value_" + i);
}
cassandraManager.updateRow(key2, row2);
/**
* ____________________________________ | Retrieve all columns for all keys ------------------------------------
*/
result = cassandraManager.readColumnSliceAllColumns(keys);
keysCopy = new HashSet<Long>(keys);
count = 0;
assertNotNull(result);
/**
* NOTE: We are using [while(true) --> break] loop here because CassandraResultSet points to the first row when its created. CassandraResultSet.hasNextResult returns true
* if there are any more rows and CassandraResultSet.nextResult () moves the pointer to the next row. So in the loop, we needed the processing --> check break condition -->
* move the pointer.
*/
while (true) {
if (result.getColumnNames().size() > 0) {
// Only count rows that actually contain results
count++;
}
assertEquals(true, keysCopy.remove(result.getKey()));
if (result.getKey().equals(key1)) {
// Column count should be 80
assertEquals(80, result.getColumnNames().size());
for (String columnName : row1.keySet()) {
assertEquals(row1.get(columnName), result.getString(columnName));
}
} else if (result.getKey().equals(key2)) {
// Column count should be 60
assertEquals(60, result.getColumnNames().size());
for (String columnName : row2.keySet()) {
assertEquals(row2.get(columnName), result.getString(columnName));
}
} else if (result.getKey().equals(key3)) {
// Column count should be 0 since key3 doesn't exist
assertEquals(0, result.getColumnNames().size());
}
if (!result.hasNextResult()) {
break;
}
result.nextResult();
}
assertEquals(2, count); // Asserts 2 rows contained data
if (keysCopy.size() == 1) {
// key3 did not exist in cassandra so CQL will not return it
assertTrue(keysCopy.contains(key3));
} else {
assertEquals(0, keysCopy.size()); // Asserts we get all the keys in the result set
}
}
@Test
public void testReadAllColumns() throws Exception {
logger.info("Testing Hector readAllColumns for single key");
CassandraParamsBean bean = getDefaultCassandraParamsBean();
HecubaClientManager<Long> cassandraManager = getHecubaClientManager(bean);
Map<String, Object> row = new HashMap<String, Object>();
/*********************************************************/
/****** TEST CASSANDRA ROW CONTAINS > 100 COLUMNS ********/
/*********************************************************/
// Insert 200 columns in cassandra in a single row
int noOfColumns = 200;
Long key = 1234L;
for (int i = 1; i <= noOfColumns; i++) {
row.put("column_" + i, "value_" + i);
if (i <= 100) {
}
}
cassandraManager.updateRow(key, row);
/**
* ___________________________________ | Retrieve all columns for the key -----------------------------------
*/
// set maxColumnCount to 200 since there 200 columns in test row
bean.setMaxColumnCount(200);
// re-create cassandra manager with maxColumnCount set
cassandraManager = getHecubaClientManager(bean);
CassandraResultSet<Long, String> result = cassandraManager.readAllColumns(key);
assertEquals(200, result.getColumnNames().size());
for (String columnName : row.keySet()) {
assertEquals(row.get(columnName), result.getString(columnName));
}
}
@Test
public void testReadColumnsMultipleKeys() throws Exception {
logger.info("Testing readColumns with multiple keys");
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
/***********************************/
/****** TEST CASSANDRA ROWS ********/
/***********************************/
Map<Long, Map<String, Object>> dataSet = new HashMap<Long, Map<String, Object>>();
int noOfColumns = 50;
Random randomGen = new Random();
for (int k = 1; k <= 30; k++) {
Long key = (long) randomGen.nextInt(99999999);
Map<String, Object> rowData = new HashMap<String, Object>();
for (int i = 1; i <= noOfColumns; i++) {
rowData.put("column_" + i, "value_" + (i + key));
}
cassandraManager.updateRow(key, rowData);
dataSet.put(key, rowData);
}
int noOfKeysToFetch = 20;
int count = 0;
Set<Long> keys = new HashSet<Long>();
for (Long key : dataSet.keySet()) { // Prepare set of 20 keys to fetch
keys.add(key);
count++;
if (count >= noOfKeysToFetch) {
break;
}
}
final List<String> emptyColumnNamesList = Collections.<String> emptyList();
final Set<Long> emptyKeysSet = Collections.<Long> emptySet();
/**
* CASE 1 _______________________________________________________________ | Retrieve non-empty set of columns for non-empty set of keys |
* ---------------------------------------------------------------
*/
List<String> columnNames = new ArrayList<String>();
for (int i = 11; i <= 35; i++) { // Prepare set of 25 columns to fetch
columnNames.add("column_" + i);
}
CassandraResultSet<Long, String> result = cassandraManager.readColumns(keys, columnNames);
assertCassandraResultSet(result, dataSet, keys, columnNames);
/**
* CASE 2 ______________________________________________ | Empty set of keys and empty set of columns | ----------------------------------------------
*/
result = cassandraManager.readColumns(emptyKeysSet, emptyColumnNamesList);
assertEmptyCassandraResultSet(result);
/**
* CASE 3 ______________________________________________ | Empty set of keys but valid set of columns | ----------------------------------------------
*/
result = cassandraManager.readColumns(emptyKeysSet, columnNames);
assertEmptyCassandraResultSet(result);
/**
* CASE 4 ______________________________________________ | Valid set of keys but empty set of columns | ----------------------------------------------
*/
List<String> allColumnNames = new ArrayList<String>();
for (int i = 1; i <= noOfColumns; i++) {
allColumnNames.add("column_" + i);
}
result = cassandraManager.readColumns(keys, emptyColumnNamesList);
assertCassandraResultSet(result, dataSet, keys, allColumnNames); // should return all columns
/**
* CASE 5 _____________________________________ | Valid set of keys and all columns | -------------------------------------
*/
result = cassandraManager.readColumns(keys, allColumnNames);
assertCassandraResultSet(result, dataSet, keys, allColumnNames); // should return all columns
/**
* CASE 6 ____________________________ | All keys and all columns | ----------------------------
*/
result = cassandraManager.readColumns(dataSet.keySet(), allColumnNames);
assertCassandraResultSet(result, dataSet, dataSet.keySet(), allColumnNames); // should return all columns
/**
* CASE 7 ____________________________ | 1 key and all columns | ----------------------------
*/
Set<Long> oneKey = new HashSet<Long>();
oneKey.add(dataSet.keySet().iterator().next());
result = cassandraManager.readColumns(oneKey, allColumnNames);
assertCassandraResultSet(result, dataSet, oneKey, allColumnNames); // should return all columns
/**
* CASE 8 __________________________________ | 1 key and valid set of columns | ----------------------------------
*/
result = cassandraManager.readColumns(oneKey, columnNames);
assertCassandraResultSet(result, dataSet, oneKey, columnNames);
/**
* CASE 9 __________________________________ | 1 key and empty set of columns | ----------------------------------
*/
result = cassandraManager.readColumns(oneKey, emptyColumnNamesList);
assertCassandraResultSet(result, dataSet, oneKey, allColumnNames); // should return all columns
/**
* CASE 10 _____________________________ | 1 key and null columnList | -----------------------------
*/
result = cassandraManager.readColumns(oneKey, null);
assertCassandraResultSet(result, dataSet, oneKey, allColumnNames); // should return all columns
/**
* CASE 11 _________________________________________ | valid set of keys and null columnList | -----------------------------------------
*/
result = cassandraManager.readColumns(keys, null);
assertCassandraResultSet(result, dataSet, keys, allColumnNames); // should return all columns
}
private <K, N> void assertCassandraResultSet(CassandraResultSet<K, N> result, Map<K, Map<N, Object>> dataSet, Set<K> fetchedKeys, List<N> fetchedColumns) {
assertNotNull(result);
assertTrue(result.hasResults());
assertFalse(CollectionUtils.isEmpty(result.getColumnNames()));
Set<K> keysCopy = new HashSet<K>(fetchedKeys);
int count = 0;
/**
* NOTE: We are using [while(true) --> break] loop here because CassandraResultSet points to the first row when its created. CassandraResultSet.hasNextResult returns true
* if there are any more rows and CassandraResultSet.nextResult() moves the pointer to the next row. So in the loop, we needed the processing --> check break condition -->
* move the pointer.
*/
while (true) {
K key = result.getKey();
count++;
assertEquals(true, keysCopy.remove(key));
assertEquals(fetchedColumns.size(), result.getColumnNames().size());
for (N columnName : fetchedColumns) {
Object expectedValue = dataSet.get(key).get(columnName);
assertNotNull(expectedValue);
assertEquals(expectedValue, result.getString(columnName));
}
if (!result.hasNextResult()) {
break;
}
result.nextResult();
}
assertEquals(fetchedKeys.size(), count); // Asserts the result set contains exactly same number of rows as is the fetchedKeys size
assertEquals(0, keysCopy.size()); // Asserts we get all the keys in the result set
}
private <K, N> void assertEmptyCassandraResultSet(CassandraResultSet<K, N> result) {
assertNotNull(result);
assertFalse(result.hasResults());
assertTrue(CollectionUtils.isEmpty(result.getColumnNames()));
}
/**
* testSecondaryIndexWithUpdatesToSingleColumn
*/
@Test
public void testUpdateRowScenario13() {
CassandraParamsBean bean = getDefaultCassandraParamsBean();
bean.setSiColumns("MySecondaryKey_1:MySecondaryKey_2");
HecubaClientManager<Long> cassandraManager = getHecubaClientManager(bean);
cassandraManager.updateString(1234L, "test_column", "test_value");
// add a secondary index column, for the first time.
cassandraManager.updateString(1234L, "MySecondaryKey_1", "SecondaryIndexValue");
/**
* __________________________________________ | MySecondaryKey_1:SecondaryIndexValue | --> 1234 ------------------------------------------
*/
// try to retrieve that by its id.
CassandraResultSet<Long, String> resultFromFirstRetrieval = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "SecondaryIndexValue");
// result should have the id 1234L
assertNotNull(resultFromFirstRetrieval);
assertEquals(new Long(1234), resultFromFirstRetrieval.getKey());
// And that should have other columns too.
assertEquals("test_value", resultFromFirstRetrieval.getString("test_column"));
// add another row with the same value for the secondary index
cassandraManager.updateString(1233L, "MySecondaryKey_1", "SecondaryIndexValue");
cassandraManager.updateString(1233L, "test_column", "test_value_2");
/**
* __________________________________________ | MySecondaryKey_1:SecondaryIndexValue | --> 1234, 1233 ------------------------------------------
*/
// 2. And that should have the id 1234L and 1233L
resultFromFirstRetrieval = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "SecondaryIndexValue");
List<String> items = new ArrayList<String>();
assertTrue(resultFromFirstRetrieval != null);
// get first result.
items.add(resultFromFirstRetrieval.getString("test_column"));
while (resultFromFirstRetrieval.hasNextResult()) {
resultFromFirstRetrieval.nextResult();
items.add(resultFromFirstRetrieval.getString("test_column"));
}
assertEquals(items.size(), 2);
// Since we can't really check each items, since order is not guaranteed.
Collections.sort(items);
assertTrue(Collections.binarySearch(items, "test_value_2") >= 0);
assertTrue(Collections.binarySearch(items, "test_value") >= 0);
// 3. And that should have other columns too.
cassandraManager.updateString(1233L, "MySecondaryKey_1", "SecondaryIndexValue_2");
/**
* __________________________________________ | MySecondaryKey_1:SecondaryIndexValue | --> 1234 ------------------------------------------
*
* ____________________________________________ | MySecondaryKey_1:SecondaryIndexValue_2 | --> 1233 --------------------------------------------
*/
// retrieve the row from the new secondary value
CassandraResultSet<Long, String> resultFromThirdRetrieval = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "SecondaryIndexValue_2");
// 1. we should have retrieved only one.
assertEquals(false, resultFromThirdRetrieval.hasNextResult());
// 2. And that should have the id 1233L
assertEquals(new Long(1233), resultFromThirdRetrieval.getKey());
// 3. And that should have other columns too.
assertEquals("test_value_2", resultFromThirdRetrieval.getString("test_column"));
// try to retrieve from the previous one and see whether it returns only one.
CassandraResultSet<Long, String> resultFromFourthRetrieval = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "SecondaryIndexValue");
// 2. And that should have the id 1234L and 1233L
assertEquals(new Long(1234), resultFromFourthRetrieval.getKey());
// change the value of the secondary index for the first row above and see whether the initial query returns
// anything now.
cassandraManager.updateString(1234L, "MySecondaryKey_1", "SecondaryIndexValue_3");
/**
* __________________________________________ | MySecondaryKey_1:SecondaryIndexValue | --> ------------------------------------------
*
* ____________________________________________ | MySecondaryKey_1:SecondaryIndexValue_2 | --> 1233 --------------------------------------------
*
* ____________________________________________ | MySecondaryKey_1:SecondaryIndexValue_3 | --> 1234 --------------------------------------------
*
*/
CassandraResultSet<Long, String> resultFromFifthRetrieval = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "SecondaryIndexValue");
assertEquals(null, resultFromFifthRetrieval);
resultFromFifthRetrieval = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "SecondaryIndexValue_2");
// 1. we should have retrieved one
assertEquals(false, resultFromFifthRetrieval.hasNextResult());
resultFromFifthRetrieval = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "SecondaryIndexValue_3");
// 1. we should have retrieved one
assertEquals(false, resultFromFifthRetrieval.hasNextResult());
}
@Test
public void testHecubaClientManager() {
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
assertEquals(CLUSTER_NAME, cassandraManager.getClusterName());
assertEquals(LOCATION, cassandraManager.getLocationURL());
assertEquals(PORT, cassandraManager.getPort());
assertEquals(KEYSPACE, cassandraManager.getKeyspace());
}
@Test
public void testUpdateString() {
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
cassandraManager.updateString(1234L, "test_column", "test_value");
assertEquals("test_value", cassandraManager.readString(1234L, "test_column"));
// Test non-string column name
cassandraManager.updateString(1234L, "987654321", "test_value2");
assertEquals("test_value2", cassandraManager.readString(1234L, "987654321"));
}
@Test
public void testUpdateBoolean() {
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
cassandraManager.updateBoolean(1234L, "test_column_1", false);
assertEquals(Boolean.FALSE, cassandraManager.readBoolean(1234L, "test_column_1"));
cassandraManager.updateBoolean(1234L, "test_column_2", true);
assertEquals(Boolean.TRUE, cassandraManager.readBoolean(1234L, "test_column_2"));
}
@Test
public void testUpdateDate() {
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
Date date = new Date();
cassandraManager.updateDate(1234L, "test_column_1", date);
Date actualDate = cassandraManager.readDate(1234L, "test_column_1");
assertEquals(HecubaConstants.DATE_FORMATTER.print(date.getTime()), HecubaConstants.DATE_FORMATTER.print(actualDate.getTime()));
}
@Test
public void testUpdateDouble() {
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
cassandraManager.updateDouble(1234L, "test_column_1", 0.0);
assertTrue(0.0 == cassandraManager.readDouble(1234L, "test_column_1"));
cassandraManager.updateDouble(1234L, "test_column_2", 1245.1245);
assertTrue(1245.1245 == cassandraManager.readDouble(1234L, "test_column_2"));
cassandraManager.updateDouble(1234L, "test_column_3", -1.55);
assertTrue(-1.55 == cassandraManager.readDouble(1234L, "test_column_3"));
}
@Test
public void testUpdateLong() {
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
cassandraManager.updateLong(1234L, "test_column_1", 0L);
assertTrue(0L == cassandraManager.readLong(1234L, "test_column_1"));
cassandraManager.updateLong(1234L, "test_column_2", 123456789123456789L);
assertTrue(123456789123456789L == cassandraManager.readLong(1234L, "test_column_2"));
cassandraManager.updateLong(1234L, "test_column_3", -112233445566778899L);
assertTrue(-112233445566778899L == cassandraManager.readLong(1234L, "test_column_3"));
}
@Test
public void testUpdateInteger() {
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
cassandraManager.updateInteger(1234L, "test_column_1", 0);
assertTrue(0.0 == cassandraManager.readDouble(1234L, "test_column_1"));
cassandraManager.updateInteger(1234L, "test_column_2", 1245);
assertTrue(1245 == cassandraManager.readDouble(1234L, "test_column_2"));
cassandraManager.updateInteger(1234L, "test_column_3", -1456);
assertTrue(-1456 == cassandraManager.readDouble(1234L, "test_column_3"));
}
@Test
public void testUpdateRow() throws Exception {
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
// First lets add new columns and check it.
Date currentDate = new Date();
Map<String, Object> columnValues = new HashMap<String, Object>();
columnValues.put("test_column_1", new Integer(0));
columnValues.put("test_column_2", new Integer(6));
columnValues.put("test_column_3", "Nextag");
columnValues.put("test_column_4", 12112.121);
columnValues.put("test_column_5", currentDate);
cassandraManager.updateRow(12312L, columnValues);
assertEquals(new Integer(0), cassandraManager.readInteger(12312L, "test_column_1"));
assertEquals(new Integer(6), cassandraManager.readInteger(12312L, "test_column_2"));
assertEquals("Nextag", cassandraManager.readString(12312L, "test_column_3"));
assertEquals(new Double(12112.121), cassandraManager.readDouble(12312L, "test_column_4"));
assertEquals(HecubaConstants.DATE_FORMATTER.print(currentDate.getTime()),
HecubaConstants.DATE_FORMATTER.print(cassandraManager.readDate(12312L, "test_column_5").getTime()));
// Now lets update certain columns and test it.
columnValues = new HashMap<String, Object>();
columnValues.put("test_column_1", new Integer(-1212));
columnValues.put("test_column_3", "Nextag Goes Live");
cassandraManager.updateRow(12312L, columnValues);
assertEquals(new Integer(-1212), cassandraManager.readInteger(12312L, "test_column_1"));
assertEquals("Nextag Goes Live", cassandraManager.readString(12312L, "test_column_3"));
}
@Test
public void testDeleteColumn() {
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
cassandraManager.updateString(1234L, "test_column", "test_value");
assertEquals("test_value", cassandraManager.readString(1234L, "test_column"));
cassandraManager.deleteColumn(1234L, "test_column");
assertEquals(null, cassandraManager.readString(1234L, "test_column"));
}
@Test
public void testDeleteRow() throws Exception {
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
// First lets add new columns and check it.
Date currentDate = new Date();
Map<String, Object> columnValues = new HashMap<String, Object>();
columnValues.put("test_column_1", new Integer(0));
columnValues.put("test_column_2", new Integer(6));
columnValues.put("test_column_3", "Nextag");
columnValues.put("test_column_4", 12112.121);
columnValues.put("test_column_5", currentDate);
cassandraManager.updateRow(12312L, columnValues);
// Just make sure we have the added row.
assertEquals(new Integer(0), cassandraManager.readInteger(12312L, "test_column_1"));
assertEquals(new Integer(6), cassandraManager.readInteger(12312L, "test_column_2"));
assertEquals("Nextag", cassandraManager.readString(12312L, "test_column_3"));
assertEquals(new Double(12112.121), cassandraManager.readDouble(12312L, "test_column_4"));
assertEquals(HecubaConstants.DATE_FORMATTER.print(currentDate.getTime()),
HecubaConstants.DATE_FORMATTER.print(cassandraManager.readDate(12312L, "test_column_5").getTime()));
// Now lets remove the entire row.
cassandraManager.deleteRow(12312L);
assertEquals(new Integer(-1), cassandraManager.readInteger(12312L, "test_column_1", -1));
assertEquals(null, cassandraManager.readString(12312L, "test_column_3"));
}
/**
* testUpdateStringWithNoTimestampOrTTL
*/
@Test
public void testUpdateRowScenario12() {
final HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
final long objectId = 1234L;
cassandraManager.updateString(objectId, "test_column", "test_value", -1, -1);
final CassandraColumn testColumn = cassandraManager.readColumnInfo(objectId, "test_column");
assertEquals("test_value", testColumn.getValue());
compareDates(System.currentTimeMillis(), convertToJavaTimestamp(testColumn.getTimestamp()));
assertEquals(0, testColumn.getTtl());
assertEquals("test_column", testColumn.getName());
}
private void compareDates(long expected, long actual) {
Date expectedDate = new Date(expected);
Date actualDate = new Date(actual);
assertTrue(DateUtils.isSameDay(expectedDate, actualDate));
}
private long convertToJavaTimestamp(long cassandraTimestamp) {
return cassandraTimestamp / 1000;
}
/**
* testUpdateStringWithTimestampOnly
*/
@Test
public void testUpdateRowScenario11() {
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
final long timestamp = new GregorianCalendar(2006, 8, 4).getTimeInMillis();
cassandraManager.updateString(1234L, "test_column", "test_value", timestamp, -1);
final CassandraColumn testColumn = cassandraManager.readColumnInfo(1234L, "test_column");
assertEquals("test_value", testColumn.getValue());
compareDates(timestamp, testColumn.getTimestamp());
assertEquals(0, testColumn.getTtl());
assertEquals("test_column", testColumn.getName());
}
/**
* testUpdateStringWithTTLOnly
*/
@Test
public void testUpdateRowScenario10() {
final HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
final long objectId = 1234L;
final int ttl = 2;
cassandraManager.updateString(objectId, "test_column", "test_value", -1, ttl);
// assuming this executed within 3 seconds, we should get a result.
CassandraColumn testColumn = cassandraManager.readColumnInfo(objectId, "test_column");
assertEquals("test_value", testColumn.getValue());
// since we don't know what the set timestamp is, we are leaving the delta to be the time difference between
// now and when we did the insertion.
compareDates(System.currentTimeMillis(), convertToJavaTimestamp(testColumn.getTimestamp()));
assertEquals(ttl, testColumn.getTtl());
assertEquals("test_column", testColumn.getName());
// lets wait for ttl and see whether this has expired.
try {
Thread.sleep(1000 * (ttl + 1));
} catch (InterruptedException e) {
e.printStackTrace();
}
testColumn = cassandraManager.readColumnInfo(objectId, "test_column");
assertNull(testColumn);
}
/**
* testUpdateStringWithBothTimestampAndTTL
*/
@Test
public void testUpdateRowScenario9() {
final HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
final long objectId = 1234L;
final int ttl = 2;
cassandraManager.updateString(objectId, "test_column", "test_value", 500, ttl);
// assuming this executed within 2 seconds, we should get a result.
final CassandraColumn testColumn = cassandraManager.readColumnInfo(objectId, "test_column");
assertEquals("test_value", testColumn.getValue());
assertEquals(500, testColumn.getTimestamp());
int actualTTL = testColumn.getTtl();
// TTL should be within 2 seconds of each other (CQL returns remaining time to live)
assertTrue(Math.abs(ttl - actualTTL) < 2);
assertEquals("test_column", testColumn.getName());
}
/**
* testUpdateStringWithBothTimpstampsAndTTLSetToNegative
*/
@Test
public void testUpdateRowScenario8() {
final HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
final long objectId = 1234L;
cassandraManager.updateString(objectId, "test_column", "test_value", -100, -2000);
final CassandraColumn testColumn = cassandraManager.readColumnInfo(objectId, "test_column");
assertEquals("test_value", testColumn.getValue());
compareDates(System.currentTimeMillis(), convertToJavaTimestamp(testColumn.getTimestamp()));
assertEquals(0, testColumn.getTtl());
assertEquals("test_column", testColumn.getName());
}
/**
* testUpdateRowWithBothTimpStampAndTTLSetToNull
*
* @throws Exception
*/
@Test
public void testUpdateRowScenario7() throws Exception {
testUpdateRowResults(null, null, "testUpdateRowScenario7");
}
/**
* testUpdateRowWithBothTimpStampAndTTLSetToEmptyMaps
*
* @throws Exception
*/
@Test
public void testUpdateRowScenario6() throws Exception {
testUpdateRowResults(new HashMap<String, Long>(), new HashMap<String, Integer>(), "testUpdateRowScenario6");
}
private void testUpdateRowResults(Map<String, Long> timestamps, Map<String, Integer> ttls, String columnFamily) throws Exception {
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
final long objectId = 1234L;
Map<String, Object> columns = new HashMap<String, Object>();
for (int i = 0; i < 5; i++) {
columns.put("Column_" + i, "value_" + i);
}
cassandraManager.updateRow(objectId, columns, timestamps, ttls);
CassandraColumn testColumn = null;
for (String columnName : columns.keySet()) {
testColumn = cassandraManager.readColumnInfo(objectId, columnName);
assertEquals(columnName, testColumn.getName());
final boolean timeStampAvailable = timestamps != null && timestamps.get(columnName) != null && timestamps.get(columnName) > 0;
final long expected = timeStampAvailable ? timestamps.get(columnName) : System.currentTimeMillis();
final long actual = timeStampAvailable ? testColumn.getTimestamp() : convertToJavaTimestamp(testColumn.getTimestamp());
compareDates(expected, actual);
final boolean ttlAvailable = ttls != null && ttls.get(columnName) != null && ttls.get(columnName) > 0;
int expectedTTL = ttlAvailable ? ttls.get(columnName) : 0;
int actualTTL = testColumn.getTtl();
// TTL should be within 2 seconds of each other (CQL returns remaining time to live)
assertTrue(Math.abs(expectedTTL - actualTTL) < 2);
assertEquals(columns.get(columnName), testColumn.getValue());
}
}
/**
* testUpdateRowWithAllTimpStampsSetButNoTTL
*
* @throws Exception
*/
@Test
public void testUpdateRowScenario5() throws Exception {
Map<String, Long> timestamps = new HashMap<String, Long>();
Random random = new Random();
for (int i = 0; i < 5; i++) {
timestamps.put("Column_" + i, Math.abs(random.nextLong()));
}
testUpdateRowResults(timestamps, null, "testUpdateRowScenario5");
}
/**
* testUpdateRowWithSomeTimestampsSetButNoTTL
*
* @throws Exception
*/
@Test
public void testUpdateRowScenario4() throws Exception {
Map<String, Long> timestamps = new HashMap<String, Long>();
Random random = new Random();
timestamps.put("Column_2", Math.abs(random.nextLong()));
timestamps.put("Column_4", Math.abs(random.nextLong()));
testUpdateRowResults(timestamps, null, "testUpdateRowScenario4");
}
/**
* testUpdateRowWithAllTTLSetButNoTimestamp
*
* @throws Exception
*/
@Test
public void testUpdateRowScenario3() throws Exception {
Map<String, Integer> ttls = new HashMap<String, Integer>();
Random random = new Random();
for (int i = 0; i < 5; i++) {
ttls.put("Column_" + i, Math.abs(random.nextInt(TEN_YEARS) + 20));
}
testUpdateRowResults(null, ttls, "testUpdateRowScenario3");
}
/**
* testUpdateRowWithSomeTTLsSetButNoTimestamp
*
* @throws Exception
*/
@Test
public void testUpdateRowScenario2() throws Exception {
Map<String, Integer> ttls = new HashMap<String, Integer>();
Random random = new Random();
ttls.put("Column_1", Math.abs(random.nextInt(TEN_YEARS) + 20));
ttls.put("Column_3", Math.abs(random.nextInt(TEN_YEARS) + 20));
testUpdateRowResults(null, ttls, "testUpdateRowScenario2");
}
/**
* testUpdateRowWithAllTTLAndTimestampSet
*
* @throws Exception
*/
@Test
public void testUpdateRowScenario1() throws Exception {
Map<String, Integer> ttls = new HashMap<String, Integer>();
Map<String, Long> timestamps = new HashMap<String, Long>();
Random random = new Random();
for (int i = 0; i < 5; i++) {
ttls.put("Column_" + i, Math.abs(random.nextInt(TEN_YEARS) + 20));
timestamps.put("Column_" + i, Math.abs(random.nextLong()));
}
testUpdateRowResults(timestamps, ttls, "testUpdateRowScenario1");
}
/**
* test retrieval of only keys using secondary index
*
* @throws Exception
*/
@Test
public void testRetrieveSecondaryIdxKeys() throws Exception {
CassandraParamsBean bean = getDefaultCassandraParamsBean();
bean.setSiColumns("MySecondaryKey");
// retrieve the cassandra manager.
HecubaClientManager<Long> cassandraManager = getHecubaClientManager(bean);
// insert the record 1234L with columns having secondary indices.
HashMap<String, Object> row = new HashMap<>();
row.put("column_1", "value_11");
row.put("column_2", "value_12");
row.put("MySecondaryKey", "MySecondaryValue");
cassandraManager.updateRow(1234L, row);
row = new HashMap<>();
row.put("column_1", "value_21");
row.put("column_2", "value_22");
row.put("MySecondaryKey", "MySecondaryValue");
cassandraManager.updateRow(2345L, row);
row = new HashMap<>();
row.put("column_1", "value_31");
row.put("column_2", "value_32");
row.put("MySecondaryKey", "MySecondaryValue3");
cassandraManager.updateRow(3456L, row);
// now lets only keys using secondary index
final List<Long> keys = cassandraManager.retrieveKeysBySecondaryIndex("MySecondaryKey", "MySecondaryValue");
assertNotNull(keys);
assertEquals(2, keys.size());
assertEquals(new Long(1234L), keys.get(0));
assertEquals(new Long(2345L), keys.get(1));
// now retrieve keys for 2 columnValues (multi-get)
List<String> siColumnValues = new ArrayList<>();
siColumnValues.add("MySecondaryValue");
siColumnValues.add("MySecondaryValue3");
final Map<String, List<Long>> keysMap = cassandraManager.retrieveKeysBySecondaryIndex("MySecondaryKey", siColumnValues);
assertNotNull(keysMap);
assertEquals(2, keys.size());
assertNotNull(keysMap.get("MySecondaryValue"));
assertEquals(2, keysMap.get("MySecondaryValue").size());
assertEquals(new Long(1234L), keysMap.get("MySecondaryValue").get(0));
assertEquals(new Long(2345L), keysMap.get("MySecondaryValue").get(1));
assertNotNull(keysMap.get("MySecondaryValue3"));
assertEquals(1, keysMap.get("MySecondaryValue3").size());
assertEquals(new Long(3456L), keysMap.get("MySecondaryValue3").get(0));
}
/**
* test update of Row which contains column with TTL and that column is also a secondary index.
*
* @throws Exception
*/
@Test
public void testUpdateRowScenario17() throws Exception {
CassandraParamsBean bean = getDefaultCassandraParamsBean();
bean.setSiColumns("MySecondaryKey_1:MySecondaryKey_2");
// retrieve the cassandra manager.
HecubaClientManager<Long> cassandraManager = getHecubaClientManager(bean);
// insert the record 1234L with columns having secondary indices.
HashMap<String, Object> row = new HashMap<String, Object>();
row.put("column_1", "value_1");
row.put("column_2", "value_2");
row.put("MySecondaryKey_1", "MySecondaryKey_1_value_1");
row.put("MySecondaryKey_2", "MySecondaryKey_2_value_2");
// TTL on MySecondaryKey_1 of 1 sec
Map<String, Integer> ttls = new HashMap<String, Integer>();
ttls.put("MySecondaryKey_1", 2);
cassandraManager.updateRow(1234L, row, null, ttls);
// Sleep for MySecondaryKey_1 column (with 1 sec TTL) to expire
try {
Thread.sleep(1000 * (1 + ttls.get("MySecondaryKey_1")));
} catch (InterruptedException e) {
e.printStackTrace();
}
// now lets see whether we can retrieve this item by the secondary indices.
// Since MySecondaryKey_1 column is expired, it's secondary index should also expire
final CassandraResultSet<Long, String> resultSetRetrievedUsingSecondaryIdx1 = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", "MySecondaryKey_1_value_1");
assertNull(resultSetRetrievedUsingSecondaryIdx1);
// We should be able to retrieve using secondary index on MySecondaryKey_2
final CassandraResultSet<Long, String> resultSetRetrievedUsingSecondaryIdx2 = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_2", "MySecondaryKey_2_value_2");
assertNotNull(resultSetRetrievedUsingSecondaryIdx2);
assertNotNull(resultSetRetrievedUsingSecondaryIdx2.getColumnNames());
assertEquals(row.size() - 1, resultSetRetrievedUsingSecondaryIdx2.getColumnNames().size()); // MySecondaryKey_1 column is expired
for (String columnName : resultSetRetrievedUsingSecondaryIdx2.getColumnNames()) {
assertEquals(row.get(columnName), resultSetRetrievedUsingSecondaryIdx2.getString(columnName));
}
}
/**
* Ensure "null" is handled correctly
*
* @throws Exception
*/
@Test
public void testUpdateRowScenario18() throws Exception {
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
Map<String, Object> row = new HashMap<>();
row.put("null_column", "null");
row.put("another_null_column", null);
row.put("non_null_column", "some value");
cassandraManager.updateRow(1234L, row);
CassandraResultSet<Long, String> resultSet = cassandraManager.readAllColumns(1234L);
assertTrue(resultSet.hasResults());
assertEquals(resultSet.getColumnNames().size(), 3);
assertNull(resultSet.getString("null_column"));
assertNull(resultSet.getString("another_null_column"));
assertEquals(resultSet.getString("non_null_column"), "some value");
}
@Test
public void outOfOrderDeleteTest() throws Exception {
final long SECOND_KEY = 112233L;
HecubaClientManager<Long> cassandraManager = getHecubaClientManager();
Map<String, Object> rows = new HashMap<String, Object>();
rows.put("column1", "value1");
rows.put("column2", "value2");
rows.put("column3", "value3");
// add a new row to CF.
cassandraManager.updateRow(1234L, rows);
// delete it and make sure its gone.
cassandraManager.deleteRow(1234L);
CassandraResultSet<Long, String> longStringCassandraResultSet = cassandraManager.readAllColumns(1234L);
assertFalse(longStringCassandraResultSet.hasResults());
// now add another row to CF with multiple columns.
HashMap<String, Long> timestampMap = new HashMap<String, Long>();
long earlierTimestamp = System.currentTimeMillis();
for (String columnName : rows.keySet()) {
timestampMap.put(columnName, earlierTimestamp);
}
cassandraManager.updateRow(SECOND_KEY, rows, timestampMap, null);
Thread.sleep(100);
long timestamp = System.currentTimeMillis();
// send an update to that row with a new timestamp (say X)
cassandraManager.updateString(SECOND_KEY, "column1", "NewValue", timestamp, -1);
CassandraResultSet<Long, String> resultsBeforeDelete = cassandraManager.readAllColumns(SECOND_KEY);
assertNotNull(resultsBeforeDelete.getString("column2", null));
assertNotNull(resultsBeforeDelete.getString("column3", null));
assertTrue(resultsBeforeDelete.hasResults());
assertEquals("NewValue", resultsBeforeDelete.getString("column1"));
// send a delete to that row with a timestamp older than X.
cassandraManager.deleteRow(SECOND_KEY, timestamp - 5);
CassandraResultSet<Long, String> resultsAfterDelete = cassandraManager.readAllColumns(SECOND_KEY);
assertTrue(resultsAfterDelete.hasResults());
assertEquals("NewValue", resultsAfterDelete.getString("column1"));
assertNull(resultsAfterDelete.getString("column2", null));
assertNull(resultsAfterDelete.getString("column3", null));
}
@Test
public void testSecondaryIndexMultiGet() throws Exception {
CassandraParamsBean bean = getDefaultCassandraParamsBean();
bean.setSiColumns("MySecondaryKey_1:MySecondaryKey_2");
// Large SecondIndex result set.
HecubaClientManager<Long> cassandraManager = getHecubaClientManager(bean);
final int numberOfRecordsInserted = 25;
// Write 120 rows to cassandra, with the same secondary Index.
for (long i = 0; i < numberOfRecordsInserted; i++) {
HashMap<String, Object> row = new HashMap<>();
row.put("column_1", "value_1");
row.put("column_2", "value_2");
row.put("MySecondaryKey_1", i % 5);
cassandraManager.updateRow(i, row);
}
List<String> expectedSecondaryIndexValues = new ArrayList<>();
expectedSecondaryIndexValues.add("1");
expectedSecondaryIndexValues.add("2");
// try to retrieve data by secondaryIndex value.
CassandraResultSet<Long, String> results = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", expectedSecondaryIndexValues);
assertNotNull(results);
int count = 1;
while (results.hasNextResult()) {
results.nextResult();
count++;
}
assertEquals(numberOfRecordsInserted * 2 / 5, count);
// try to retrieve data by secondaryIndex value.
results = cassandraManager.retrieveBySecondaryIndex("MySecondaryKey_1", expectedSecondaryIndexValues);
// check the first one here.
assertTrue(results.hasResults());
Long key = results.getKey();
assertTrue((key % 5) == 1 || (key % 5) == 2);
while (results.hasNextResult()) {
results.nextResult();
key = results.getKey();
assertTrue((key % 5) == 1 || (key % 5) == 2);
}
}
@Override
protected List<String> getSecondaryIndexExcludeList() {
return null;
}
@Override
protected Map<String, String> getColumnValueTypeOverrides() {
return null;
}
}