Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**************************************************************************************
* Copyright (C) 2006-2015 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.epl.variable;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.EventType;
import com.espertech.esper.client.VariableValueException;
import com.espertech.esper.collection.Pair;
import com.espertech.esper.core.service.StatementExtensionSvcContext;
import com.espertech.esper.core.start.EPStatementStartMethod;
import com.espertech.esper.epl.core.EngineImportException;
import com.espertech.esper.epl.core.EngineImportService;
import com.espertech.esper.event.EventAdapterService;
import com.espertech.esper.schedule.TimeProvider;
import com.espertech.esper.util.JavaClassHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.StringWriter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Variables service for reading and writing variables, and for setting a version number for the current thread to
* consider variables for.
*
* Consider a statement as follows: select * from MyEvent as A where A.val > var1 and A.val2 > var1 and A.val3 > var2
*
* Upon statement execution we need to guarantee that the same atomic value for all variables is applied for all
* variable reads (by expressions typically) within the statement.
*
* Designed to support:
*
*
lock-less read of the current and prior version, locked reads for older versions
*
atomicity by keeping multiple versions for each variable and a threadlocal that receives the current version each call
*
one write lock for all variables (required to coordinate with single global version number),
* however writes are very fast (entry to collection plus increment an int) and therefore blocking should not be an issue
*
*
* As an alternative to a version-based design, a read-lock for the variable space could also be used, with the following
* disadvantages: The write lock may just not be granted unless fair locks are used which are more expensive; And
* a read-lock is more expensive to acquire for multiple CPUs; A thread-local is still need to deal with
* "set var1=3, var2=var1+1" assignments where the new uncommitted value must be visible in the local evaluation.
*
* Every new write to a variable creates a new version. Thus when reading variables, readers can ignore newer versions
* and a read lock is not required in most circumstances.
*
* This algorithm works as follows:
*
* A thread processing an event into the engine via sendEvent() calls the "setLocalVersion" method once
* before processing a statement that has variables.
* This places into a threadlocal variable the current version number, say version 570.
*
* A statement that reads a variable has an {@link com.espertech.esper.epl.expression.core.ExprVariableNode} that has a {@link com.espertech.esper.epl.variable.VariableReader} handle
* obtained during validation (example).
*
* The {@link com.espertech.esper.epl.variable.VariableReader} takes the version from the threadlocal (570) and compares the version number with the
* version numbers held for the variable.
* If the current version is same or lower (520, as old or older) then the threadlocal version,
* then use the current value.
* If the current version is higher (571, newer) then the threadlocal version, then go to the prior value.
* Use the prior value until a version is found that as old or older then the threadlocal version.
*
* If no version can be found that is old enough, output a warning and return the newest version.
* This should not happen, unless a thread is executing for very long within a single statement such that
* lifetime-old-version time speriod passed before the thread asks for variable values.
*
* As version numbers are counted up they may reach a boundary. Any write transaction after the boundary
* is reached performs a roll-over. In a roll-over, all variables version lists are
* newly created and any existing threads that read versions go against a (old) high-collection,
* while new threads reading the reset version go against a new low-collection.
*
* The class also allows an optional state handler to be plugged in to handle persistence for variable state.
* The state handler gets invoked when a variable changes value, and when a variable gets created
* to obtain the current value from persistence, if any.
*/
public class VariableServiceImpl implements VariableService
{
private static Log log = LogFactory.getLog(VariableServiceImpl.class);
/**
* Sets the boundary above which a reader considers the high-version list of variable values.
* For use in roll-over when the current version number overflows the ROLLOVER_WRITER_BOUNDARY.
*/
protected final static int ROLLOVER_READER_BOUNDARY = Integer.MAX_VALUE - 100000;
/**
* Applicable for each variable if more then the number of versions accumulated, check
* timestamps to determine if a version can be expired.
*/
protected final static int HIGH_WATERMARK_VERSIONS = 50;
// Each variable has an index number, a context-partition id, a current version and a list of values
private final ArrayList> variableVersionsPerCP;
// Each variable and a context-partition id may have a set of callbacks to invoke when the variable changes
private final ArrayList