package org.rhq.cassandra.schema; import java.util.Set; import com.datastax.driver.core.BoundStatement; import com.datastax.driver.core.PreparedStatement; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; import com.datastax.driver.core.Session; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.joda.time.DateTime; import org.joda.time.Days; import org.joda.time.Duration; import org.joda.time.Hours; /** * @author John Sanda */ public class Replace412Index { private static final Log log = LogFactory.getLog(Replace412Index.class); private static final int NUM_PARTITIONS = 10; private static final int PAGE_SIZE = Integer.parseInt(System.getProperty("rhq.metrics.index.page-size", "2500")); private Session session; private PreparedStatement find412IndexEntries; private PreparedStatement find412IndexEntriesAfterScheduleId; private PreparedStatement updateNewIndex; public Replace412Index(Session session) { this.session = session; } public void execute(DateRanges dateRanges) { initPreparedStatements(); DateTime startDay = dateRanges.sixHourStartTime; updateRawIndex(dateRanges.rawStartTime, dateRanges.rawEndTime, startDay); update1HourIndex(dateRanges.oneHourStartTime, dateRanges.oneHourEndTime, startDay); update6HourIndex(dateRanges.sixHourStartTime, dateRanges.sixHourEndTime, startDay); dropTables("rhq.metrics_cache", "rhq.metrics_cache_index"); } private void initPreparedStatements() { find412IndexEntries = session.prepare( "SELECT day, start_schedule_id, schedule_ids FROM rhq.metrics_cache_index WHERE bucket = ? " + "AND partition = 0 AND day = ? AND collection_time_slice = ? LIMIT " + PAGE_SIZE); find412IndexEntriesAfterScheduleId = session.prepare( "SELECT day, start_schedule_id, schedule_ids FROM rhq.metrics_cache_index WHERE bucket = ? " + "AND partition = 0 AND day = ? AND collection_time_slice = ? AND start_schedule_id > ? LIMIT " + PAGE_SIZE); updateNewIndex = session.prepare( "INSERT INTO rhq.metrics_idx (bucket, partition, time, schedule_id) VALUES (?, ?, ?, ?)"); } private void updateRawIndex(DateTime start, DateTime end, DateTime startDay) { log.info("Updating raw index"); updateIndex("raw_metrics", "raw", startDay, start, end, Hours.ONE.toStandardDuration()); } private void update1HourIndex(DateTime start, DateTime end, DateTime startDay) { log.info("Updating one_hour index"); updateIndex("one_hour_metrics", "one_hour", startDay, start, end, Hours.SIX.toStandardDuration()); } private void update6HourIndex(DateTime start, DateTime end, DateTime startDay) { log.info("Updating six_hour index"); updateIndex("six_hour_metrics", "six_hour", startDay, start, end, Days.ONE.toStandardDuration()); } private void updateIndex(String oldBucket, String newBucket, DateTime startDay, DateTime start, DateTime end, Duration timeSlice) { DateTime time = start; BoundStatement statement = find412IndexEntries.bind(oldBucket, startDay.toDate(), start.toDate()); ResultSet resultSet = session.execute(statement); DateTime day = startDay; int startScheduleId = 0; int count = 0; int partition = 0; do { for (Row row : resultSet) { day = new DateTime(row.getDate(0)); startScheduleId = row.getInt(1); Set<Integer> scheduleIds = row.getSet(2, Integer.class); ++count; for (Integer scheduleId : scheduleIds) { partition = (scheduleId % NUM_PARTITIONS); session.execute(updateNewIndex.bind(newBucket, partition, DateUtils.getUTCTimeSlice(time, timeSlice).toDate(), scheduleId)); } } if (count < PAGE_SIZE) { time = DateUtils.plusDSTAware(time, timeSlice); DateTime tempDay = DateUtils.plusDSTAware(day, Days.ONE.toStandardDuration()); if (time.equals(tempDay)) { day = DateUtils.plusDSTAware(day, Days.ONE.toStandardDuration()); } statement = find412IndexEntries.bind(oldBucket, day.toDate(), time.toDate()); } else { statement = find412IndexEntriesAfterScheduleId.bind(oldBucket, day.toDate(), time.toDate(), startScheduleId); } count = 0; resultSet = session.execute(statement); } while (!time.isAfter(end)); } private void dropTables(String... tables) { for (String table : tables) { log.info("Dropping table " + table); session.execute("DROP table " + table); } } }