the embodiment described here is a time series monitoring system implemented as software in the java computer language . refer to fig1 for a diagram showing system parts and some of their relationships . this description begins with an introduction to system parts and their roles . next , there is a description of how the system responds to an input value from a time series . next , there is a description of persistent query syntax and parsing . then processes used by the system to accomplish various functions are described in a step - by - step fashion . the time series monitoring system can be implemented using a software class called an engine . the engine comprises a filter , a sequencer , a set of registers , and a set of persistent queries . the engine also coordinates methods to insert data into the system , to execute persistent queries , and to dynamically manage registers , windows , and persistent queries . each time series monitored by the system corresponds to a register . each register has a ring buffer to store time series values . each register may contain one or more windows . each window is associated with a subset of the time series . each window maintains statistics for the associated subset of the time series . each persistent query comprises an event condition and a payload specification . the event condition is a boolean function that may depend on statistics from multiple registers . the payload specification expresses which data are to be output by the engine when the event condition is evaluated as true . for each persistent query , there is a set of associated registers called trigger registers . the engine evaluates the event condition in response to receiving a value from any time series corresponding to a trigger register . the engine receives as input a stream of labeled data , in which each value is associated with a label indicating the time series to which the value belongs . for each input value , the filter uses the label to determine whether the value belongs to a time series monitored by the system . if not , then the value is discarded . if so , then the engine forms a point that comprises the value , a timestamp , and a unique id number supplied by a sequencer . then the engine sends the point to the register that corresponds to the time series to which the value belongs . the register installs the point in the buffer of the register . next , each window in the register updates the statistics for the window using online computation , accounting for the new point and for any points that have expired from the window since the previous statistics computation . then the register adjusts the buffer , discarding points that have expired from all windows , growing the buffer if needed to accommodate new points , and shrinking the buffer if needed to accommodate storage needs of other buffers . then the engine executes each persistent query for which the register is a trigger . each persistent query comprises an event condition and a payload specification . the engine evaluates the event condition . if the event condition is true , then the engine creates a payload according to the payload specification and delivers the payload as output . a persistent query may be expressed using a query string . the query string syntax is similar to sql , the standard database query language . the format for a query string is as follows . the columns encode the payload specification . column syntax is as follows . this is a comma - separated list of identifiers of the form register . window . name where name is the name of a statistic ( like count , sum , mean , stdev ), one of ( valid , all , last , val ), or a number . valid is true when the window is valid ( has enough points in it or enough time in it ) and false if not . all indicates the set of points that entered the window since the last time the event condition evaluated as true . if the window has received a new point since the event condition last evaluated to true , then last indicates the newest point in the window , and val is the time series value in that point . otherwise , last and val are both null . ( the behavior for valid and val is slightly different in evaluation of event conditions . the differences are explained later , in the “ condition ” subsection .) a number indicates the point at the position in the window specified by the number , with the number 0 indicating the oldest point . for example , “ window . 0 , window . 1 , window . 2 ” indicates the oldest three points in window . the payload is delivered as a pair of lists . one list contains the column names specified in the query string . the other list contains the corresponding values . the persistent query execution system evaluates the event condition each time a point is added to any register in the set of trigger registers for the persistent query . the trigger registers syntax is as follows . the event condition is encoded in the section of the query denoted by the syntax is that of a java expression , extended to allow use of identifiers in the same register . winnow . name syntax as in the payload specification . allowed names include statistics , valid , and val . all such identifiers resolve to primitive double type values . in the expression , valid is 1 . 0 if the window is valid and 0 . 0 otherwise . the name val refers to the value in the last point added to the window . select abc . 50 . mean , def . 5 min . val , def . 1 min . all , def . 50 . stdev from abc , def where abc . 50 . mean & gt ; def . 50 . mean + def . 50 . stdev after adding the corresponding persistent query to an engine , the following occurs . after each new point is inserted into register abc or def , the condition abc . 50 . mean & gt ; def . 50 . mean + def . 50 . stdev is evaluated . if the condition is true , then the payload abc . 50 . mean , def . 5 min . val , def . 1 min . all , def . 50 . stdev is output . the process of converting a query string to a persistent query is called compilation . two different compilation methods are dynamic compilation and runtime compilation . in dynamic compilation , a query parser class takes the query string as input and produces a java program . ( the query parser class translates the query into a standard form , ensures that the system can satisfy references to identifiers , and creates a fetcher class for each identifier .) then a dynamic java package uses the java program to make a proxy class for the event condition evaluator . in runtime compilation , the java compiler javac and the disk are used to generate class bytes directly . the following are step - by - step descriptions of some system processes , including details about how inter - process synchronization allows some processes to proceed concurrently . there are descriptions of processes to initialize the system , add a register , add a window , add a persistent query , and add a point . the system is initialized by creating a new engine instance or by loading a persisted engine instance from a file , using the following steps . 1 . create a sequencer . ( the sequencer provides a unique number for each input value . the sequence numbers are used to ensure that each result is detected exactly once .) 2 . create a parser . ( the parser plays a role in converting query strings to persistent queries .) 3 . set a compilation directory . ( the compilation directory is used as a container for class files during runtime compilation of persistent queries .) 4 . register an event listener with the system . ( as part of the event detection and payload output functions , the event listener receives notifications when the system detects true event conditions and receives output payloads .) when de - persisting an engine from a file , initialization also contains these steps : 5 . de - persist and add to the engine any registers and any windows specified by the file 6 . compile any query strings specified by the file to form persistent queries . add the persistent queries to the engine . after this process , the engine is ready to undertake other methods , including adding registers , windows , persistent queries , and data points . these other methods can be performed concurrently with each other after the engine is instantiated . the method to add a register to the engine comprises the following steps : 2 . add a reference to the register to a hashtable with register names as keys . this hashtable enables fast lookup of a register by name . 3 . if the register contains any windows , add each window name , in the format register . window , to an engine hashtable with window names as keys . this hashtable enables fast lookup of a window by register and window name . the process to add a window to a register involves obtaining and releasing locks in order to ensure mutual exclusion between adding a window and parts of other processes . for each register , there are two locks , a basic lock and a booster lock . also , each window has a lock . obtaining a lock may involve waiting for the lock to be released by another process . releasing a lock allows it to be obtained by another process . the process to add a window to a register comprises the following steps . 1 . obtain the basic register lock in order to ensure mutual exclusion with the process of adding a point to the register . 2 . set the number of points in the window to zero , and set window endpoints to indicate that the most recent point in the register is one position beyond the points in the window . 3 . associate the window with the register , adding the window to the list of windows to be updated for each input point received by the register . 4 . add the window name , in the format register . window , to an engine hashtable with window names as keys . this hashtable enables fast lookup of the window by register and window name . 6 . to use historical data to populate the window , use the following iterative process . 6b . get a reference to the next historical point to add to the window , i . e ., a reference to the most recent point in the register that was added before the window and is not in the window . 6f . update the window endpoints to indicate that the referenced point is in the window . 6h . determine whether the process of populating the window is complete , as follows . for a value window , check whether the number of points in the window equals or exceeds the target . for a time window , check whether the next historical point to be added falls before the beginning of the time interval . if the process is not complete , then go to step 6a . the engine has a query lock , which is used to ensure mutual exclusion between the process of adding a persistent query and the process of executing a persistent query . the process to add a persistent query , specified by a query string , to the engine comprises the following steps . 2 . parse the query to obtain strings corresponding to the payload specification , trigger registers , and event condition . 3 . parse the payload specification , trigger registers , and event condition strings to determine all references to registers , windows , and names . check that the referenced entities exist . if so , then proceed . if not , then release the query lock and exit this process . 4 . compile the query string to form a persistent query , using runtime or dynamic compilation as described previously . 5 . register the persistent query with any with any trigger registers of the persistent query . each input value is accompanied by a label that indicates the time series to which the value belongs . the process by which the engine handles an input time series value comprises the following steps . 1 . use the filter to determine whether the label refers to a time series that corresponds to a register in the engine . if not then exit this process . 2 . use the sequencer to generate a unique sequence number for the value . form a point that comprises the value and the unique sequence number . 3 . obtain the register basic lock . this ensures that no window is added to the register and that no other point is added to the register while the point is being added to the register . 4 . check whether the size of the buffer in the register is large enough to include the point in addition to any previous points in the buffer . if the buffer is not large enough , then boost the buffer size as follows . 4a . obtain the booster lock on the register . this ensures mutual exclusion with part of the process to populate a new window with historical points . 4c . copy existing points into any corresponding positions of newly allocated buffer storage . ( a similar process to steps 4a to 4e is used to shrink the buffer size when little of the buffer is being used after data expiry or window deletion .) 5 . for each window of the register , ( a ) obtain the window lock ; ( b ) update the window to account for the new point ; ( c ) determine which points ( if any ) have expired from the window , and update statistics to account for expiry ; ( d ) release the window lock . 6 . discard points from the register buffer that will have no further effect on statistics or values for any window . 7 . for each persistent query for which the register is a trigger , do the following . obtain the query lock . evaluate the event condition . if the event condition is true , then fetch and output the payload as specified by the payload specification . then release the query lock .