带版本的共享缓冲区
当股票模式以一个事件流作为输入时,状态转换将会作用于事件流从而引起事件的状态变化。结合窗口对参与匹配的事件的限制以及模式中结合事件上下文(状态)的过滤条件,同一事件流随着时间的流动或者多次运行都会产生多种不同的匹配结果。在此我们为示例模式构建了一个事件流以及其可能产生的三种匹配结果,如下图:
在事件e6到达后,会产生两个结果:R1和R2,而结果R3将会在e8到来之后匹配成功。图中可见R1、R2和R3这三个匹配结果在一些事件上产生了重叠。
为了保留已匹配的结果,需要将匹配结果中包含的事件保存起来,这种数据结构在论文中称之为缓冲区。首先,初步的解决方案是为独立匹配而设计缓冲区,在缓冲区中为了让不同的状态存储不同的事件,每个状态对应一个栈空间(除了最终态),针对上面三个匹配的独立缓冲区如下图a-c所示:
上图中的a-c描述了存储R1-R3三个匹配结果的独立缓冲区。每个栈包含事件和指向事件的指针,它们通常是因为“begin”或者“take”状态转换而被加入到缓冲区中。每个事件有一个前置指针指向之前被选择的事件,之前的事件要么在相同的栈中要么在之前的栈中。当一个事件被加入到缓冲区中,它的指针也一同被设置,在缓冲区中从该事件开始沿着前置指针的一次遍历将能检索到完整的匹配。
为每个匹配单独构建缓冲区,从技术实现上来看是没有问题的,但随着事件的流入,模式的匹配结果也将会变得更多,从而导致缓冲区的数量也极具上升。为了避免缓冲区、栈的数目过多以及在栈中频繁地复制事件,一种优化措施是将这些独立的缓冲区合并为单一共享的缓冲区。这个过程最终是基于合并这些独立缓冲区中相应的栈来实现的。为了在遍历时找到匹配的事件流,合并栈中相同的事件时必须保留他们的前置指针,这一步是整个优化措施的关键,如果草率地合并这些栈中的事件,在共享缓冲区中沿着这些已存在的指针所进行的遍历将会导致错误的结果。举个例子,假设我们将R2的a[i]栈中的e4元素以及b栈中的e6元素与R3缓冲区里的a[i]栈以及b栈合并(来达到合并R1和R2缓冲区的目的),从e6开始的一次遍历会产生包含:e1,e2,e3,e4和e6元素的结果,而这是一个错误的结果。产生这一问题的原因是因为在合并的过程中,没有区分来自不同缓冲区中的不同指针。
为了解决这个问题,