/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
***************************************************************************************
*/
package com.espertech.esper.pattern.guard;
import com.espertech.esper.core.service.EPStatementHandleCallback;
import com.espertech.esper.core.service.EngineLevelExtensionServicesContext;
import com.espertech.esper.metrics.instrumentation.InstrumentationHelper;
import com.espertech.esper.pattern.MatchedEventMap;
import com.espertech.esper.schedule.ScheduleHandleCallback;
/**
* Guard implementation that keeps a timer instance and quits when the timer expired,
* and also keeps a count of the number of matches so far, checking both count and timer,
* letting all {@link com.espertech.esper.pattern.MatchedEventMap} instances pass until then.
*/
public class TimerWithinOrMaxCountGuard implements Guard, ScheduleHandleCallback {
private final long deltaTime;
private final int numCountTo;
private final Quitable quitable;
private final long scheduleSlot;
private int counter;
private boolean isTimerActive;
private EPStatementHandleCallback scheduleHandle;
/**
* Ctor.
*
* @param deltaTime - number of millisecond to guard expiration
* @param numCountTo - max number of counts
* @param quitable - to use to indicate that the gaurd quitted
*/
public TimerWithinOrMaxCountGuard(long deltaTime, int numCountTo, Quitable quitable) {
this.deltaTime = deltaTime;
this.numCountTo = numCountTo;
this.quitable = quitable;
this.scheduleSlot = quitable.getContext().getPatternContext().getScheduleBucket().allocateSlot();
}
public void startGuard() {
if (isTimerActive) {
throw new IllegalStateException("Timer already active");
}
scheduleHandle = new EPStatementHandleCallback(quitable.getContext().getAgentInstanceContext().getEpStatementAgentInstanceHandle(), this);
quitable.getContext().getPatternContext().getSchedulingService().add(deltaTime, scheduleHandle, scheduleSlot);
isTimerActive = true;
counter = 0;
}
public boolean inspect(MatchedEventMap matchEvent) {
counter++;
if (counter > numCountTo) {
quitable.guardQuit();
deactivateTimer();
return false;
}
return true;
}
public void stopGuard() {
if (isTimerActive) {
deactivateTimer();
}
}
public void scheduledTrigger(EngineLevelExtensionServicesContext engineLevelExtensionServicesContext) {
if (InstrumentationHelper.ENABLED) {
InstrumentationHelper.get().qPatternGuardScheduledEval();
}
// Timer callback is automatically removed when triggering
isTimerActive = false;
quitable.guardQuit();
if (InstrumentationHelper.ENABLED) {
InstrumentationHelper.get().aPatternGuardScheduledEval();
}
}
public void accept(EventGuardVisitor visitor) {
visitor.visitGuard(20, scheduleSlot);
}
private void deactivateTimer() {
if (scheduleHandle != null) {
quitable.getContext().getPatternContext().getSchedulingService().remove(scheduleHandle, scheduleSlot);
}
scheduleHandle = null;
isTimerActive = false;
}
}