package proto import ( "fmt" "time" "gordenko.dev/dima/diploma" "gordenko.dev/dima/diploma/bin" "gordenko.dev/dima/diploma/bufreader" ) const ( TypeDeleteMeasures byte = 1 TypeListCurrentValues byte = 2 TypeListInstantMeasures byte = 3 TypeListCumulativeMeasures byte = 33 TypeListInstantPeriods byte = 4 TypeListCumulativePeriods byte = 44 TypeGetMetric byte = 5 TypeAddMetric byte = 6 TypeListAllInstantMeasures byte = 8 TypeListAllCumulativeMeasures byte = 88 TypeAppendMeasure byte = 10 TypeAppendMeasures byte = 11 TypeDeleteMetric byte = 12 RespPartOfValue byte = 255 RespEndOfValue byte = 254 RespError byte = 253 RespSuccess byte = 252 RespValue byte = 251 ErrNoMetric = 1 ErrDuplicate = 2 ErrWrongMetricType = 3 ErrWrongFracDigits = 4 ErrExpiredMeasure = 5 ErrNonMonotonicValue = 6 ErrEmptyMetricID = 7 ErrInvalidRange = 8 ErrUnexpected = 9 ) func ErrorCodeToText(code uint16) string { switch code { case ErrNoMetric: return "NoMetric" case ErrDuplicate: return "Duplicate" case ErrWrongMetricType: return "WrongMetricType" case ErrWrongFracDigits: return "WrongFracDigits" case ErrExpiredMeasure: return "ExpiredMeasure" case ErrNonMonotonicValue: return "NonMonotonicValue" case ErrEmptyMetricID: return "EmptyMetricID" case ErrInvalidRange: return "InvalidRange" case ErrUnexpected: return "Unexpected" default: return "" } } // common type Metric struct { MetricID uint32 MetricType diploma.MetricType FracDigits int } type AppendError struct { MetricID uint32 ErrorCode uint16 } type TimeBound struct { Year int Month time.Month Day int } type CumulativeMeasure struct { Timestamp uint32 Value float64 Total float64 } type CumulativePeriod struct { Period uint32 Since uint32 Until uint32 EndValue float64 Total float64 } type InstantMeasure struct { Timestamp uint32 Value float64 } type InstantPeriod struct { Period uint32 Since uint32 Until uint32 Min float64 Max float64 Avg float64 } type CurrentValue struct { MetricID uint32 Timestamp uint32 Value float64 } // API reqs type GetMetricReq struct { MetricID uint32 } func ReadGetMetricReq(r *bufreader.BufferedReader) (m GetMetricReq, err error) { m.MetricID, err = bin.ReadUint32(r) if err != nil { err = fmt.Errorf("read req: %s", err) return } return } type ListCurrentValuesReq struct { MetricIDs []uint32 } func ReadListCurrentValuesReq(r *bufreader.BufferedReader) (m ListCurrentValuesReq, err error) { qty, err := bin.ReadUint16(r) if err != nil { err = fmt.Errorf("read req: %s", err) return } for i := range int(qty) { var metricID uint32 metricID, err = bin.ReadUint32(r) if err != nil { err = fmt.Errorf("read metricID (#%d): %s", i, err) return } m.MetricIDs = append(m.MetricIDs, metricID) } return } type AddMetricReq struct { MetricID uint32 MetricType diploma.MetricType FracDigits int } func ReadAddMetricReq(r *bufreader.BufferedReader) (m AddMetricReq, err error) { arr, err := r.ReadN(6) if err != nil { err = fmt.Errorf("read req: %s", err) return } return UnpackAddMetricReq(arr), nil } func UnpackAddMetricReq(arr []byte) (m AddMetricReq) { m.MetricID = bin.GetUint32(arr) m.MetricType = diploma.MetricType(arr[4]) m.FracDigits = int(arr[5]) return } type DeleteMetricReq struct { MetricID uint32 } func ReadDeleteMetricReq(r *bufreader.BufferedReader) (m DeleteMetricReq, err error) { m.MetricID, err = bin.ReadUint32(r) if err != nil { err = fmt.Errorf("read req: %s", err) return } return } type DeleteMeasuresReq struct { MetricID uint32 Since uint32 // timestamp (optional) } func ReadDeleteMeasuresReq(r *bufreader.BufferedReader) (m DeleteMeasuresReq, err error) { arr, err := r.ReadN(8) if err != nil { err = fmt.Errorf("read req: %s", err) return } return UnpackDeleteMeasuresReq(arr), nil } func UnpackDeleteMeasuresReq(arr []byte) (m DeleteMeasuresReq) { m.MetricID = bin.GetUint32(arr) m.Since = bin.GetUint32(arr[4:]) return } type AppendMeasureReq struct { MetricID uint32 Timestamp uint32 Value float64 } func ReadAppendMeasureReq(r *bufreader.BufferedReader) (m AppendMeasureReq, err error) { arr, err := r.ReadN(16) if err != nil { err = fmt.Errorf("read req: %s", err) return } return UnpackAppendMeasureReq(arr), nil } func UnpackAppendMeasureReq(arr []byte) (m AppendMeasureReq) { m.MetricID = bin.GetUint32(arr) m.Timestamp = bin.GetUint32(arr[4:]) m.Value = bin.GetFloat64(arr[8:]) return } type AppendMeasuresReq struct { MetricID uint32 Measures []Measure } type Measure struct { Timestamp uint32 Value float64 } func ReadAppendMeasuresReq(r *bufreader.BufferedReader) (m AppendMeasuresReq, err error) { prefix, err := bin.ReadN(r, 6) // metricID + measures qty if err != nil { err = fmt.Errorf("read prefix: %s", err) return } m.MetricID = bin.GetUint32(prefix[0:]) qty := bin.GetUint16(prefix[4:]) for i := range int(qty) { var measure Measure measure.Timestamp, err = bin.ReadUint32(r) if err != nil { err = fmt.Errorf("read timestamp (#%d): %s", i, err) return } measure.Value, err = bin.ReadFloat64(r) if err != nil { err = fmt.Errorf("read value (#%d): %s", i, err) return } m.Measures = append(m.Measures, measure) } return } type MetricMeasure struct { MetricID uint32 Timestamp uint32 Value float64 } func ReadAppendMeasurePerMetricReq(r *bufreader.BufferedReader) (measures []MetricMeasure, err error) { qty, err := bin.ReadUint16(r) if err != nil { return } var tmp = make([]byte, 16) for range int(qty) { err = bin.ReadNInto(r, tmp) if err != nil { return } measures = append(measures, MetricMeasure{ MetricID: bin.GetUint32(tmp[0:]), Timestamp: bin.GetUint32(tmp[4:]), Value: bin.GetFloat64(tmp[8:]), }) } return } type ListAllInstantMetricMeasuresReq struct { MetricID uint32 } func ReadListAllInstantMeasuresReq(r *bufreader.BufferedReader) (m ListAllInstantMetricMeasuresReq, err error) { m.MetricID, err = bin.ReadUint32(r) if err != nil { err = fmt.Errorf("read req: %s", err) return } return } type ListAllCumulativeMeasuresReq struct { MetricID uint32 } func ReadListAllCumulativeMeasuresReq(r *bufreader.BufferedReader) (m ListAllCumulativeMeasuresReq, err error) { m.MetricID, err = bin.ReadUint32(r) if err != nil { err = fmt.Errorf("read req: %s", err) return } return } type ListInstantMeasuresReq struct { MetricID uint32 Since uint32 Until uint32 } func ReadListInstantMeasuresReq(r *bufreader.BufferedReader) (m ListInstantMeasuresReq, err error) { arr, err := r.ReadN(12) if err != nil { err = fmt.Errorf("read req: %s", err) return } return UnpackListInstantMeasuresReq(arr), nil } func UnpackListInstantMeasuresReq(arr []byte) (m ListInstantMeasuresReq) { m.MetricID = bin.GetUint32(arr[0:]) m.Since = bin.GetUint32(arr[4:]) m.Until = bin.GetUint32(arr[8:]) return } type ListCumulativeMeasuresReq struct { MetricID uint32 Since uint32 Until uint32 } func ReadListCumulativeMeasuresReq(r *bufreader.BufferedReader) (m ListCumulativeMeasuresReq, err error) { arr, err := r.ReadN(12) if err != nil { err = fmt.Errorf("read req: %s", err) return } return UnpackListCumulativeMeasuresReq(arr), nil } func UnpackListCumulativeMeasuresReq(arr []byte) (m ListCumulativeMeasuresReq) { m.MetricID = bin.GetUint32(arr) m.Since = bin.GetUint32(arr[4:]) m.Until = bin.GetUint32(arr[8:]) return } type ListInstantPeriodsReq struct { MetricID uint32 Since TimeBound Until TimeBound GroupBy diploma.GroupBy AggregateFuncs byte FirstHourOfDay int } func ReadListInstantPeriodsReq(r *bufreader.BufferedReader) (m ListInstantPeriodsReq, err error) { arr, err := r.ReadN(15) if err != nil { err = fmt.Errorf("read req: %s", err) return } return UnpackListInstantPeriodsReq(arr), nil } func UnpackListInstantPeriodsReq(arr []byte) (m ListInstantPeriodsReq) { m.MetricID = bin.GetUint32(arr) m.Since = TimeBound{ Year: int(bin.GetUint16(arr[4:])), Month: time.Month(arr[6]), Day: int(arr[7]), } m.Until = TimeBound{ Year: int(bin.GetUint16(arr[8:])), Month: time.Month(arr[10]), Day: int(arr[11]), } m.GroupBy = diploma.GroupBy(arr[12]) m.AggregateFuncs = arr[13] m.FirstHourOfDay = int(arr[14]) return } type ListCumulativePeriodsReq struct { MetricID uint32 Since TimeBound Until TimeBound GroupBy diploma.GroupBy FirstHourOfDay int } func ReadListCumulativePeriodsReq(r *bufreader.BufferedReader) (m ListCumulativePeriodsReq, err error) { arr, err := r.ReadN(14) if err != nil { err = fmt.Errorf("read req: %s", err) return } return UnpackListCumulativePeriodsReq(arr), nil } func UnpackListCumulativePeriodsReq(arr []byte) (m ListCumulativePeriodsReq) { m.MetricID = bin.GetUint32(arr[0:]) m.Since = TimeBound{ Year: int(bin.GetUint16(arr[4:])), Month: time.Month(arr[6]), Day: int(arr[7]), } m.Until = TimeBound{ Year: int(bin.GetUint16(arr[8:])), Month: time.Month(arr[10]), Day: int(arr[11]), } m.GroupBy = diploma.GroupBy(arr[12]) m.FirstHourOfDay = int(arr[13]) return }