first cut at metrics_cache table which replaces metrics_index table

The number of reads performed during aggregation grow linearly in proportion to
the number of schedules with data to be aggregated. In the worst case scenario
when 1 hr and 6 hr data are aggregated along with raw data, the number of reads
is 3 * N where N is the number of schedules. If there are a million schedules
with data, then a million reads have to be performed just to aggregate the raw
data.

The new metrics_cache table allows us to dramatically reduce the number of
reads. When raw data for example is stored it is now written to both the
raw_data table as well as the metrics_cache table. A single partition, i.e.,
row, in metrics_cache contains data for some configurable number of schedules.
Right now it defaults to 100. Each partition in metrics_cache contains data
only for a given time slice, e.g., 18:00 to 19:00. Once aggregation has run for
that time slice, the partition is deleted.

If we have a million schedules with raw data and 100 schedules are being stored
per partition in metrics_cache, then the number of reads drops from 1 million
to 10,000. That is a 99% reduction in the number of reads. And this reduction
will not come with a sharp increase in memory utilization.

Some refactoring and fixing bug in TaskTracker

Moving code to process batches into Aggregator2 (which will be renamed). Part
of the reason for this refactoring is logging. Info or debug level logging can
be turned on for AggregationManager without flooding the log file with a lot
of log statements.

TaskTracker provides synchronization for schedules tasks. It is used to track
when all of the scheduled tasks have completed. CountDownLatch cannot be used
anymore because it requires you to specify the number of tasks or events up
front. This worked fine with the metrics_index table since we were only
querying against a single row, and we would iterate over the result set to get
the count. It is not know in advance though how many rows there will be in
metrics_cache so a different sychronization mechanism was needed.

Lastly I should mention that I am not referring to CQL rows here but rather
rows at the actual storage layer, i.e., thrift rows.

more clean up, removing classes that are now unused.

update logging to output number of schedules aggregated

cleaning up and re-enabling some tests

This commit also updates the logic for determine when aggregation last ran
after a server outage. It is a bit more complicated now since with
metrics_cache there can be multiple partitions per time slice; so, we have to
iterate over all possible partitiion keys per time slice, and if we fail to
find any data, only then do we check the previous time slice. It was eaasier
with the metrics_index table because there was only one partition per time
slice.

re-enabling and updating tests in MetricsServerTest

update server code to pass min/max schedule ids to MetricsServer

adding some initial support for failure handling

This commit gives the capability to log stack traces when exceptions occur
while processing a batch of futures. More importantly, this is a step towards
providing fail fast behavior. Suppose we provide a configurable threshold for
failures, and when that threshold is passed, we abort the aggregation so that
it can be retried at some later time.

making some changes based on feedback from code review

The wait() notify() calls have been replaced with a CountDownLatch to address
the scenario in which notify() is invoked before wait(). JavaDoc has also been
added to explain usage.

remove references to now obsolete metrics_index table

There is still a reference in the data migration code. That will be addressed
in a separate task.

changing naming convention for the bucket column in metrics_cache

Previously when inserting a row into metrics_index, the bucket column would
have the next wider bucket as its value. For example, if we inserted raw data,
then we would update metrics_index with the bucket column having a value of
"one_hour_metrics". With the schema changes to start using metrics_cache in
place of metrics_index, this approach got confusing. The bucket column now
is set to the name of the historical table in which data is being written.

adding metrics_cache_index table to schema along with initial query support

update metrics_cache_index when inserting raw data

updating, refactoring tests

do not insert raw data that is too old

This initial support caps the age at 24 hours. The plan going forward however
is to make that cap configurable.

update metrics_cache and metrics_cache_index for 1 hour and 6 hour data

This commit also introduces a big refactoring of AggregationTests. Tracking and
updating expected values was tedious and error prone; consequently, I
introduced InMemoryMetricsDB.

re-enabling 24 hour data tests

adding initial support for aggregating late/past data

