Chronaxis用户手册English
本页目录

chronaxis.execution.record_event_durations

源码基线:8904c2f744951857659abd40aaa3535d57faf53c

1"""按需计算每段事件的持续时长,只为周期模式保存必要驱动时间。23实际模式直接使用事件范围。固定/DBC需要知道事件两端落在哪对报文中,因而4保存每条所选驱动的一个整数时间;按索引二分定位,只回读相关记录对。该文件5没有数值、原帧或另一时间轴,未请求此类统计时不建立;关闭自动删除。6"""78import heapq9from ..core.models import Interval10from ..core.calculations import CalculationDefinition11from ..core.numeric import ScalarValue12from ..core.types import SignalDType as D,QualityFlag as Q13from ..results.errors import ResultClosedError14from ..results.spool import _reserve_owned_ram,_release_owned_ram,_cleanup_owner15from .record_time_calculation import RecordTimeCalculation16from .history import _metadata_bytes17from ..planning.record_execution import is_event_duration181920class RecordEventDurations:21    """拥有必要时点文件、尚缺右端的事件及一个短生命周期数值查询。"""2223    def __init__(self,plan,budget,work_dir,steps,consumer,*,indexes=None):24        """预付有限索引状态,不为actual创建文件。参数: 计划/预算/目录/周期/回调;indexes借用共享必要时点,不在此重复保存。返回: owner。异常: 原构造错误。"""25        self._plan,self._budget,self._path,self._steps,self._consumer=plan,budget,work_dir,steps,consumer26        self._requests=tuple(item for item in plan.calculations if is_event_duration(item))27        self._choices=dict(plan.intervals.resolved)28        self._held_cost=self._fixed_cost=self._pending_cost=029        self._indexes=indexes30        self._queue=[]31        self._serial=032        self._calculation=None33        self._closed=self._failed=False34        try:35            _reserve_owned_ram(self,131072+32768*len(self._requests)+32*_metadata_bytes(self._requests),'_fixed_cost')36        except BaseException as error:37            _cleanup_owner(self,error,'record_event_duration_cleanup_owner','事件时长构造')38            raise3940    def _open(self):41        """拒绝关闭/失败实例。参数: 无。返回: None。异常: ResultClosedError。"""42        if self._closed or self._failed:43            raise ResultClosedError('事件时长已关闭或失败')4445    def observe_group(self,group):46        """父已更新共享时点索引,尝试完成等待中的事件。参数: 完整组。返回: None。异常: 查询原错。"""47        self._open()48        self._flush_ready()4950    def observe_event(self,event):51        """只为匹配事件建立必要查询,缺右端时暂存端点和ID。参数: 事件。返回: None。异常: 预算/求值原错。"""52        self._open()53        for request in self._requests:54            if request.scope!='event:'+event.rule.rule_id:55                continue56            end=event.start_ns if event.end_ns is None else event.end_ns57            # 快捷时长与一般事件计算使用同一选择范围;确认等于结束时保留空区间。58            rule=next(item for item in self._plan.rules if item.rule_id==event.rule.rule_id)59            start=event.confirmed_ns if rule.selection_origin=='confirmed' else event.start_ns60            cost=8192+16*_metadata_bytes(event.event_id)61            _reserve_owned_ram(self,cost,'_pending_cost')62            heapq.heappush(self._queue,(end,self._serial,request,event.event_id,start,cost,63                                        bool(event.dependency_quality & Q.ESTIMATED)))64            self._serial+=165        self._flush_ready()6667    def _calculate(self,request,event_id,start_ns,end_ns,estimated=False):68        """只借取事件两侧及区间内的驱动点,复用原两后端时长核。6970        参数: 请求/父ID/真实端点。返回: None,结果交回调。异常: 构造/数值/发布原错。71        """72        step=self._steps[request.calculation_id]73        spec=CalculationDefinition(request.calculation_id,'duration',Interval(start_ns,end_ns),request.partial_policy,74                        request.unit,'event',request.minimum_coverage,config_version=self._plan.config_version)75        try:76            self._calculation=RecordTimeCalculation(self._budget,spec,'1',D.BOOL,step,77                backend=self._plan.execution.backend,batch_intervals=64)78        except BaseException as error:79            self._calculation=getattr(error,'record_time_cleanup_owner',None)80            raise81        value=ScalarValue(True,D.BOOL,True,Q.NONE)82        if step is None:83            if start_ns<end_ns:84                self._calculation.consume(((start_ns,value),(end_ns,value)))85        else:86            driver=self._choices[request.calculation_id].driver87            count=self._indexes.count(driver)88            if count:89                first=self._indexes.lower(driver,start_ns)90                if first==count or first>0 and self._indexes.at(driver,first)>start_ns:91                    first-=192                last=min(count-1,self._indexes.lower(driver,end_ns))93                for index in range(first,last+1):94                    self._calculation.consume(((self._indexes.at(driver,index),value),))95        result=self._calculation.finish()96        if estimated:97            from .transform_partial import partial_result98            result=partial_result(result,request.partial_policy)99        self._consumer(request,event_id,result)100        self._calculation.close();self._calculation=None101102    def _flush_ready(self,final=False):103        """保留仍缺右端的请求,其余按必要范围计算;EOF不补记录。104105        参数: final只在真实来源EOF后使用。返回: None。异常: 原查询错,费用留到close。106        """107        pending=[]108        try:109            while self._queue:110                item=heapq.heappop(self._queue)111                end,serial,request,event_id,start,cost,estimated=item112                driver=self._choices[request.calculation_id].driver113                last=None if self._indexes is None or driver is None else self._indexes.last(driver)114                if not final and self._steps[request.calculation_id] is not None and (last is None or last<end):115                    pending.append(item)116                    continue117                self._calculate(request,event_id,start,end,estimated)118                item=None119                _release_owned_ram(self,cost,'_pending_cost')120        except BaseException:121            self._failed=True122            raise123        finally:124            for item in pending:125                heapq.heappush(self._queue,item)126127    def finish(self):128        """真实EOF后结算未完成范围,不假造周期尾段。参数: 无。返回: None。异常: 原计算错。"""129        self._open()130        self._flush_ready(final=True)131132    @property133    def closed(self):134        """返回关闭状态。参数: 无。返回: bool。异常: 无。"""135        return self._closed136137    def close(self):138        """只关闭自己的临时文件,成功后才撤销责任。参数: 无。返回: None。异常: 原关闭错可重试。"""139        if self._closed:140            return141        if self._calculation is not None:142            self._calculation.close();self._calculation=None143        self._queue.clear()144        self._plan=self._requests=self._consumer=self._choices=None145        _release_owned_ram(self,self._pending_cost,'_pending_cost')146        _release_owned_ram(self,self._fixed_cost,'_fixed_cost')147        self._closed=True148
Chronaxis 用户手册 · 离线阅读