/**************************************************************************************
* Copyright (C) 2008 EsperTech, Inc. All rights reserved. *
* http://esper.codehaus.org *
* 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.core.service;
import com.espertech.esper.client.EventBean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* A suspend-and-notify implementation of a latch for use in guaranteeing delivery between
* a single event produced by a single statement and consumable by another statement.
*/
public class InsertIntoLatchWait
{
private static final Log log = LogFactory.getLog(InsertIntoLatchWait.class);
// The earlier latch is the latch generated before this latch
private InsertIntoLatchFactory factory;
private InsertIntoLatchWait earlier;
private long msecTimeout;
private EventBean payload;
// The later latch is the latch generated after this latch
private InsertIntoLatchWait later;
private volatile boolean isCompleted;
/**
* Ctor.
* @param earlier the latch before this latch that this latch should be waiting for
* @param msecTimeout the timeout after which delivery occurs
* @param payload the payload is an event to deliver
*/
public InsertIntoLatchWait(InsertIntoLatchFactory factory, InsertIntoLatchWait earlier, long msecTimeout, EventBean payload)
{
this.factory = factory;
this.earlier = earlier;
this.msecTimeout = msecTimeout;
this.payload = payload;
}
/**
* Ctor - use for the first and unused latch to indicate completion.
*/
public InsertIntoLatchWait(InsertIntoLatchFactory factory)
{
this.factory = factory;
isCompleted = true;
earlier = null;
msecTimeout = 0;
}
/**
* Returns true if the dispatch completed for this future.
* @return true for completed, false if not
*/
public boolean isCompleted()
{
return isCompleted;
}
/**
* Hand a later latch to use for indicating completion via notify.
* @param later is the later latch
*/
public void setLater(InsertIntoLatchWait later)
{
this.later = later;
}
/**
* Blcking call that returns only when the earlier latch completed.
* @return payload of the latch
*/
public EventBean await()
{
if (!earlier.isCompleted)
{
synchronized(this)
{
if (!earlier.isCompleted)
{
try
{
this.wait(msecTimeout);
}
catch (InterruptedException e)
{
log.error(e);
}
}
}
}
if (!earlier.isCompleted)
{
log.info("Wait timeout exceeded for insert-into dispatch with notify");
}
return payload;
}
/**
* Called to indicate that the latch completed and a later latch can start.
*/
public void done()
{
isCompleted = true;
if (later != null)
{
synchronized(later)
{
later.notify();
}
}
earlier = null;
later = null;
}
}