There are two main changes in this commit. The first is the initial suppport
for aggregating late data. That is, raw data that is stored after its time
slice has already passed.

The schema for metrics_cache_index is changed slightly as well. We now order by
the time column before the start_schedule_id column. And we are always storing
the day, i.e., hour zero in the time_slice column. This reduces the number of
queries that need to be performed when looking to see if there is past data to
aggregate.

There is still work to do for handling late data along with a bunch of clean
up and refactoring. I am trying to consolidate the logic as much as possible
for aggregating past data and for current data so as to avoid a lot of the code
duplication that is going on right now.

major refactoring to consolidate common aggregation functions

After adding initial support for aggregating old/past data, it was evident that
there was a lot of duplicate functionality around aggregating past and current
data. This commit introduces a new class, BaseAggregator, which contains common
functions. Aggregation has been renamed to CacheAggregator since it only works
with data out of the metrics_cache table.

This is also the initial commit for CacheIterator. The computeAggregates
function, in its previous forms, took a list of result sets as input. The
computations to be performed for past and current data is the same, but the
format of the input differed. Now the input is an Iterable so that the function
can be used with both past and current data.

updating logic for determining most recent raw data after server outage

This commit also remove the logic around the min/max scheudle ids. Previously
we needed the min and max schedule ids in order to determine the possible set
of rows in metrics_cache. This is no longer necessary though since we track the
schedule ids in metrics_cache_index.

adding more util methods and javadoc to DateTimeService

add support for aggregating cache blocks in PastDataAggregator

If aggregation for a cache block (i.e., partition in metrics_cache) fails,
neither the partition nor the corresponding row in metrics_cache_index are
deleted. When a subsequent aggregation run is performed, PastDataAggregator
will retry those failed partitions. It can be assumed that all data for the
time slice is present in metrics_cache; therefore, we can pull data from
metrics_cache instead of raw_metrics and potentially reduce query and I/O
overhead.

when the 6 hour time slice has passed for late data, recompute the 6 hour data

This commit is best explained with an example. Suppose the current time is
06:12. We receive a measurement report with data having a timestamp of 05:50.
Aggregation will run again at 07:00. The 6 hour time slice for the late data is
00:00 to 06:00, and that time slice has already passed. When aggregation runs,
we not only compute the 1 hour aggregate for the data inserted at 05:50, we
also recompute the 6 hour aggregate so that the late data is included.

update cache and cache index only when necessary for late data

When aggregating late data whose 6 hour time slice has not yet finished, we
should update metrics_cache and metrics_cache_index so that the necessary rows
are present when 6 hour data aggregation runs. If the 6 hour time slice has
already passed, then there is no need to update metrics_cache and
metrics_cache_index because we go ahead and recompute the 6 hour data. The
same idea holds with 24 hour data. If the 24 hour time slice has not yet
finished, then should update metrics_cache and metrics_cache_index so that the
necessary rows are present when 24 hour data aggregation runs; however, if the
24 hour time slice has already passed, then there is no need to perform the
updates because we will (in the next commit) go ahead and recompute 24 hour
data.

adding support for recomputing 24 hour data

refactoring some functions into a utility class

This commit also updates the logic in PastDataAggregator for how it invokes the
processCacheBlock method. If the 6 hour time slice has finished, it no longer
updates the metrics_cache and metrics_cache_index tables. There are additional
changes needed for when PastDataAggregator calls processCacheBlock. It needs to
determine if the 6 hour and 24 hour data need to be recomputed similar to what
is done in the processBatch method.

recompute 6 hour data when aggregating late data out of metrics_cache table

If the 6 hour time slice of the late data has passed, we need to recompute the
6 hour data just as we do when we pull data from raw_metrics.

updating test for recomputing 24 hr data when pulling data from metrics_cache

refactoring task scheduling logic

Task scheduling logic has been pulled up into BaseAggregator which is now an
abstract class. Subclasses are responsible for creating the Runnable tasks.

