/* * Copyright (c) 2012 European Synchrotron Radiation Facility, * Diamond Light Source Ltd. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package uk.ac.diamond.gwt.rf.queue.client.core; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.RepeatingCommand; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.Document; import com.google.gwt.event.shared.HandlerManager; import com.google.gwt.event.shared.HandlerRegistration; /** * Manage the pipe. */ public class QosManager implements PipeTarget { private final static int TIMER_PERIOD = 1000; private final List<QosEntry> list = new ArrayList<QosEntry>(); private final HandlerManager handlerManager = new HandlerManager(this); private BackOff backOff = new BackOff(); private QosRequestTransport requestTransport; public QosManager() { } public void start() { Scheduler.get().scheduleFixedPeriod(new RepeatingCommand() { @Override public boolean execute() { tick(); return true; } }, TIMER_PERIOD); } void tick() { if (!backOff.sleepAgain()) { boolean foundFailed = resetFailed(); if (foundFailed) { backOff.retry(); } } fireReady(); } void preProcess() { Iterator<QosEntry> it = list.iterator(); while (it.hasNext()) { QosEntry e = it.next(); if (e.isReady()) { float score = 1.0f; for (QosModifier m : e.getModifiers()) { score = score * m.getScore(e); if (score == 0.f) { it.remove(); break; } } e.setScore(score); } } Collections.sort(list); } boolean isBlocked(QosEntry e) { for (QosModifier m : e.getModifiers()) { if (m.isBlocked(e)) { return true; } } return false; } void fireReady() { Iterator<QosEntry> it = getList().iterator(); while (it.hasNext()) { QosEntry entry = it.next(); if (entry.isReady()) { if (!isBlocked(entry)) { entry.fire(requestTransport); } } if (QosEntry.State.DONE.equals(entry.getState())) { it.remove(); } } if (list.isEmpty()) { backOff.reset(); } Document.get().getDocumentElement().setPropertyString("qosPending", "" + list.size()); handlerManager.fireEvent(new QosEvent(list, backOff.getAttemptCount(), backOff.getCountDown() * TIMER_PERIOD )); } @Override public void add(QosEntry e) { e.attachToManager(this); for (QosModifier m : e.getModifiers()) { m.add(e); } list.add(e); Scheduler.get().scheduleFinally(new ScheduledCommand() { @Override public void execute() { fireReady(); } }); } List<QosEntry> getList() { preProcess(); return list; } boolean resetFailed() { boolean foundFailed = false; for (QosEntry q : list) { if (QosEntry.State.FAILED.equals(q.getState())) { q.reset(); foundFailed = true; } } return foundFailed; } public HandlerRegistration addQosEventHandler(QosEventHandler handler) { return handlerManager.addHandler(QosEvent.getType(), handler); } public QosRequestTransport getRequestTransport() { return requestTransport; } public void setRequestTransport(QosRequestTransport p) { this.requestTransport = p; } public void retryNow() { backOff.reset(); tick(); } }