Package com.senseidb.indexing.activity.time

Source Code of com.senseidb.indexing.activity.time.AggregatesUpdateJob

/**
* This software is licensed to you under the Apache License, Version 2.0 (the
* "Apache License").
*
* LinkedIn's contributions are made under the Apache License. If you contribute
* to the Software, the contributions will be deemed to have been made under the
* Apache License, unless you expressly indicate otherwise. Please do not make any
* contributions that would be inconsistent with the Apache License.
*
* You may obtain a copy of the Apache License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, this software
* distributed under the Apache License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Apache
* License for the specific language governing permissions and limitations for the
* software governed under the Apache License.
*
* © 2012 LinkedIn Corp. All Rights Reserved. 
*/
package com.senseidb.indexing.activity.time;

import com.senseidb.metrics.MetricFactory;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;

import com.senseidb.indexing.activity.ActivityPersistenceFactory.AggregatesMetadata;
import com.senseidb.indexing.activity.time.TimeAggregatedActivityValues.IntValueHolder;
import com.senseidb.metrics.MetricsConstants;
import com.yammer.metrics.core.MetricName;
import com.yammer.metrics.core.Timer;

/**
* Operates on top of TimeAggregatedActivityValues.
* It is executed every 30 seceonds.
* Updates the activity values for the time aggregates based on the current time. For example is the activity 5m count is 10,
* and one of the activity updates came into the system more than 5 mins ago,
* it will substract the stale activity value from ten and assign the result to the  5m time aggregated count
* @author vzhabiuk
*
*/
public class AggregatesUpdateJob implements Runnable {
  private final static Logger logger = Logger.getLogger(AggregatesUpdateJob.class);
  protected ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
  private final TimeAggregatedActivityValues timeAggregatedActivityValues;
  private final AggregatesMetadata aggregatesMetadata;
  private int currentCount;
  private final Timer timer = MetricFactory.newTimer(new MetricName(MetricsConstants.Domain,
                                                                    "timer",
                                                                    "updateJob-time",
                                                                    "agregatesUpdateJob"),
                                                     TimeUnit.MILLISECONDS,
                                                     TimeUnit.SECONDS);
 
  public AggregatesUpdateJob(TimeAggregatedActivityValues timeAggregatedActivityValues, AggregatesMetadata aggregatesMetadata) {
    this.timeAggregatedActivityValues = timeAggregatedActivityValues;
    this.aggregatesMetadata = aggregatesMetadata;
  }
  public void start() {
    executorService.scheduleAtFixedRate(this, 30, 30, TimeUnit.SECONDS);   
  }
  public void stop() {
    executorService.shutdown();   
  }
  public void awaitTermination() {   
    try {
      executorService.awaitTermination(5, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
      throw new RuntimeException(e);
    }
  }
  @Override
  public synchronized void run() {
    try {
      timer.time(new Callable<Void>() {
        @Override
        public Void call() throws Exception {
          runUpdateJob();
          return null;
        }
      });
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
   
  }
  public void runUpdateJob() {
    int currentTime = Clock.getCurrentTimeInMinutes();
    if (currentTime <= aggregatesMetadata.getLastUpdatedTime()) {
      return;
    }
    currentCount = 0;;
    for (int i = 0; i <= timeAggregatedActivityValues.maxIndex; i++) {
      synchronized (timeAggregatedActivityValues.timeActivities.getLock(i)) {
        if (!timeAggregatedActivityValues.timeActivities.isSet(i)) {
          continue;
        }
        IntContainer activities = timeAggregatedActivityValues.timeActivities.getActivities(i);
        IntContainer times = timeAggregatedActivityValues.timeActivities.getTimes(i);
        int[] updateTempValues = new int[timeAggregatedActivityValues.intActivityValues.length];
        updateActivityValues(timeAggregatedActivityValues.intActivityValues, activities, times, currentTime, i, updateTempValues);       
      }     
    }   
    aggregatesMetadata.updateTime(currentTime);
    logger.info("Finished the AggregatesUpdateJob. Updated " + currentCount + " records");
  }
  private final void updateActivityValues(IntValueHolder[] intActivityValues, IntContainer activities, IntContainer times, int currentTime, int index, int[] updateTempValues) {      
    int minimumAggregateIndex = 0;
    for (int activityIndex = 0; activityIndex < activities.getSize(); activityIndex++) {
      //the activity is current. As they are sorted in the ascending order, we can stop now
      if (times.size() != activities.size()) {
        throw new IllegalStateException("activities.size = " + activities.getSize() + ", times.size() = " + times.size());
      }
      if (times.size() == 0) {
        continue;
      }
      if (currentTime - times.get(activityIndex) < intActivityValues[intActivityValues.length - 1].timeInMinutes) {
        break;
      }
      for (int aggregateIndex = intActivityValues.length - 1; aggregateIndex >= minimumAggregateIndex; aggregateIndex--) {
        IntValueHolder intValueHolder = intActivityValues[aggregateIndex];       
        int currentElapsedTime = currentTime - times.get(activityIndex);
        //activity is current
        if (currentElapsedTime < intValueHolder.timeInMinutes) {
          minimumAggregateIndex = aggregateIndex + 1;
          break;
        }
        int previousElapsedTime = aggregatesMetadata.getLastUpdatedTime() - times.get(activityIndex);
        //activity is not current against the current time, but was current for the previous run
        if (currentElapsedTime >= intValueHolder.timeInMinutes && previousElapsedTime < intValueHolder.timeInMinutes) {
          int activityValue = activities.get(activityIndex);
          if (activityValue != 0) {
            updateTempValues[aggregateIndex] += activityValue;
            currentCount++;
          }
        }
      }
    }
    for (int i = 0; i < updateTempValues.length; i++) {
      int updateValue = updateTempValues[i];
      if (updateValue != 0) {
        synchronized (intActivityValues[i].activityIntValues.getFieldValues()) {
         intActivityValues[i].activityIntValues.update(index, updateValue > 0 ? String.valueOf(-updateValue) : "+" + String.valueOf(updateValue));
       }
       updateTempValues[i] = 0;
      }
    }
    //remove outdated activities
    while (true) {
      if (times.size() == 0) {
        break;
      }
      int time = times.peekFirst();
      int elapsedTime = currentTime - time;
      if (elapsedTime >= intActivityValues[0].timeInMinutes) {
        times.removeFirst();
        activities.removeFirst();
        if (times.size() == 0) {
          timeAggregatedActivityValues.timeActivities.reset(index);
        }
      } else {
        break;
      }
    }
  }
}
TOP

Related Classes of com.senseidb.indexing.activity.time.AggregatesUpdateJob

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.