Program: 2155
Project: 2155
Buggy source:
/** 
 * The sequence of events is: <ul> <li>Build the aggregated TimelineTimes object, and save it, setting not_valid to true, and aggregation_level to 1.  This means that it won't be noticed by any of the dashboard queries.  The save operation returns the new timeline_times_id</li> <li>Retrieve all sample chunks associated with the TimelineTimes objects were aggregating, ordered by host_id, sample_kind_id and start_time.  Aggregate and save those, with timeline_time_id of the newly-created aggregated TimelineTimes object</li> <li>Then, in a single transaction, update the aggregated TimelineTimes object to have not_valid = 0, and also delete the TimelineTimes objects that were the basis of the aggregation, and flush any TimelineTime chunks that happen to be in the cache.</li> <li>Finally, delete the sample chunks that we aggregated.  Since sample chunks are only accessed by timeline_time_id, so the old sample chunks can no longer be referenced  Therefore they don't need to be deleted.</li> <p/>
 * @param timelineTimesChunks the TimelineTimes chunks to be aggregated
 */
private void aggregateHostSampleChunks(final List<TimelineTimes> timelineTimesChunks,final int aggregationLevel){
  final TimelineTimes firstTimesChunk=timelineTimesChunks.get(0);
  final TimelineTimes lastTimesChunk=timelineTimesChunks.get(timelineTimesChunks.size() - 1);
  final int hostId=firstTimesChunk.getHostId();
  final DateTime startTime=firstTimesChunk.getStartTime();
  final DateTime endTime=lastTimesChunk.getEndTime();
  int totalTimelineSize=0;
  int sampleCount=0;
  final List<Long> timelineTimesIds=new ArrayList<Long>(timelineTimesChunks.size());
  for (  final TimelineTimes timelineTimes : timelineTimesChunks) {
    totalTimelineSize+=timelineTimes.getCompressedTimes().length;
    sampleCount+=timelineTimes.getSampleCount();
    timelineTimesIds.add(timelineTimes.getObjectId());
  }
  log.info("String_Node_Str",new Object[]{timelineTimesChunks.size(),totalTimelineSize,sampleCount,timelineTimesIds});
  final int totalSampleCount=sampleCount;
  final byte[] aggregatedTimes=new byte[totalTimelineSize];
  int timeChunkIndex=0;
  for (  final TimelineTimes chunk : timelineTimesChunks) {
    final int chunkTimeLength=chunk.getCompressedTimes().length;
    System.arraycopy(chunk.getCompressedTimes(),0,aggregatedTimes,timeChunkIndex,chunkTimeLength);
    timeChunkIndex+=chunkTimeLength;
  }
  aggregatorDao.begin();
  aggregatorDao.insertNewInvalidTimelineTimes(new TimelineTimes(-1,hostId,firstTimesChunk.getEventCategory(),startTime,endTime,aggregatedTimes,totalSampleCount),aggregationLevel + 1);
  final int newTimelineTimesId=aggregatorDao.getLastInsertedId();
  aggregatorDao.commit();
  aggregateSampleChunks(timelineTimesIds,newTimelineTimesId,totalSampleCount);
  aggregatorDao.begin();
  aggregatorDao.makeTimelineTimesValid(newTimelineTimesId);
  aggregatorDao.makeTimelineTimesInvalid(timelineTimesIds);
  aggregatorDao.commit();
  if (config.getDeleteAggregatedChunks()) {
    aggregatorDao.begin();
    aggregatorDao.deleteTimelineTimes(timelineTimesIds);
    aggregatorDao.deleteTimelineChunks(timelineTimesIds);
    aggregatorDao.commit();
  }
}

Fixed version (ground truth):
/** 
 * The sequence of events is: <ul> <li>Build the aggregated TimelineTimes object, and save it, setting not_valid to true, and aggregation_level to 1.  This means that it won't be noticed by any of the dashboard queries.  The save operation returns the new timeline_times_id</li> <li>Retrieve all sample chunks associated with the TimelineTimes objects were aggregating, ordered by host_id, sample_kind_id and start_time.  Aggregate and save those, with timeline_time_id of the newly-created aggregated TimelineTimes object</li> <li>Then, in a single transaction, update the aggregated TimelineTimes object to have not_valid = 0, and also delete the TimelineTimes objects that were the basis of the aggregation, and flush any TimelineTime chunks that happen to be in the cache.</li> <li>Finally, delete the sample chunks that we aggregated.  Since sample chunks are only accessed by timeline_time_id, so the old sample chunks can no longer be referenced  Therefore they don't need to be deleted.</li> <p/>
 * @param timelineTimesChunks the TimelineTimes chunks to be aggregated
 */
private void aggregateHostSampleChunks(final List<TimelineTimes> timelineTimesChunks,final int aggregationLevel){
  final TimelineTimes firstTimesChunk=timelineTimesChunks.get(0);
  final TimelineTimes lastTimesChunk=timelineTimesChunks.get(timelineTimesChunks.size() - 1);
  final int hostId=firstTimesChunk.getHostId();
  final DateTime startTime=firstTimesChunk.getStartTime();
  final DateTime endTime=lastTimesChunk.getEndTime();
  int totalTimelineSize=0;
  int sampleCount=0;
  final List<Long> timelineTimesIds=new ArrayList<Long>(timelineTimesChunks.size());
  for (  final TimelineTimes timelineTimes : timelineTimesChunks) {
    totalTimelineSize+=timelineTimes.getCompressedTimes().length;
    sampleCount+=timelineTimes.getSampleCount();
    timelineTimesIds.add(timelineTimes.getObjectId());
  }
  log.info("String_Node_Str",new Object[]{firstTimesChunk.getHostId(),firstTimesChunk.getAggregationLevel(),timelineTimesChunks.size(),totalTimelineSize,sampleCount,timelineTimesIds});
  final int totalSampleCount=sampleCount;
  final byte[] aggregatedTimes=new byte[totalTimelineSize];
  int timeChunkIndex=0;
  for (  final TimelineTimes chunk : timelineTimesChunks) {
    final int chunkTimeLength=chunk.getCompressedTimes().length;
    System.arraycopy(chunk.getCompressedTimes(),0,aggregatedTimes,timeChunkIndex,chunkTimeLength);
    timeChunkIndex+=chunkTimeLength;
  }
  aggregatorDao.begin();
  aggregatorDao.insertNewInvalidTimelineTimes(new TimelineTimes(-1,hostId,firstTimesChunk.getEventCategory(),startTime,endTime,aggregatedTimes,totalSampleCount),aggregationLevel + 1);
  final int newTimelineTimesId=aggregatorDao.getLastInsertedId();
  aggregatorDao.commit();
  aggregateSampleChunks(timelineTimesIds,newTimelineTimesId,totalSampleCount);
  aggregatorDao.begin();
  aggregatorDao.makeTimelineTimesValid(newTimelineTimesId);
  aggregatorDao.makeTimelineTimesInvalid(timelineTimesIds);
  aggregatorDao.commit();
  if (config.getDeleteAggregatedChunks()) {
    aggregatorDao.begin();
    aggregatorDao.deleteTimelineTimes(timelineTimesIds);
    aggregatorDao.deleteTimelineChunks(timelineTimesIds);
    aggregatorDao.commit();
  }
}