org.rhq.server.metrics.migrator.workers.MetricsIndexMigrator.java Source code

Java tutorial

Introduction

Here is the source code for org.rhq.server.metrics.migrator.workers.MetricsIndexMigrator.java

Source

/*
 * RHQ Management Platform
 * Copyright 2013, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

package org.rhq.server.metrics.migrator.workers;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.ResultSetFuture;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;
import org.hibernate.StatelessSession;
import org.joda.time.DateTime;
import org.joda.time.Duration;

import org.rhq.server.metrics.DateTimeService;
import org.rhq.server.metrics.MetricsConfiguration;
import org.rhq.server.metrics.domain.MetricsTable;
import org.rhq.server.metrics.migrator.DataMigrator.DataMigratorConfiguration;

/**
 * @author Stefan Negrea
 *
 */
public class MetricsIndexMigrator extends AbstractMigrationWorker {
    private static final int MAX_SIZE = 3000;

    private final Log log = LogFactory.getLog(MetricsIndexMigrator.class);

    private final DateTimeService dateTimeService = new DateTimeService();
    private final MetricsConfiguration metricsConfiguration = new MetricsConfiguration();
    private final Map<Integer, Set<Long>> accumulator = new HashMap<Integer, Set<Long>>();

    private final MigrationTable table;
    private final DataMigratorConfiguration migratorConfiguration;

    private final long timeLimit;
    private final PreparedStatement updateMetricsIndex;
    private final Duration sliceDuration;
    private final boolean validAccumulatorTable;

    private int currentCount = 0;

    public MetricsIndexMigrator(MigrationTable table, DataMigratorConfiguration config) {
        this.table = table;
        this.migratorConfiguration = config;

        if (MigrationTable.RAW.equals(table) || MigrationTable.ONE_HOUR.equals(table)
                || MigrationTable.SIX_HOUR.equals(table)) {
            this.sliceDuration = this.getTimeSliceDuration(table);
            this.timeLimit = this.getLastAggregationTime(table) - this.sliceDuration.getMillis();
            this.updateMetricsIndex = config.getSession().prepare("INSERT INTO " + MetricsTable.INDEX + " "
                    + "(bucket, partition, time, schedule_id) " + "VALUES (?, ?, ?, ?) ");
            this.validAccumulatorTable = true;
        } else {
            this.timeLimit = Integer.MAX_VALUE;
            this.updateMetricsIndex = null;
            this.sliceDuration = null;
            this.validAccumulatorTable = false;
        }
    }

    public void add(int scheduleId, long timestamp) throws Exception {
        if (validAccumulatorTable && timeLimit <= timestamp) {
            long alignedTimeSlice = dateTimeService.getTimeSlice(timestamp, sliceDuration).getMillis();

            if (accumulator.containsKey(scheduleId)) {
                Set<Long> timestamps = accumulator.get(scheduleId);
                if (!timestamps.contains(alignedTimeSlice)) {
                    timestamps.add(alignedTimeSlice);

                    currentCount++;
                }
            } else {
                Set<Long> timestamps = new HashSet<Long>();
                timestamps.add(timestamp);
                accumulator.put(scheduleId, timestamps);

                currentCount++;
            }
        }

        if (currentCount > MAX_SIZE) {
            drain();
        }
    }

    public void drain() throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("Draining metrics index accumulator with " + currentCount + " entries");
        }

        List<ResultSetFuture> resultSetFutures = new ArrayList<ResultSetFuture>();

        for (Map.Entry<Integer, Set<Long>> entry : accumulator.entrySet()) {
            for (Long timestamp : entry.getValue()) {
                Integer scheduleId = entry.getKey();

                BoundStatement statement = updateMetricsIndex.bind(table.getAggregationBucket().toString(),
                        (scheduleId % metricsConfiguration.getIndexPartitions()), new Date(timestamp), scheduleId);

                resultSetFutures.add(migratorConfiguration.getSession().executeAsync(statement));
            }
        }

        for (ResultSetFuture future : resultSetFutures) {
            future.get();
        }

        accumulator.clear();
        currentCount = 0;
    }

    private long getLastAggregationTime(MigrationTable migratedTable) {
        StatelessSession session = getSQLSession(migratorConfiguration);

        long aggregationSlice = Integer.MAX_VALUE;
        Duration duration = null;
        String queryString = null;

        if (MigrationTable.RAW.equals(migratedTable)) {
            duration = metricsConfiguration.getRawTimeSliceDuration();
            queryString = MigrationQuery.MAX_TIMESTAMP_1H_DATA.toString();
        } else if (MigrationTable.ONE_HOUR.equals(migratedTable)) {
            duration = metricsConfiguration.getOneHourTimeSliceDuration();
            queryString = MigrationQuery.MAX_TIMESTAMP_6H_DATA.toString();
        } else if (MigrationTable.SIX_HOUR.equals(migratedTable)) {
            duration = metricsConfiguration.getSixHourTimeSliceDuration();
            queryString = MigrationQuery.MAX_TIMESTAMP_1D_DATA.toString();
        }

        if (duration != null && queryString != null) {
            Query query = session.createSQLQuery(queryString);

            Long timeStamp;
            Object result = query.uniqueResult();
            if (result != null) {
                String queryResult = query.uniqueResult().toString();
                Long timestamp = Long.parseLong(queryResult);
                aggregationSlice = dateTimeService.getTimeSlice(new DateTime(timestamp), duration).getMillis();
            }
        }

        closeSQLSession(session);

        return aggregationSlice;
    }

    public Duration getTimeSliceDuration(MigrationTable table) {
        if (MigrationTable.RAW.equals(table)) {
            return metricsConfiguration.getRawTimeSliceDuration();
        } else if (MigrationTable.ONE_HOUR.equals(table)) {
            return metricsConfiguration.getOneHourTimeSliceDuration();
        } else if (MigrationTable.SIX_HOUR.equals(table)) {
            return metricsConfiguration.getSixHourTimeSliceDuration();
        }

        throw new IllegalArgumentException(
                "Time slice duration for " + table.getTableName() + " table is not supported");
    }
}