Package org.olat.course.statistic

Source Code of org.olat.course.statistic.StatisticUpdateManagerImpl

package org.olat.course.statistic;

import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.commons.taskExecutor.TaskExecutorManager;
import org.olat.core.gui.control.Event;
import org.olat.core.logging.AssertException;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.coordinate.Coordinator;
import org.olat.core.util.event.GenericEventListener;
import org.olat.core.util.event.MultiUserEvent;
import org.olat.core.util.resource.OresHelper;
import org.olat.properties.Property;
import org.olat.properties.PropertyManager;

/**
* Default implementation for IStatisticUpdateManager
* <P>
* Initial Date:  11.02.2010 <br>
* @author Stefan
*/
class StatisticUpdateManagerImpl implements StatisticUpdateManager, GenericEventListener {
 
  /** the logging object used in this class **/
  static final OLog log_ = Tracing.createLoggerFor(StatisticUpdateManagerImpl.class);

  /** the category used for statistics properties (in the o_properties table) **/
  private static final String STATISTICS_PROPERTIES_CATEGORY = "STATISTICS_PROPERTIES";
 
  /** the name used for last_updated property (in the o_properties table) **/
  private static final String LAST_UPDATED_PROPERTY_NAME = "LAST_UPDATED";

  /** the event string used to ensure that only one StatisticUpdateManagerImpl is active in a cluster **/
  private static final String STARTUP_EVENT = "startupEvent";
 
  /** all the IStatisticUpdaters that registered with the StatisticUpdaterManager **/
  final List<IStatisticUpdater> updaters_ = new LinkedList<IStatisticUpdater>();

  private final MultiUserEvent startupEvent_ = new MultiUserEvent(STARTUP_EVENT);

  /** whether or not this manager is enabled - disables itself when there is more than 1 in the cluster **/
  private boolean enabled_ = true;
 
  boolean updateOngoing_ = false;
 
 
  /** spring **/
  public StatisticUpdateManagerImpl(Coordinator coordinator, StatisticUpdateConfig config) {
    updaters_.addAll(config.getUpdaters());
   
    // note: not using CoordinatorManager.getCoordinator() in this spring-called-constructor
    //       as we have a problem in 6.3 where Tracing calls into CoordinatorManager.getCoordinator()
    //       which in turn causes the coord variable there to be initialized, which in turn
    //       initializes the CoreSpringFactory, which in turn creates this bean *BEFORE*
    //       the CoordinatorManager.coord was set ... hence we'd get a NullPointerException here
    //@TODO cleanup in 6.4
    coordinator.getEventBus().registerFor(this, null,
        OresHelper.createOLATResourceableTypeWithoutCheck(StatisticUpdateManagerImpl.class.getName()));
    coordinator.getEventBus().fireEventToListenersOf(startupEvent_,
        OresHelper.createOLATResourceableTypeWithoutCheck(StatisticUpdateManagerImpl.class.getName()));
  }
 

  @Override
  public void addStatisticUpdater(IStatisticUpdater updater) {
    updaters_.add(updater);
  }
 
  @Override
  public synchronized boolean isEnabled() {
    return enabled_;
  }
 
  @Override
  public synchronized boolean updateOngoing() {
    return updateOngoing_;
  }
 
  @Override
  public boolean updateStatistics(final boolean fullRecalculation, final Runnable finishedCallback) {
   
    synchronized(this) {
      if (!enabled_) {
        log_.warn("updateStatistics: cannot update statistics, manager is not enabled!", new Exception("updateStatistics"));
        return false;
      }
      if (updateOngoing_) {
        log_.warn("updateStatistics: cannot update statistics since an update is currently ongoing");
        return false;
      }
      updateOngoing_ = true;
    }
   
    Runnable r = new Runnable() {

      @Override
      public void run() {
        final long start = System.currentTimeMillis();
        try{
          log_.info("updateStatistics: initialization for update");
         
          long nowInMilliseconds = System.currentTimeMillis();
          long lastUpdatedInMilliseconds = getAndUpdateLastUpdated(nowInMilliseconds);
          if (fullRecalculation || (lastUpdatedInMilliseconds==-1)) {
            Calendar nineteennintyeight = Calendar.getInstance();
            nineteennintyeight.set(1998, 12, 31);
            lastUpdatedInMilliseconds = nineteennintyeight.getTimeInMillis();
          }
         
          Date lastUpdatedDate = new Date(lastUpdatedInMilliseconds);
          Date nowDate = new Date(nowInMilliseconds);

          log_.info("updateStatistics: starting the update");
          DBFactory.getInstance().intermediateCommit();
          for (Iterator<IStatisticUpdater> it = updaters_.iterator(); it.hasNext();) {
            IStatisticUpdater statisticUpdater = it.next();
            log_.info("updateStatistics: starting updater "+statisticUpdater);
            statisticUpdater.updateStatistic(fullRecalculation || (lastUpdatedInMilliseconds==-1), lastUpdatedDate, nowDate, StatisticUpdateManagerImpl.this);
            log_.info("updateStatistics: done with updater "+statisticUpdater);
            DBFactory.getInstance().intermediateCommit();
          }
        } finally {
          synchronized(StatisticUpdateManagerImpl.this) {
            updateOngoing_ = false;
          }
          final long diff = System.currentTimeMillis() - start;
          log_.info("updateStatistics: total time for updating all statistics was "+diff+" milliseconds");

          if (finishedCallback!=null) {
            finishedCallback.run();
          }
        }
      }
     
    };
    try{
      TaskExecutorManager.getInstance().runTask(r);
      log_.info("updateStatistics: starting the update in its own thread");
      return true;
    } catch(AssertException ae) {
      log_.info("updateStatistics: Could not start update due to TaskExecutorManager not yet initialized. Will be done next time Cron/User calls!");
      synchronized(StatisticUpdateManagerImpl.this) {
        updateOngoing_ = false;
      }
      return false;
    }
   
  }

  @Override
  public long getLastUpdated() {
    PropertyManager pm = PropertyManager.getInstance();
    Property p = pm.findProperty(null, null, null, STATISTICS_PROPERTIES_CATEGORY, LAST_UPDATED_PROPERTY_NAME);
    if (p==null) {
      return -1;
    } else {
      return p.getLongValue();
    }
  }
 
  @Override
  public long getAndUpdateLastUpdated(long lastUpdated) {
    PropertyManager pm = PropertyManager.getInstance();
    Property p = pm.findProperty(null, null, null, STATISTICS_PROPERTIES_CATEGORY, LAST_UPDATED_PROPERTY_NAME);
    if (p==null) {
      Property newp = pm.createPropertyInstance(null, null, null, STATISTICS_PROPERTIES_CATEGORY, LAST_UPDATED_PROPERTY_NAME, null, lastUpdated, null, null);
      pm.saveProperty(newp);
      return -1;
    } else {
      final long result = p.getLongValue();
      p.setLongValue(lastUpdated);
      pm.saveProperty(p);
      return result;
    }
  }
 
  @Override
  public void event(Event event) {
    // event from EventBus
    if (event!=startupEvent_) {
      // that means some other StatisticUpdateManager is in the cluster
      // not good!
      log_.error("event: CONFIG ERROR: there is more than one StatisticUpdateManager in this Cluster! I'll disable myself.");
      synchronized(this) {
        enabled_ = false;
      }
    }
  }
}
TOP

Related Classes of org.olat.course.statistic.StatisticUpdateManagerImpl

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.