more refactoring to correctly compute the number of schedules processed

introduce AggregationTask to provide error handling

making schema changes to metrics_cache_index table

Some columns have been renamed and a new column has been added. We now have the
following timestamp columns - day, collection_time_slice, and insert_time_slice.
collection_time_slice is the timestamp provided by the reported data.
insert_time_slice is the raw time slice in which the data is inserted. For
example, if data is inserted at 17:02, insert_time_slice will be 17:00. And
day is the 24 hour time slice of the collection timestamp.

insert_time_slice is the new column. Previously there was a scenario in which
we could fail to aggregate data. Suppose aggregation for a cache partition
failed. Its cache index entry would be left intact., and note that the set of
schedule ids was empty. Then late data is reported in the next time slice. At
that point, the cache index entry is updated with the schedule ids of the late
data. Prior to this commit we would have only aggregated data for the schedule
ids with late data.

Now we always update the schedule ids for the cache index, even for current
data. When we have past/late data, we now compare collection_time_slice with
insert_time_slice to determine if we can pull data from metrics_cache.

fix scheduling logic for past data aggregation tasks

With the addition of the insert_time_slice column, we can now have multiple
index entries for a {column_time_slice, start_schedule_id} pair. We can reduce
those into a single index entry and submit an aggregation task for that
combined entry.

PastDataAggregator also now has a deleteCacheIndexEntries function to take care
of deleting all index entries for a {column_time_slice, start_schedule_id} pair.

more refactoring of processing index entries and adding javadocs

refactoring tests and adding javadocs

use the same insert time slice for each raw data

There is no need to recompute the insert time slice for each raw data. It is
sufficient to use insert time slice timestamp as the starting point at which
we beging inserting raw data.

do not schedule aggregation tasks on I/O thread

I had previously and inadvertently perfoming the scheduling of aggregation
tasks on an I/O thread. Long running tasks should never run on an I/O thread.
I discovered this mistake in a test environment where I was generating
NoHostAvailableExceptions because of this mistake.

This commit also makes a subtle yet significant change in
AggregateNumericMetricMapper. It now checks for nulls which it should have been
doing all along since we use weak consistency for reads and writes. The change
was needed because I was hitting occassional NPEs with past data aggregation
when 1 hr and/or 6 hr aggregates have to be computed. It is easiest to explain
with an example.

Suppose we are aggregating some past data and we also need to aggregate the
1 hour data into 6 hour data. Almost immediately after computing and storing
the  1 hour data for the given time slice, we then fetch all of the 1 hour data
for the 6 hour time slice. Unless the query is against the same node to which
the preceding write went, the query results might not include all of the data.
We do not have to worry about the missing data in the result sets though
because we already have the data in memory.

updating logging and adding javadocs

add support for "decactivating" metrics_cache

Deactivating metrics_cache results in data *not* being pulled from it. This
applies to both past and current data. Once a specified time has been reached,
it is reactived and we start pulling from metrics_cache again. This logic is
necessary for two purrposes. First, we need it simplify and speed up the data
migration that will be necessary when upgrading to RHQ 4.11. Secondly, it is
necessary for the resizing of cache partitions to take effect. For example,
suppose we store data for up to 5 schedules per cache partition. We decide
to store data for 10 schedules per partition. We need to deactivate the cache
while the change takes effect.

fixing merge conflicts from rebase

Adding data migration support needed during upgrades

The C* schema management tool has been changed such that it now supports
arbitrary tasks in addition to raw CQL statements. An arbitrary task/step must
implement the new Step interface. PopulateCacheIndex is one such custom task
that migrates data out of metrics_index and into metrics_cache_index.

A property has been added to the system settings for the cache activation time.
PopulateCacheIndex sets that property so the server knows when it can start
pulling data from metrics_cache during aggregation. And at server start up,
MetricsServer is initialized with the property value.

fixing merge conflict errors
fixing upgrade for metrics aggregation schema changes