/*
* Created on Apr 12, 2007 Copyright (C) 2001-6, Anthony Harrison anh23@pitt.edu
* (jactr.org) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the License,
* or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have
* received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.jactr.tools.async.iterative.tracker;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.commonreality.net.session.ISessionInfo;
import org.jactr.tools.async.common.NetworkedEndpoint;
import org.jactr.tools.async.iterative.listener.NetworkedIterativeRunListener;
import org.jactr.tools.async.iterative.message.DeadLockMessage;
import org.jactr.tools.async.iterative.message.ExceptionMessage;
import org.jactr.tools.async.iterative.message.StatusMessage;
import org.jactr.tools.deadlock.IDeadLockListener;
/**
* for the receiving of updates from the {@link NetworkedIterativeRunListener}
*
* @author developer
*/
public class IterativeRunTracker extends NetworkedEndpoint
{
/**
* logger definition
*/
static private final Log LOGGER = LogFactory
.getLog(IterativeRunTracker.class);
private int _totalIterations;
private int _currentIteration;
private long _startTime = 0;
private long _summedDurations;
private long _estimatedIterationDuration;
private long _estimatedCompletionTime;
private Set<Integer> _exceptionIterations = new TreeSet<Integer>();
private IDeadLockListener _listener;
static private DateFormat _longTimeFormat = DateFormat
.getTimeInstance(DateFormat.LONG);
public IterativeRunTracker()
{
}
@Override
protected void createDefaultHandlers()
{
super.createDefaultHandlers();
_defaultHandlers.put(DeadLockMessage.class, (s, m) -> {
LOGGER.error("Deadlock has been detected, notifying");
if (_listener != null) _listener.deadlockDetected();
});
_defaultHandlers.put(ExceptionMessage.class,
(s, m) -> update((ExceptionMessage) m));
_defaultHandlers.put(StatusMessage.class,
(s, m) -> update((StatusMessage) m));
}
protected void update(StatusMessage message)
{
_totalIterations = message.getTotalIterations();
_currentIteration = message.getIteration();
if (_startTime == 0) _startTime = message.getWhen(); // when it actually
// started
if (message.isStop())
{
long currentDuration = message.getWhen() - _startTime;
/*
* we set the next start time to this so that we can accurately measure
* the cost of any analyses being run outside of the simulation
*/
_startTime = message.getWhen();
_summedDurations += currentDuration;
/*
* weighted average of everyone up to now and last
*/
_estimatedIterationDuration = _summedDurations / _currentIteration;
long remainingTime = (_totalIterations - _currentIteration + 1)
* _estimatedIterationDuration;
_estimatedCompletionTime = remainingTime + message.getWhen();
if (LOGGER.isDebugEnabled())
LOGGER.debug("estimated duration : "
+ _estimatedIterationDuration
+ " r:"
+ (_totalIterations - _currentIteration)
+ " remainingTime : "
+ remainingTime
+ "ms eta "
+ _longTimeFormat.format(
_estimatedCompletionTime));
}
if (LOGGER.isDebugEnabled())
{
StringBuilder sb = new StringBuilder();
sb.append(message.getIteration()).append("/")
.append(message.getTotalIterations());
if (message.isStart())
sb.append(" started @ ");
else
sb.append(" stopped @ ");
sb.append(_longTimeFormat.format(new Date(message.getWhen())));
LOGGER.debug(sb.toString());
LOGGER.debug("Will finish @ "
+ _longTimeFormat.format(new Date(getETA()))
+ " in " + getTimeToCompletion() + "ms");
}
}
protected void update(ExceptionMessage message)
{
_exceptionIterations.add(message.getIteration());
if (LOGGER.isDebugEnabled())
{
StringBuilder sb = new StringBuilder("Exception thrown during iteration ");
sb.append(message.getIteration()).append(" by ")
.append(message.getModelName()).append(" ");
LOGGER.debug(sb.toString(), message.getThrown());
}
}
@Override
public ISessionInfo getActiveSession()
{
return getSession();
}
public void setDeadLockListener(IDeadLockListener listener)
{
_listener = listener;
}
public int getCurrentIteration()
{
return _currentIteration;
}
public int getTotalIterations()
{
return _totalIterations;
}
public long getEstimatedDuration()
{
return _estimatedIterationDuration;
}
public long getTimeToCompletion()
{
long eta = getETA();
if (eta != 0) return eta - System.currentTimeMillis();
return 0;
}
public long getETA()
{
return _estimatedCompletionTime;
}
public Collection<Integer> getExceptionCycles()
{
return new ArrayList<Integer>(_exceptionIterations);
}
public void start() throws Exception
{
connect();
}
public void stop() throws Exception
{
// getIOHandler().waitForPendingWrites();
// getIOHandler().waitForDisconnect();
disconnect();
}
}