Class VariableManagementServiceImpl

java.lang.Object
com.espertech.esper.common.internal.epl.variable.core.VariableManagementServiceImpl
All Implemented Interfaces:
VariableManagementService

public class VariableManagementServiceImpl extends Object implements VariableManagementService
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:

  1. lock-less read of the current and prior version, locked reads for older versions
  2. atomicity by keeping multiple versions for each variable and a threadlocal that receives the current version each call
  3. 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 runtimevia 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 variable node that has a VariableReader handle obtained during validation (example).

The 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.