You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
619 lines
12 KiB
619 lines
12 KiB
package atree
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
octopus "gordenko.dev/dima/diploma"
|
|
)
|
|
|
|
type IterateAllCumulativeByTreeCursorReq struct {
|
|
FracDigits byte
|
|
PageNo uint32
|
|
EndTimestamp uint32
|
|
EndValue float64
|
|
ResponseWriter *CumulativeMeasureWriter
|
|
}
|
|
|
|
func (s *Atree) IterateAllCumulativeByTreeCursor(req IterateAllCumulativeByTreeCursorReq) error {
|
|
buf, err := s.fetchDataPage(req.PageNo)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
treeCursor, err := NewBackwardCursor(BackwardCursorOptions{
|
|
PageNo: req.PageNo,
|
|
PageData: buf,
|
|
Atree: s,
|
|
FracDigits: req.FracDigits,
|
|
MetricType: octopus.Cumulative,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer treeCursor.Close()
|
|
|
|
var (
|
|
endTimestamp = req.EndTimestamp
|
|
endValue = req.EndValue
|
|
)
|
|
|
|
for {
|
|
timestamp, value, done, err := treeCursor.Prev()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if done {
|
|
err := req.ResponseWriter.WriteMeasure(CumulativeMeasure{
|
|
Timestamp: endTimestamp,
|
|
Value: endValue,
|
|
Total: endValue,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
err = req.ResponseWriter.WriteMeasure(CumulativeMeasure{
|
|
Timestamp: endTimestamp,
|
|
Value: endValue,
|
|
Total: endValue - value,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
endTimestamp = timestamp
|
|
endValue = value
|
|
}
|
|
}
|
|
|
|
type ContinueIterateCumulativeByTreeCursorReq struct {
|
|
FracDigits byte
|
|
Since uint32
|
|
Until uint32
|
|
LastPageNo uint32
|
|
EndTimestamp uint32
|
|
EndValue float64
|
|
ResponseWriter *CumulativeMeasureWriter
|
|
}
|
|
|
|
func (s *Atree) ContinueIterateCumulativeByTreeCursor(req ContinueIterateCumulativeByTreeCursorReq) error {
|
|
buf, err := s.fetchDataPage(req.LastPageNo)
|
|
if err != nil {
|
|
return fmt.Errorf("fetchDataPage(%d): %s", req.LastPageNo, err)
|
|
}
|
|
|
|
treeCursor, err := NewBackwardCursor(BackwardCursorOptions{
|
|
PageNo: req.LastPageNo,
|
|
PageData: buf,
|
|
Atree: s,
|
|
FracDigits: req.FracDigits,
|
|
MetricType: octopus.Cumulative,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer treeCursor.Close()
|
|
|
|
var (
|
|
endTimestamp = req.EndTimestamp
|
|
endValue = req.EndValue
|
|
)
|
|
|
|
for {
|
|
timestamp, value, done, err := treeCursor.Prev()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if done {
|
|
err := req.ResponseWriter.WriteMeasure(CumulativeMeasure{
|
|
Timestamp: endTimestamp,
|
|
Value: endValue,
|
|
Total: endValue,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
if timestamp <= req.Until {
|
|
err := req.ResponseWriter.WriteMeasure(CumulativeMeasure{
|
|
Timestamp: endTimestamp,
|
|
Value: endValue,
|
|
Total: endValue - value,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if timestamp < req.Since {
|
|
return nil
|
|
}
|
|
} else {
|
|
// bug panic
|
|
panic("continue cumulative but timestamp > req.Until")
|
|
}
|
|
}
|
|
}
|
|
|
|
type FindAndIterateCumulativeByTreeCursorReq struct {
|
|
FracDigits byte
|
|
Since uint32
|
|
Until uint32
|
|
RootPageNo uint32
|
|
ResponseWriter *CumulativeMeasureWriter
|
|
}
|
|
|
|
func (s *Atree) FindAndIterateCumulativeByTreeCursor(req FindAndIterateCumulativeByTreeCursorReq) error {
|
|
pageNo, buf, err := s.findDataPage(req.RootPageNo, req.Until)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
treeCursor, err := NewBackwardCursor(BackwardCursorOptions{
|
|
PageNo: pageNo,
|
|
PageData: buf,
|
|
Atree: s,
|
|
FracDigits: req.FracDigits,
|
|
MetricType: octopus.Cumulative,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer treeCursor.Close()
|
|
|
|
var (
|
|
endTimestamp uint32
|
|
endValue float64
|
|
)
|
|
|
|
for {
|
|
timestamp, value, done, err := treeCursor.Prev()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if done {
|
|
if endTimestamp > 0 {
|
|
err := req.ResponseWriter.WriteMeasure(CumulativeMeasure{
|
|
Timestamp: endTimestamp,
|
|
Value: endValue,
|
|
Total: endValue,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
if timestamp > req.Until {
|
|
continue
|
|
}
|
|
|
|
if endTimestamp > 0 {
|
|
err := req.ResponseWriter.WriteMeasure(CumulativeMeasure{
|
|
Timestamp: endTimestamp,
|
|
Value: endValue,
|
|
Total: endValue - value,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
endTimestamp = timestamp
|
|
endValue = value
|
|
|
|
if timestamp < req.Since {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
type IterateAllInstantByTreeCursorReq struct {
|
|
FracDigits byte
|
|
PageNo uint32
|
|
ResponseWriter *InstantMeasureWriter
|
|
}
|
|
|
|
func (s *Atree) IterateAllInstantByTreeCursor(req IterateAllInstantByTreeCursorReq) error {
|
|
buf, err := s.fetchDataPage(req.PageNo)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
treeCursor, err := NewBackwardCursor(BackwardCursorOptions{
|
|
PageNo: req.PageNo,
|
|
PageData: buf,
|
|
Atree: s,
|
|
FracDigits: req.FracDigits,
|
|
MetricType: octopus.Instant,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer treeCursor.Close()
|
|
|
|
for {
|
|
timestamp, value, done, err := treeCursor.Prev()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if done {
|
|
return nil
|
|
}
|
|
|
|
err = req.ResponseWriter.WriteMeasure(InstantMeasure{
|
|
Timestamp: timestamp,
|
|
Value: value,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
type ContinueIterateInstantByTreeCursorReq struct {
|
|
FracDigits byte
|
|
Since uint32
|
|
Until uint32
|
|
LastPageNo uint32
|
|
ResponseWriter *InstantMeasureWriter
|
|
}
|
|
|
|
func (s *Atree) ContinueIterateInstantByTreeCursor(req ContinueIterateInstantByTreeCursorReq) error {
|
|
buf, err := s.fetchDataPage(req.LastPageNo)
|
|
if err != nil {
|
|
return fmt.Errorf("fetchDataPage(%d): %s", req.LastPageNo, err)
|
|
}
|
|
|
|
treeCursor, err := NewBackwardCursor(BackwardCursorOptions{
|
|
PageNo: req.LastPageNo,
|
|
PageData: buf,
|
|
Atree: s,
|
|
FracDigits: req.FracDigits,
|
|
MetricType: octopus.Instant,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer treeCursor.Close()
|
|
|
|
for {
|
|
timestamp, value, done, err := treeCursor.Prev()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if done {
|
|
// - записи закончились;
|
|
return nil
|
|
}
|
|
|
|
if timestamp > req.Until {
|
|
panic("continue instant timestamp > req.Until")
|
|
}
|
|
|
|
if timestamp < req.Since {
|
|
return nil
|
|
}
|
|
|
|
err = req.ResponseWriter.WriteMeasure(InstantMeasure{
|
|
Timestamp: timestamp,
|
|
Value: value,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
type FindAndIterateInstantByTreeCursorReq struct {
|
|
FracDigits byte
|
|
Since uint32
|
|
Until uint32
|
|
RootPageNo uint32
|
|
ResponseWriter *InstantMeasureWriter
|
|
}
|
|
|
|
func (s *Atree) FindAndIterateInstantByTreeCursor(req FindAndIterateInstantByTreeCursorReq) error {
|
|
pageNo, buf, err := s.findDataPage(req.RootPageNo, req.Until)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
treeCursor, err := NewBackwardCursor(BackwardCursorOptions{
|
|
PageNo: pageNo,
|
|
PageData: buf,
|
|
Atree: s,
|
|
FracDigits: req.FracDigits,
|
|
MetricType: octopus.Instant,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer treeCursor.Close()
|
|
|
|
for {
|
|
timestamp, value, done, err := treeCursor.Prev()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if done {
|
|
return nil
|
|
}
|
|
|
|
if timestamp > req.Until {
|
|
continue
|
|
}
|
|
|
|
if timestamp < req.Since {
|
|
return nil
|
|
}
|
|
|
|
err = req.ResponseWriter.WriteMeasure(InstantMeasure{
|
|
Timestamp: timestamp,
|
|
Value: value,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
type ContinueCollectInstantPeriodsReq struct {
|
|
FracDigits byte
|
|
Aggregator *InstantAggregator
|
|
ResponseWriter *InstantPeriodsWriter
|
|
LastPageNo uint32
|
|
Since uint32
|
|
Until uint32
|
|
}
|
|
|
|
func (s *Atree) ContinueCollectInstantPeriods(req ContinueCollectInstantPeriodsReq) error {
|
|
buf, err := s.fetchDataPage(req.LastPageNo)
|
|
if err != nil {
|
|
return fmt.Errorf("fetchDataPage(%d): %s", req.LastPageNo, err)
|
|
}
|
|
|
|
treeCursor, err := NewBackwardCursor(BackwardCursorOptions{
|
|
PageNo: req.LastPageNo,
|
|
PageData: buf,
|
|
Atree: s,
|
|
FracDigits: req.FracDigits,
|
|
MetricType: octopus.Instant,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer treeCursor.Close()
|
|
|
|
var period InstantPeriod
|
|
|
|
for {
|
|
timestamp, value, done, err := treeCursor.Prev()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if done || timestamp < req.Since {
|
|
isCompleted := req.Aggregator.FillPeriod(timestamp, &period)
|
|
if isCompleted {
|
|
err := req.ResponseWriter.WritePeriod(period)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
if timestamp <= req.Until {
|
|
isCompleted := req.Aggregator.Feed(timestamp, value, &period)
|
|
if isCompleted {
|
|
err := req.ResponseWriter.WritePeriod(period)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
type FindInstantPeriodsReq struct {
|
|
FracDigits byte
|
|
ResponseWriter *InstantPeriodsWriter
|
|
RootPageNo uint32
|
|
Since uint32
|
|
Until uint32
|
|
GroupBy octopus.GroupBy
|
|
FirstHourOfDay int
|
|
LastDayOfMonth int
|
|
}
|
|
|
|
func (s *Atree) FindInstantPeriods(req FindInstantPeriodsReq) error {
|
|
pageNo, buf, err := s.findDataPage(req.RootPageNo, req.Until)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
aggregator, err := NewInstantAggregator(InstantAggregatorOptions{
|
|
GroupBy: req.GroupBy,
|
|
FirstHourOfDay: req.FirstHourOfDay,
|
|
LastDayOfMonth: req.LastDayOfMonth,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cursor, err := NewBackwardCursor(BackwardCursorOptions{
|
|
PageNo: pageNo,
|
|
PageData: buf,
|
|
Atree: s,
|
|
FracDigits: req.FracDigits,
|
|
MetricType: octopus.Instant,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer cursor.Close()
|
|
|
|
var period InstantPeriod
|
|
|
|
for {
|
|
timestamp, value, done, err := cursor.Prev()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if done || timestamp < req.Since {
|
|
isCompleted := aggregator.FillPeriod(timestamp, &period)
|
|
if isCompleted {
|
|
err := req.ResponseWriter.WritePeriod(period)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
if timestamp <= req.Until {
|
|
isCompleted := aggregator.Feed(timestamp, value, &period)
|
|
if isCompleted {
|
|
err := req.ResponseWriter.WritePeriod(period)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
type FindCumulativePeriodsReq struct {
|
|
FracDigits byte
|
|
ResponseWriter *CumulativePeriodsWriter
|
|
RootPageNo uint32
|
|
Since uint32
|
|
Until uint32
|
|
GroupBy octopus.GroupBy
|
|
FirstHourOfDay int
|
|
LastDayOfMonth int
|
|
}
|
|
|
|
func (s *Atree) FindCumulativePeriods(req FindCumulativePeriodsReq) error {
|
|
pageNo, buf, err := s.findDataPage(req.RootPageNo, req.Until)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
aggregator, err := NewCumulativeAggregator(CumulativeAggregatorOptions{
|
|
GroupBy: req.GroupBy,
|
|
FirstHourOfDay: req.FirstHourOfDay,
|
|
LastDayOfMonth: req.LastDayOfMonth,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cursor, err := NewBackwardCursor(BackwardCursorOptions{
|
|
PageNo: pageNo,
|
|
PageData: buf,
|
|
Atree: s,
|
|
FracDigits: req.FracDigits,
|
|
MetricType: octopus.Cumulative,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer cursor.Close()
|
|
|
|
var period CumulativePeriod
|
|
|
|
for {
|
|
timestamp, value, done, err := cursor.Prev()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if done || timestamp < req.Since {
|
|
isCompleted := aggregator.FillPeriod(timestamp, value, &period)
|
|
if isCompleted {
|
|
err := req.ResponseWriter.WritePeriod(period)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
if timestamp <= req.Until {
|
|
isCompleted := aggregator.Feed(timestamp, value, &period)
|
|
if isCompleted {
|
|
err := req.ResponseWriter.WritePeriod(period)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
type ContinueCollectCumulativePeriodsReq struct {
|
|
FracDigits byte
|
|
Aggregator *CumulativeAggregator
|
|
ResponseWriter *CumulativePeriodsWriter
|
|
LastPageNo uint32
|
|
Since uint32
|
|
Until uint32
|
|
}
|
|
|
|
func (s *Atree) ContinueCollectCumulativePeriods(req ContinueCollectCumulativePeriodsReq) error {
|
|
buf, err := s.fetchDataPage(req.LastPageNo)
|
|
if err != nil {
|
|
return fmt.Errorf("fetchDataPage(%d): %s", req.LastPageNo, err)
|
|
}
|
|
|
|
treeCursor, err := NewBackwardCursor(BackwardCursorOptions{
|
|
PageNo: req.LastPageNo,
|
|
PageData: buf,
|
|
Atree: s,
|
|
FracDigits: req.FracDigits,
|
|
MetricType: octopus.Cumulative,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer treeCursor.Close()
|
|
|
|
var period CumulativePeriod
|
|
|
|
for {
|
|
timestamp, value, done, err := treeCursor.Prev()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if done || timestamp < req.Since {
|
|
isCompleted := req.Aggregator.FillPeriod(timestamp, value, &period)
|
|
if isCompleted {
|
|
err := req.ResponseWriter.WritePeriod(period)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
if timestamp <= req.Until {
|
|
isCompleted := req.Aggregator.Feed(timestamp, value, &period)
|
|
if isCompleted {
|
|
err := req.ResponseWriter.WritePeriod(period)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|