/* * 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; } }